Add edit backpacks button to /firm storage
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
|
@file:OptIn(ExperimentalContracts::class)
|
||||||
|
|
||||||
package moe.nea.firmament.features.inventory.storageoverlay
|
package moe.nea.firmament.features.inventory.storageoverlay
|
||||||
|
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.contract
|
||||||
import net.minecraft.client.gui.screen.Screen
|
import net.minecraft.client.gui.screen.Screen
|
||||||
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
|
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
|
||||||
import net.minecraft.screen.GenericContainerScreenHandler
|
import net.minecraft.screen.GenericContainerScreenHandler
|
||||||
@@ -39,6 +41,9 @@ sealed interface StorageBackingHandle {
|
|||||||
* selection screen.
|
* selection screen.
|
||||||
*/
|
*/
|
||||||
fun fromScreen(screen: Screen?): StorageBackingHandle? {
|
fun fromScreen(screen: Screen?): StorageBackingHandle? {
|
||||||
|
contract {
|
||||||
|
returnsNotNull() implies (screen != null)
|
||||||
|
}
|
||||||
if (screen == null) return null
|
if (screen == null) return null
|
||||||
if (screen !is GenericContainerScreen) return null
|
if (screen !is GenericContainerScreen) return null
|
||||||
val title = screen.title.unformattedString
|
val title = screen.title.unformattedString
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
package moe.nea.firmament.features.inventory.storageoverlay
|
package moe.nea.firmament.features.inventory.storageoverlay
|
||||||
|
|
||||||
import java.util.SortedMap
|
import java.util.SortedMap
|
||||||
@@ -22,133 +20,134 @@ import moe.nea.firmament.util.data.ProfileSpecificDataHolder
|
|||||||
object StorageOverlay : FirmamentFeature {
|
object StorageOverlay : FirmamentFeature {
|
||||||
|
|
||||||
|
|
||||||
object Data : ProfileSpecificDataHolder<StorageData>(serializer(), "storage-data", ::StorageData)
|
object Data : ProfileSpecificDataHolder<StorageData>(serializer(), "storage-data", ::StorageData)
|
||||||
|
|
||||||
override val identifier: String
|
override val identifier: String
|
||||||
get() = "storage-overlay"
|
get() = "storage-overlay"
|
||||||
|
|
||||||
object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
|
object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
|
||||||
val alwaysReplace by toggle("always-replace") { true }
|
val alwaysReplace by toggle("always-replace") { true }
|
||||||
val columns by integer("rows", 1, 10) { 3 }
|
val columns by integer("rows", 1, 10) { 3 }
|
||||||
val scrollSpeed by integer("scroll-speed", 1, 50) { 10 }
|
val scrollSpeed by integer("scroll-speed", 1, 50) { 10 }
|
||||||
val inverseScroll by toggle("inverse-scroll") { false }
|
val inverseScroll by toggle("inverse-scroll") { false }
|
||||||
val padding by integer("padding", 1, 20) { 5 }
|
val padding by integer("padding", 1, 20) { 5 }
|
||||||
val margin by integer("margin", 1, 60) { 20 }
|
val margin by integer("margin", 1, 60) { 20 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun adjustScrollSpeed(amount: Double): Double {
|
fun adjustScrollSpeed(amount: Double): Double {
|
||||||
return amount * TConfig.scrollSpeed * (if (TConfig.inverseScroll) 1 else -1)
|
return amount * TConfig.scrollSpeed * (if (TConfig.inverseScroll) 1 else -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val config: TConfig
|
override val config: TConfig
|
||||||
get() = TConfig
|
get() = TConfig
|
||||||
|
|
||||||
var lastStorageOverlay: StorageOverviewScreen? = null
|
var lastStorageOverlay: StorageOverviewScreen? = null
|
||||||
var skipNextStorageOverlayBackflip = false
|
var skipNextStorageOverlayBackflip = false
|
||||||
var currentHandler: StorageBackingHandle? = null
|
var currentHandler: StorageBackingHandle? = null
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
fun onTick(event: TickEvent) {
|
fun onTick(event: TickEvent) {
|
||||||
rememberContent(currentHandler ?: return)
|
rememberContent(currentHandler ?: return)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
fun onClick(event: SlotClickEvent) {
|
fun onClick(event: SlotClickEvent) {
|
||||||
if (lastStorageOverlay != null && event.slot.inventory !is PlayerInventory && event.slot.index < 9
|
if (lastStorageOverlay != null && event.slot.inventory !is PlayerInventory && event.slot.index < 9
|
||||||
&& event.stack.item != Items.BLACK_STAINED_GLASS_PANE
|
&& event.stack.item != Items.BLACK_STAINED_GLASS_PANE
|
||||||
) {
|
) {
|
||||||
skipNextStorageOverlayBackflip = true
|
skipNextStorageOverlayBackflip = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
fun onScreenChange(it: ScreenChangeEvent) {
|
fun onScreenChange(it: ScreenChangeEvent) {
|
||||||
if (it.old == null && it.new == null) return
|
if (it.old == null && it.new == null) return
|
||||||
val storageOverlayScreen = it.old as? StorageOverlayScreen
|
val storageOverlayScreen = it.old as? StorageOverlayScreen
|
||||||
?: ((it.old as? HandledScreen<*>)?.customGui as? StorageOverlayCustom)?.overview
|
?: ((it.old as? HandledScreen<*>)?.customGui as? StorageOverlayCustom)?.overview
|
||||||
var storageOverviewScreen = it.old as? StorageOverviewScreen
|
var storageOverviewScreen = it.old as? StorageOverviewScreen
|
||||||
val screen = it.new as? GenericContainerScreen
|
val screen = it.new as? GenericContainerScreen
|
||||||
val oldHandler = currentHandler
|
val oldHandler = currentHandler
|
||||||
currentHandler = StorageBackingHandle.fromScreen(screen)
|
currentHandler = StorageBackingHandle.fromScreen(screen)
|
||||||
rememberContent(currentHandler)
|
rememberContent(currentHandler)
|
||||||
if (storageOverviewScreen != null && oldHandler is StorageBackingHandle.HasBackingScreen) {
|
if (storageOverviewScreen != null && oldHandler is StorageBackingHandle.HasBackingScreen) {
|
||||||
val player = MC.player
|
val player = MC.player
|
||||||
assert(player != null)
|
assert(player != null)
|
||||||
player?.networkHandler?.sendPacket(CloseHandledScreenC2SPacket(oldHandler.handler.syncId))
|
player?.networkHandler?.sendPacket(CloseHandledScreenC2SPacket(oldHandler.handler.syncId))
|
||||||
if (player?.currentScreenHandler === oldHandler.handler) {
|
if (player?.currentScreenHandler === oldHandler.handler) {
|
||||||
player.currentScreenHandler = player.playerScreenHandler
|
player.currentScreenHandler = player.playerScreenHandler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
storageOverviewScreen = storageOverviewScreen ?: lastStorageOverlay
|
storageOverviewScreen = storageOverviewScreen ?: lastStorageOverlay
|
||||||
if (it.new == null && storageOverlayScreen != null && !storageOverlayScreen.isExiting) {
|
if (it.new == null && storageOverlayScreen != null && !storageOverlayScreen.isExiting) {
|
||||||
it.overrideScreen = storageOverlayScreen
|
it.overrideScreen = storageOverlayScreen
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (storageOverviewScreen != null
|
if (storageOverviewScreen != null
|
||||||
&& !storageOverviewScreen.isClosing
|
&& !storageOverviewScreen.isClosing
|
||||||
&& (currentHandler is StorageBackingHandle.Overview || currentHandler == null)
|
&& (currentHandler is StorageBackingHandle.Overview || currentHandler == null)
|
||||||
) {
|
) {
|
||||||
if (skipNextStorageOverlayBackflip) {
|
if (skipNextStorageOverlayBackflip) {
|
||||||
skipNextStorageOverlayBackflip = false
|
skipNextStorageOverlayBackflip = false
|
||||||
} else {
|
} else {
|
||||||
it.overrideScreen = storageOverviewScreen
|
it.overrideScreen = storageOverviewScreen
|
||||||
lastStorageOverlay = null
|
lastStorageOverlay = null
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
screen ?: return
|
screen ?: return
|
||||||
screen.customGui = StorageOverlayCustom(
|
if (storageOverlayScreen?.isExiting == true) return
|
||||||
currentHandler ?: return,
|
screen.customGui = StorageOverlayCustom(
|
||||||
screen,
|
currentHandler ?: return,
|
||||||
storageOverlayScreen ?: (if (TConfig.alwaysReplace) StorageOverlayScreen() else return))
|
screen,
|
||||||
}
|
storageOverlayScreen ?: (if (TConfig.alwaysReplace) StorageOverlayScreen() else return))
|
||||||
|
}
|
||||||
|
|
||||||
fun rememberContent(handler: StorageBackingHandle?) {
|
fun rememberContent(handler: StorageBackingHandle?) {
|
||||||
handler ?: return
|
handler ?: return
|
||||||
// TODO: Make all of these functions work on deltas / updates instead of the entire contents
|
// TODO: Make all of these functions work on deltas / updates instead of the entire contents
|
||||||
val data = Data.data?.storageInventories ?: return
|
val data = Data.data?.storageInventories ?: return
|
||||||
when (handler) {
|
when (handler) {
|
||||||
is StorageBackingHandle.Overview -> rememberStorageOverview(handler, data)
|
is StorageBackingHandle.Overview -> rememberStorageOverview(handler, data)
|
||||||
is StorageBackingHandle.Page -> rememberPage(handler, data)
|
is StorageBackingHandle.Page -> rememberPage(handler, data)
|
||||||
}
|
}
|
||||||
Data.markDirty()
|
Data.markDirty()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun rememberStorageOverview(
|
private fun rememberStorageOverview(
|
||||||
handler: StorageBackingHandle.Overview,
|
handler: StorageBackingHandle.Overview,
|
||||||
data: SortedMap<StoragePageSlot, StorageData.StorageInventory>
|
data: SortedMap<StoragePageSlot, StorageData.StorageInventory>
|
||||||
) {
|
) {
|
||||||
for ((index, stack) in handler.handler.stacks.withIndex()) {
|
for ((index, stack) in handler.handler.stacks.withIndex()) {
|
||||||
// Ignore unloaded item stacks
|
// Ignore unloaded item stacks
|
||||||
if (stack.isEmpty) continue
|
if (stack.isEmpty) continue
|
||||||
val slot = StoragePageSlot.fromOverviewSlotIndex(index) ?: continue
|
val slot = StoragePageSlot.fromOverviewSlotIndex(index) ?: continue
|
||||||
val isEmpty = stack.item in StorageOverviewScreen.emptyStorageSlotItems
|
val isEmpty = stack.item in StorageOverviewScreen.emptyStorageSlotItems
|
||||||
if (slot in data) {
|
if (slot in data) {
|
||||||
if (isEmpty)
|
if (isEmpty)
|
||||||
data.remove(slot)
|
data.remove(slot)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (!isEmpty) {
|
if (!isEmpty) {
|
||||||
data[slot] = StorageData.StorageInventory(slot.defaultName(), slot, null)
|
data[slot] = StorageData.StorageInventory(slot.defaultName(), slot, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun rememberPage(
|
private fun rememberPage(
|
||||||
handler: StorageBackingHandle.Page,
|
handler: StorageBackingHandle.Page,
|
||||||
data: SortedMap<StoragePageSlot, StorageData.StorageInventory>
|
data: SortedMap<StoragePageSlot, StorageData.StorageInventory>
|
||||||
) {
|
) {
|
||||||
// TODO: FIXME: FIXME NOW: Definitely don't copy all of this every tick into persistence
|
// TODO: FIXME: FIXME NOW: Definitely don't copy all of this every tick into persistence
|
||||||
val newStacks =
|
val newStacks =
|
||||||
VirtualInventory(handler.handler.stacks.take(handler.handler.rows * 9).drop(9).map { it.copy() })
|
VirtualInventory(handler.handler.stacks.take(handler.handler.rows * 9).drop(9).map { it.copy() })
|
||||||
data.compute(handler.storagePageSlot) { slot, existingInventory ->
|
data.compute(handler.storagePageSlot) { slot, existingInventory ->
|
||||||
(existingInventory ?: StorageData.StorageInventory(
|
(existingInventory ?: StorageData.StorageInventory(
|
||||||
slot.defaultName(),
|
slot.defaultName(),
|
||||||
slot,
|
slot,
|
||||||
null
|
null
|
||||||
)).also {
|
)).also {
|
||||||
it.inventory = newStacks
|
it.inventory = newStacks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ class StorageOverlayCustom(
|
|||||||
screen.screenHandler.slots.take(screen.screenHandler.rows * 9).drop(9),
|
screen.screenHandler.slots.take(screen.screenHandler.rows * 9).drop(9),
|
||||||
Point((screen as AccessorHandledScreen).x_Firmament, screen.y_Firmament))
|
Point((screen as AccessorHandledScreen).x_Firmament, screen.y_Firmament))
|
||||||
overview.drawScrollBar(drawContext)
|
overview.drawScrollBar(drawContext)
|
||||||
|
overview.drawControls(drawContext, mouseX, mouseY)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun moveSlot(slot: Slot) {
|
override fun moveSlot(slot: Slot) {
|
||||||
|
|||||||
@@ -1,14 +1,26 @@
|
|||||||
package moe.nea.firmament.features.inventory.storageoverlay
|
package moe.nea.firmament.features.inventory.storageoverlay
|
||||||
|
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.GuiContext
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.MouseEvent
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.component.ColumnComponent
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||||
import me.shedaniel.math.Point
|
import me.shedaniel.math.Point
|
||||||
import me.shedaniel.math.Rectangle
|
import me.shedaniel.math.Rectangle
|
||||||
import net.minecraft.client.gui.DrawContext
|
import net.minecraft.client.gui.DrawContext
|
||||||
import net.minecraft.client.gui.screen.Screen
|
import net.minecraft.client.gui.screen.Screen
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||||
import net.minecraft.screen.slot.Slot
|
import net.minecraft.screen.slot.Slot
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
|
import moe.nea.firmament.gui.EmptyComponent
|
||||||
|
import moe.nea.firmament.gui.FirmButtonComponent
|
||||||
import moe.nea.firmament.util.MC
|
import moe.nea.firmament.util.MC
|
||||||
|
import moe.nea.firmament.util.MoulConfigUtils.adopt
|
||||||
|
import moe.nea.firmament.util.MoulConfigUtils.clickMCComponentInPlace
|
||||||
|
import moe.nea.firmament.util.MoulConfigUtils.drawMCComponentInPlace
|
||||||
import moe.nea.firmament.util.assertTrueOr
|
import moe.nea.firmament.util.assertTrueOr
|
||||||
|
import moe.nea.firmament.util.customgui.customGui
|
||||||
|
|
||||||
class StorageOverlayScreen : Screen(Text.literal("")) {
|
class StorageOverlayScreen : Screen(Text.literal("")) {
|
||||||
|
|
||||||
@@ -24,6 +36,9 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
val MAIN_INVENTORY_Y = 9
|
val MAIN_INVENTORY_Y = 9
|
||||||
val SCROLL_BAR_WIDTH = 8
|
val SCROLL_BAR_WIDTH = 8
|
||||||
val SCROLL_BAR_HEIGHT = 16
|
val SCROLL_BAR_HEIGHT = 16
|
||||||
|
val CONTROL_WIDTH = 70
|
||||||
|
val CONTROL_BACKGROUND_WIDTH = CONTROL_WIDTH + PLAYER_Y_INSET
|
||||||
|
val CONTROL_HEIGHT = 100
|
||||||
}
|
}
|
||||||
|
|
||||||
var isExiting: Boolean = false
|
var isExiting: Boolean = false
|
||||||
@@ -39,6 +54,8 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
val y = height / 2 - (overviewHeight + PLAYER_HEIGHT) / 2
|
val y = height / 2 - (overviewHeight + PLAYER_HEIGHT) / 2
|
||||||
val playerX = width / 2 - PLAYER_WIDTH / 2
|
val playerX = width / 2 - PLAYER_WIDTH / 2
|
||||||
val playerY = y + overviewHeight - PLAYER_Y_INSET
|
val playerY = y + overviewHeight - PLAYER_Y_INSET
|
||||||
|
val controlX = x - CONTROL_WIDTH
|
||||||
|
val controlY = y + overviewHeight / 2 - CONTROL_HEIGHT / 2
|
||||||
val totalWidth = overviewWidth
|
val totalWidth = overviewWidth
|
||||||
val totalHeight = overviewHeight - PLAYER_Y_INSET + PLAYER_HEIGHT
|
val totalHeight = overviewHeight - PLAYER_Y_INSET + PLAYER_HEIGHT
|
||||||
}
|
}
|
||||||
@@ -74,6 +91,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
val slotRowSprite = Identifier.of("firmament:storageoverlay/storage_row")
|
val slotRowSprite = Identifier.of("firmament:storageoverlay/storage_row")
|
||||||
val scrollbarBackground = Identifier.of("firmament:storageoverlay/scroll_bar_background")
|
val scrollbarBackground = Identifier.of("firmament:storageoverlay/scroll_bar_background")
|
||||||
val scrollbarKnob = Identifier.of("firmament:storageoverlay/scroll_bar_knob")
|
val scrollbarKnob = Identifier.of("firmament:storageoverlay/scroll_bar_knob")
|
||||||
|
val controllerBackground = Identifier.of("firmament:storageoverlay/storage_controls")
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
isExiting = true
|
isExiting = true
|
||||||
@@ -86,6 +104,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
drawPages(context, mouseX, mouseY, delta, null, null, Point())
|
drawPages(context, mouseX, mouseY, delta, null, null, Point())
|
||||||
drawScrollBar(context)
|
drawScrollBar(context)
|
||||||
drawPlayerInventory(context, mouseX, mouseY, delta)
|
drawPlayerInventory(context, mouseX, mouseY, delta)
|
||||||
|
drawControls(context, mouseX, mouseY)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getScrollbarPercentage(): Float {
|
fun getScrollbarPercentage(): Float {
|
||||||
@@ -106,6 +125,39 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun editPages() {
|
||||||
|
isExiting = true
|
||||||
|
val hs = MC.screen as? HandledScreen<*>
|
||||||
|
if (StorageBackingHandle.fromScreen(hs) is StorageBackingHandle.Overview) {
|
||||||
|
hs.customGui = null
|
||||||
|
} else {
|
||||||
|
MC.sendCommand("storage")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val guiContext = GuiContext(EmptyComponent())
|
||||||
|
private val knobStub = EmptyComponent()
|
||||||
|
val editButton = PanelComponent(ColumnComponent(FirmButtonComponent(TextComponent("Edit"), action = ::editPages)),
|
||||||
|
8, PanelComponent.DefaultBackgroundRenderer.TRANSPARENT)
|
||||||
|
|
||||||
|
init {
|
||||||
|
guiContext.adopt(editButton)
|
||||||
|
guiContext.adopt(knobStub)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun drawControls(context: DrawContext, mouseX: Int, mouseY: Int) {
|
||||||
|
context.drawGuiTexture(
|
||||||
|
controllerBackground,
|
||||||
|
measurements.controlX,
|
||||||
|
measurements.controlY,
|
||||||
|
CONTROL_BACKGROUND_WIDTH, CONTROL_HEIGHT)
|
||||||
|
context.drawMCComponentInPlace(
|
||||||
|
editButton,
|
||||||
|
measurements.controlX, measurements.controlY,
|
||||||
|
CONTROL_WIDTH, CONTROL_HEIGHT,
|
||||||
|
mouseX, mouseY)
|
||||||
|
}
|
||||||
|
|
||||||
fun drawBackgrounds(context: DrawContext) {
|
fun drawBackgrounds(context: DrawContext) {
|
||||||
context.drawGuiTexture(upperBackgroundSprite,
|
context.drawGuiTexture(upperBackgroundSprite,
|
||||||
measurements.x,
|
measurements.x,
|
||||||
@@ -182,7 +234,10 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
context.disableScissor()
|
context.disableScissor()
|
||||||
}
|
}
|
||||||
|
|
||||||
var knobGrabbed = false
|
|
||||||
|
var knobGrabbed: Boolean
|
||||||
|
get() = guiContext.focusedElement == knobStub
|
||||||
|
set(value) = knobStub.setFocus(value)
|
||||||
|
|
||||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||||
return mouseClicked(mouseX, mouseY, button, null)
|
return mouseClicked(mouseX, mouseY, button, null)
|
||||||
@@ -193,6 +248,12 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
knobGrabbed = false
|
knobGrabbed = false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if (clickMCComponentInPlace(editButton,
|
||||||
|
measurements.controlX, measurements.controlY,
|
||||||
|
CONTROL_WIDTH, CONTROL_HEIGHT,
|
||||||
|
mouseX.toInt(), mouseY.toInt(),
|
||||||
|
MouseEvent.Click(button, false))
|
||||||
|
) return true
|
||||||
return super.mouseReleased(mouseX, mouseY, button)
|
return super.mouseReleased(mouseX, mouseY, button)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,6 +287,12 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
knobGrabbed = true
|
knobGrabbed = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if (clickMCComponentInPlace(editButton,
|
||||||
|
measurements.controlX, measurements.controlY,
|
||||||
|
CONTROL_WIDTH, CONTROL_HEIGHT,
|
||||||
|
mouseX.toInt(), mouseY.toInt(),
|
||||||
|
MouseEvent.Click(button, true))
|
||||||
|
) return true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,6 +376,10 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
Rectangle(measurements.playerX,
|
Rectangle(measurements.playerX,
|
||||||
measurements.playerY,
|
measurements.playerY,
|
||||||
PLAYER_WIDTH,
|
PLAYER_WIDTH,
|
||||||
PLAYER_HEIGHT))
|
PLAYER_HEIGHT),
|
||||||
|
Rectangle(measurements.controlX,
|
||||||
|
measurements.controlY,
|
||||||
|
CONTROL_WIDTH,
|
||||||
|
CONTROL_HEIGHT))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/main/kotlin/gui/EmptyComponent.kt
Normal file
17
src/main/kotlin/gui/EmptyComponent.kt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package moe.nea.firmament.gui
|
||||||
|
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.GuiComponent
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
|
||||||
|
|
||||||
|
class EmptyComponent : GuiComponent() {
|
||||||
|
override fun getWidth(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getHeight(): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(context: GuiImmediateContext) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
|
|
||||||
|
|
||||||
package moe.nea.firmament.util
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
|
import io.github.notenoughupdates.moulconfig.common.IMinecraft
|
||||||
import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
|
import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
|
||||||
import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
|
import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.GuiComponent
|
||||||
import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
|
import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
|
||||||
import io.github.notenoughupdates.moulconfig.gui.GuiContext
|
import io.github.notenoughupdates.moulconfig.gui.GuiContext
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.MouseEvent
|
||||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||||
|
import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
|
||||||
import io.github.notenoughupdates.moulconfig.xml.ChildCount
|
import io.github.notenoughupdates.moulconfig.xml.ChildCount
|
||||||
import io.github.notenoughupdates.moulconfig.xml.XMLContext
|
import io.github.notenoughupdates.moulconfig.xml.XMLContext
|
||||||
import io.github.notenoughupdates.moulconfig.xml.XMLGuiLoader
|
import io.github.notenoughupdates.moulconfig.xml.XMLGuiLoader
|
||||||
@@ -19,6 +22,7 @@ import me.shedaniel.math.Color
|
|||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
import net.minecraft.client.gui.DrawContext
|
||||||
import net.minecraft.client.gui.screen.Screen
|
import net.minecraft.client.gui.screen.Screen
|
||||||
import moe.nea.firmament.gui.BarComponent
|
import moe.nea.firmament.gui.BarComponent
|
||||||
import moe.nea.firmament.gui.FirmButtonComponent
|
import moe.nea.firmament.gui.FirmButtonComponent
|
||||||
@@ -26,205 +30,254 @@ import moe.nea.firmament.gui.FirmHoverComponent
|
|||||||
import moe.nea.firmament.gui.FixedComponent
|
import moe.nea.firmament.gui.FixedComponent
|
||||||
import moe.nea.firmament.gui.ImageComponent
|
import moe.nea.firmament.gui.ImageComponent
|
||||||
import moe.nea.firmament.gui.TickComponent
|
import moe.nea.firmament.gui.TickComponent
|
||||||
|
import moe.nea.firmament.util.render.isUntranslatedGuiDrawContext
|
||||||
|
|
||||||
object MoulConfigUtils {
|
object MoulConfigUtils {
|
||||||
val firmUrl = "http://firmament.nea.moe/moulconfig"
|
val firmUrl = "http://firmament.nea.moe/moulconfig"
|
||||||
val universe = XMLUniverse.getDefaultUniverse().also { uni ->
|
val universe = XMLUniverse.getDefaultUniverse().also { uni ->
|
||||||
uni.registerMapper(java.awt.Color::class.java) {
|
uni.registerMapper(java.awt.Color::class.java) {
|
||||||
if (it.startsWith("#")) {
|
if (it.startsWith("#")) {
|
||||||
val hexString = it.substring(1)
|
val hexString = it.substring(1)
|
||||||
val hex = hexString.toInt(16)
|
val hex = hexString.toInt(16)
|
||||||
if (hexString.length == 6) {
|
if (hexString.length == 6) {
|
||||||
return@registerMapper java.awt.Color(hex)
|
return@registerMapper java.awt.Color(hex)
|
||||||
}
|
}
|
||||||
if (hexString.length == 8) {
|
if (hexString.length == 8) {
|
||||||
return@registerMapper java.awt.Color(hex, true)
|
return@registerMapper java.awt.Color(hex, true)
|
||||||
}
|
}
|
||||||
error("Hexcolor $it needs to be exactly 6 or 8 hex digits long")
|
error("Hexcolor $it needs to be exactly 6 or 8 hex digits long")
|
||||||
}
|
}
|
||||||
return@registerMapper java.awt.Color(it.toInt(), true)
|
return@registerMapper java.awt.Color(it.toInt(), true)
|
||||||
}
|
}
|
||||||
uni.registerMapper(Color::class.java) {
|
uni.registerMapper(Color::class.java) {
|
||||||
val color = uni.mapXMLObject(it, java.awt.Color::class.java)
|
val color = uni.mapXMLObject(it, java.awt.Color::class.java)
|
||||||
Color.ofRGBA(color.red, color.green, color.blue, color.alpha)
|
Color.ofRGBA(color.red, color.green, color.blue, color.alpha)
|
||||||
}
|
}
|
||||||
uni.registerLoader(object : XMLGuiLoader.Basic<BarComponent> {
|
uni.registerLoader(object : XMLGuiLoader.Basic<BarComponent> {
|
||||||
override fun getName(): QName {
|
override fun getName(): QName {
|
||||||
return QName(firmUrl, "Bar")
|
return QName(firmUrl, "Bar")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createInstance(context: XMLContext<*>, element: Element): BarComponent {
|
override fun createInstance(context: XMLContext<*>, element: Element): BarComponent {
|
||||||
return BarComponent(
|
return BarComponent(
|
||||||
context.getPropertyFromAttribute(element, QName("progress"), Double::class.java)!!,
|
context.getPropertyFromAttribute(element, QName("progress"), Double::class.java)!!,
|
||||||
context.getPropertyFromAttribute(element, QName("total"), Double::class.java)!!,
|
context.getPropertyFromAttribute(element, QName("total"), Double::class.java)!!,
|
||||||
context.getPropertyFromAttribute(element, QName("fillColor"), Color::class.java)!!.get(),
|
context.getPropertyFromAttribute(element, QName("fillColor"), Color::class.java)!!.get(),
|
||||||
context.getPropertyFromAttribute(element, QName("emptyColor"), Color::class.java)!!.get(),
|
context.getPropertyFromAttribute(element, QName("emptyColor"), Color::class.java)!!.get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChildCount(): ChildCount {
|
override fun getChildCount(): ChildCount {
|
||||||
return ChildCount.NONE
|
return ChildCount.NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttributeNames(): Map<String, Boolean> {
|
override fun getAttributeNames(): Map<String, Boolean> {
|
||||||
return mapOf("progress" to true, "total" to true, "emptyColor" to true, "fillColor" to true)
|
return mapOf("progress" to true, "total" to true, "emptyColor" to true, "fillColor" to true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
uni.registerLoader(object : XMLGuiLoader.Basic<FirmHoverComponent> {
|
uni.registerLoader(object : XMLGuiLoader.Basic<FirmHoverComponent> {
|
||||||
override fun createInstance(context: XMLContext<*>, element: Element): FirmHoverComponent {
|
override fun createInstance(context: XMLContext<*>, element: Element): FirmHoverComponent {
|
||||||
return FirmHoverComponent(
|
return FirmHoverComponent(
|
||||||
context.getChildFragment(element),
|
context.getChildFragment(element),
|
||||||
context.getPropertyFromAttribute(element, QName("lines"), List::class.java) as Supplier<List<String>>,
|
context.getPropertyFromAttribute(element,
|
||||||
context.getPropertyFromAttribute(element, QName("delay"), Duration::class.java, 0.6.seconds),
|
QName("lines"),
|
||||||
)
|
List::class.java) as Supplier<List<String>>,
|
||||||
}
|
context.getPropertyFromAttribute(element, QName("delay"), Duration::class.java, 0.6.seconds),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getName(): QName {
|
override fun getName(): QName {
|
||||||
return QName(firmUrl, "Hover")
|
return QName(firmUrl, "Hover")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChildCount(): ChildCount {
|
override fun getChildCount(): ChildCount {
|
||||||
return ChildCount.ONE
|
return ChildCount.ONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttributeNames(): Map<String, Boolean> {
|
override fun getAttributeNames(): Map<String, Boolean> {
|
||||||
return mapOf(
|
return mapOf(
|
||||||
"lines" to true,
|
"lines" to true,
|
||||||
"delay" to false,
|
"delay" to false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
uni.registerLoader(object : XMLGuiLoader.Basic<FirmButtonComponent> {
|
uni.registerLoader(object : XMLGuiLoader.Basic<FirmButtonComponent> {
|
||||||
override fun getName(): QName {
|
override fun getName(): QName {
|
||||||
return QName(firmUrl, "Button")
|
return QName(firmUrl, "Button")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createInstance(context: XMLContext<*>, element: Element): FirmButtonComponent {
|
override fun createInstance(context: XMLContext<*>, element: Element): FirmButtonComponent {
|
||||||
return FirmButtonComponent(
|
return FirmButtonComponent(
|
||||||
context.getChildFragment(element),
|
context.getChildFragment(element),
|
||||||
context.getPropertyFromAttribute(element, QName("enabled"), Boolean::class.java)
|
context.getPropertyFromAttribute(element, QName("enabled"), Boolean::class.java)
|
||||||
?: GetSetter.constant(true),
|
?: GetSetter.constant(true),
|
||||||
context.getPropertyFromAttribute(element, QName("noBackground"), Boolean::class.java, false),
|
context.getPropertyFromAttribute(element, QName("noBackground"), Boolean::class.java, false),
|
||||||
context.getMethodFromAttribute(element, QName("onClick")),
|
context.getMethodFromAttribute(element, QName("onClick")),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChildCount(): ChildCount {
|
override fun getChildCount(): ChildCount {
|
||||||
return ChildCount.ONE
|
return ChildCount.ONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttributeNames(): Map<String, Boolean> {
|
override fun getAttributeNames(): Map<String, Boolean> {
|
||||||
return mapOf("onClick" to true, "enabled" to false, "noBackground" to false)
|
return mapOf("onClick" to true, "enabled" to false, "noBackground" to false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
uni.registerLoader(object : XMLGuiLoader.Basic<ImageComponent> {
|
uni.registerLoader(object : XMLGuiLoader.Basic<ImageComponent> {
|
||||||
override fun createInstance(context: XMLContext<*>, element: Element): ImageComponent {
|
override fun createInstance(context: XMLContext<*>, element: Element): ImageComponent {
|
||||||
return ImageComponent(
|
return ImageComponent(
|
||||||
context.getPropertyFromAttribute(element, QName("width"), Int::class.java)!!.get(),
|
context.getPropertyFromAttribute(element, QName("width"), Int::class.java)!!.get(),
|
||||||
context.getPropertyFromAttribute(element, QName("height"), Int::class.java)!!.get(),
|
context.getPropertyFromAttribute(element, QName("height"), Int::class.java)!!.get(),
|
||||||
context.getPropertyFromAttribute(element, QName("resource"), MyResourceLocation::class.java)!!,
|
context.getPropertyFromAttribute(element, QName("resource"), MyResourceLocation::class.java)!!,
|
||||||
context.getPropertyFromAttribute(element, QName("u1"), Float::class.java, 0f),
|
context.getPropertyFromAttribute(element, QName("u1"), Float::class.java, 0f),
|
||||||
context.getPropertyFromAttribute(element, QName("u2"), Float::class.java, 1f),
|
context.getPropertyFromAttribute(element, QName("u2"), Float::class.java, 1f),
|
||||||
context.getPropertyFromAttribute(element, QName("v1"), Float::class.java, 0f),
|
context.getPropertyFromAttribute(element, QName("v1"), Float::class.java, 0f),
|
||||||
context.getPropertyFromAttribute(element, QName("v2"), Float::class.java, 1f),
|
context.getPropertyFromAttribute(element, QName("v2"), Float::class.java, 1f),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getName(): QName {
|
override fun getName(): QName {
|
||||||
return QName(firmUrl, "Image")
|
return QName(firmUrl, "Image")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChildCount(): ChildCount {
|
override fun getChildCount(): ChildCount {
|
||||||
return ChildCount.NONE
|
return ChildCount.NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttributeNames(): Map<String, Boolean> {
|
override fun getAttributeNames(): Map<String, Boolean> {
|
||||||
return mapOf(
|
return mapOf(
|
||||||
"width" to true, "height" to true,
|
"width" to true, "height" to true,
|
||||||
"resource" to true,
|
"resource" to true,
|
||||||
"u1" to false,
|
"u1" to false,
|
||||||
"u2" to false,
|
"u2" to false,
|
||||||
"v1" to false,
|
"v1" to false,
|
||||||
"v2" to false,
|
"v2" to false,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
uni.registerLoader(object : XMLGuiLoader.Basic<TickComponent> {
|
uni.registerLoader(object : XMLGuiLoader.Basic<TickComponent> {
|
||||||
override fun createInstance(context: XMLContext<*>, element: Element): TickComponent {
|
override fun createInstance(context: XMLContext<*>, element: Element): TickComponent {
|
||||||
return TickComponent(context.getMethodFromAttribute(element, QName("tick")))
|
return TickComponent(context.getMethodFromAttribute(element, QName("tick")))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getName(): QName {
|
override fun getName(): QName {
|
||||||
return QName(firmUrl, "Tick")
|
return QName(firmUrl, "Tick")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChildCount(): ChildCount {
|
override fun getChildCount(): ChildCount {
|
||||||
return ChildCount.NONE
|
return ChildCount.NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttributeNames(): Map<String, Boolean> {
|
override fun getAttributeNames(): Map<String, Boolean> {
|
||||||
return mapOf("tick" to true)
|
return mapOf("tick" to true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
uni.registerLoader(object : XMLGuiLoader.Basic<FixedComponent> {
|
uni.registerLoader(object : XMLGuiLoader.Basic<FixedComponent> {
|
||||||
override fun createInstance(context: XMLContext<*>, element: Element): FixedComponent {
|
override fun createInstance(context: XMLContext<*>, element: Element): FixedComponent {
|
||||||
return FixedComponent(
|
return FixedComponent(
|
||||||
context.getPropertyFromAttribute(element, QName("width"), Int::class.java)
|
context.getPropertyFromAttribute(element, QName("width"), Int::class.java)
|
||||||
?: error("Requires width specified"),
|
?: error("Requires width specified"),
|
||||||
context.getPropertyFromAttribute(element, QName("height"), Int::class.java)
|
context.getPropertyFromAttribute(element, QName("height"), Int::class.java)
|
||||||
?: error("Requires height specified"),
|
?: error("Requires height specified"),
|
||||||
context.getChildFragment(element)
|
context.getChildFragment(element)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getName(): QName {
|
override fun getName(): QName {
|
||||||
return QName(firmUrl, "Fixed")
|
return QName(firmUrl, "Fixed")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChildCount(): ChildCount {
|
override fun getChildCount(): ChildCount {
|
||||||
return ChildCount.ONE
|
return ChildCount.ONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAttributeNames(): Map<String, Boolean> {
|
override fun getAttributeNames(): Map<String, Boolean> {
|
||||||
return mapOf("width" to true, "height" to true)
|
return mapOf("width" to true, "height" to true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateXSD(
|
fun generateXSD(
|
||||||
file: File,
|
file: File,
|
||||||
namespace: String
|
namespace: String
|
||||||
) {
|
) {
|
||||||
val generator = XSDGenerator(universe, namespace)
|
val generator = XSDGenerator(universe, namespace)
|
||||||
generator.writeAll()
|
generator.writeAll()
|
||||||
generator.dumpToFile(file)
|
generator.dumpToFile(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun main(args: Array<out String>) {
|
fun main(args: Array<out String>) {
|
||||||
generateXSD(File("MoulConfig.xsd"), XMLUniverse.MOULCONFIG_XML_NS)
|
generateXSD(File("MoulConfig.xsd"), XMLUniverse.MOULCONFIG_XML_NS)
|
||||||
generateXSD(File("MoulConfig.Firmament.xsd"), firmUrl)
|
generateXSD(File("MoulConfig.Firmament.xsd"), firmUrl)
|
||||||
File("wrapper.xsd").writeText("""
|
File("wrapper.xsd").writeText("""
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
<xs:import namespace="http://notenoughupdates.org/moulconfig" schemaLocation="MoulConfig.xsd"/>
|
<xs:import namespace="http://notenoughupdates.org/moulconfig" schemaLocation="MoulConfig.xsd"/>
|
||||||
<xs:import namespace="http://firmament.nea.moe/moulconfig" schemaLocation="MoulConfig.Firmament.xsd"/>
|
<xs:import namespace="http://firmament.nea.moe/moulconfig" schemaLocation="MoulConfig.Firmament.xsd"/>
|
||||||
</xs:schema>
|
</xs:schema>
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadScreen(name: String, bindTo: Any, parent: Screen?): Screen {
|
fun loadScreen(name: String, bindTo: Any, parent: Screen?): Screen {
|
||||||
return object : GuiComponentWrapper(loadGui(name, bindTo)) {
|
return object : GuiComponentWrapper(loadGui(name, bindTo)) {
|
||||||
override fun close() {
|
override fun close() {
|
||||||
if (context.onBeforeClose() == CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE) {
|
if (context.onBeforeClose() == CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE) {
|
||||||
client!!.setScreen(parent)
|
client!!.setScreen(parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadGui(name: String, bindTo: Any): GuiContext {
|
// TODO: move this utility into moulconfig (also rework guicontext into an interface so i can make this mesh better into vanilla)
|
||||||
return GuiContext(universe.load(bindTo, MyResourceLocation("firmament", "gui/$name.xml")))
|
fun GuiContext.adopt(element: GuiComponent) = element.foldRecursive(Unit, { comp, unit -> comp.context = this })
|
||||||
}
|
|
||||||
|
fun clickMCComponentInPlace(
|
||||||
|
component: GuiComponent,
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
w: Int,
|
||||||
|
h: Int,
|
||||||
|
mouseX: Int, mouseY: Int,
|
||||||
|
mouseEvent: MouseEvent
|
||||||
|
): Boolean {
|
||||||
|
val immContext = createInPlaceFullContext(null, mouseX, mouseY)
|
||||||
|
return component.mouseEvent(mouseEvent, immContext.translated(x, y, w, h))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createInPlaceFullContext(drawContext: DrawContext?, mouseX: Int, mouseY: Int): GuiImmediateContext {
|
||||||
|
assert(drawContext?.isUntranslatedGuiDrawContext() != false)
|
||||||
|
val context = drawContext?.let(::ModernRenderContext)
|
||||||
|
?: IMinecraft.instance.provideTopLevelRenderContext()
|
||||||
|
val immContext = GuiImmediateContext(context,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
mouseX, mouseY,
|
||||||
|
mouseX, mouseY,
|
||||||
|
mouseX.toFloat(),
|
||||||
|
mouseY.toFloat())
|
||||||
|
return immContext
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DrawContext.drawMCComponentInPlace(
|
||||||
|
component: GuiComponent,
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
w: Int,
|
||||||
|
h: Int,
|
||||||
|
mouseX: Int,
|
||||||
|
mouseY: Int
|
||||||
|
) {
|
||||||
|
val immContext = createInPlaceFullContext(this, mouseX, mouseY)
|
||||||
|
matrices.push()
|
||||||
|
matrices.translate(x.toFloat(), y.toFloat(), 0F)
|
||||||
|
component.render(immContext.translated(x, y, w, h))
|
||||||
|
matrices.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun loadGui(name: String, bindTo: Any): GuiContext {
|
||||||
|
return GuiContext(universe.load(bindTo, MyResourceLocation("firmament", "gui/$name.xml")))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
|
@file:OptIn(ExperimentalContracts::class)
|
||||||
|
|
||||||
package moe.nea.firmament.util
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Less aggressive version of `require(obj != null)`, which fails in devenv but continues at runtime.
|
* Less aggressive version of `require(obj != null)`, which fails in devenv but continues at runtime.
|
||||||
*/
|
*/
|
||||||
inline fun <T : Any> assertNotNullOr(obj: T?, message: String? = null, block: () -> T): T {
|
inline fun <T : Any> assertNotNullOr(obj: T?, message: String? = null, block: () -> T): T {
|
||||||
|
contract {
|
||||||
|
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
if (message == null)
|
if (message == null)
|
||||||
assert(obj != null)
|
assert(obj != null)
|
||||||
else
|
else
|
||||||
@@ -18,6 +25,9 @@ inline fun <T : Any> assertNotNullOr(obj: T?, message: String? = null, block: ()
|
|||||||
* Less aggressive version of `require(condition)`, which fails in devenv but continues at runtime.
|
* Less aggressive version of `require(condition)`, which fails in devenv but continues at runtime.
|
||||||
*/
|
*/
|
||||||
inline fun assertTrueOr(condition: Boolean, block: () -> Unit) {
|
inline fun assertTrueOr(condition: Boolean, block: () -> Unit) {
|
||||||
|
contract {
|
||||||
|
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
assert(condition)
|
assert(condition)
|
||||||
if (!condition) block()
|
if (!condition) block()
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/main/kotlin/util/render/DrawContextExt.kt
Normal file
8
src/main/kotlin/util/render/DrawContextExt.kt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package moe.nea.firmament.util.render
|
||||||
|
|
||||||
|
import org.joml.Matrix4f
|
||||||
|
import net.minecraft.client.gui.DrawContext
|
||||||
|
|
||||||
|
fun DrawContext.isUntranslatedGuiDrawContext(): Boolean {
|
||||||
|
return (matrices.peek().positionMatrix.properties() and Matrix4f.PROPERTY_IDENTITY.toInt()) != 0
|
||||||
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
|
|
||||||
|
|
||||||
package moe.nea.firmament.util
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
fun parseDashlessUUID(dashlessUuid: String): UUID {
|
fun parseDashlessUUID(dashlessUuid: String): UUID {
|
||||||
val most = BigInteger(dashlessUuid.substring(0, 16), 16)
|
val most = BigInteger(dashlessUuid.substring(0, 16), 16)
|
||||||
val least = BigInteger(dashlessUuid.substring(16, 32), 16)
|
val least = BigInteger(dashlessUuid.substring(16, 32), 16)
|
||||||
return UUID(most.toLong(), least.toLong())
|
return UUID(most.toLong(), least.toLong())
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"gui": {
|
||||||
|
"scaling": {
|
||||||
|
"type": "nine_slice",
|
||||||
|
"width": 91,
|
||||||
|
"height": 184,
|
||||||
|
"border": 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user