diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetLocation.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetLocation.kt index e49f0e87d..85b3a3bb3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetLocation.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetLocation.kt @@ -5,7 +5,6 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters object WidgetLocation { val WIDGETS_18 = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets_18.png") - val WIDGETS_8 = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets_8.png") val MISC = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "widgets/misc"), 64f, 64f) val PATTERN_PANEL_TABS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "widgets/pattern_panel_tabs"), 64f, 32f) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets8.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets8.kt index c80c0c379..4b39a9136 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets8.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets8.kt @@ -1,33 +1,26 @@ package ru.dbotthepony.mc.otm.client.render +import net.minecraft.resources.ResourceLocation +import ru.dbotthepony.mc.otm.OverdriveThatMatters + object Widgets8 { - val GRID = SkinGrid(WidgetLocation.WIDGETS_8, 8f, 8f) + val GRID = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "widgets_8"), 64f, 32f).subGrid(8f, 8f, 64 / 8, 32 / 8) - val BUTTON_IDLE = GRID.next() - val WHITE_ARROW_DOWN = GRID.next() - val S = GRID.next() - val F = GRID.next() - val E = GRID.next() - val ONE = GRID.next() + val BUTTON_IDLE = GRID[0, 0] + val BUTTON_HOVERED = GRID[0, 1] + val BUTTON_PRESSED = GRID[0, 2] + val BUTTON_DISABLED = GRID[0, 3] - init { - GRID.jump() - } + val WHITE_ARROW_DOWN = GRID[1, 0] + val S = GRID[2, 0] + val F = GRID[3, 0] + val E = GRID[4, 0] + val ONE = GRID[5, 0] - val BUTTON_HOVERED = GRID.next() - val ARROW_SIDEWAYS = GRID.next() + val ARROW_SIDEWAYS = GRID[1, 1] + val ARROW_PAINTED_UP = GRID[1, 2] + val MINUS = GRID[1, 3] - init { - GRID.jump() - } - - val BUTTON_PRESSED = GRID.next() - val ARROW_PAINTED_UP = GRID.next() - - init { - GRID.jump() - } - - val BUTTON_DISABLED = GRID.next() - val MINUS = GRID.next() + val EXOSUIT_SHOWN = GRID[2, 1] + val EXOSUIT_HIDDEN = GRID[3, 1] } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt index a8b2ed4af..489fc4ea7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/ItemMonitorScreen.kt @@ -15,6 +15,7 @@ import ru.dbotthepony.mc.otm.client.render.Widgets8 import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel +import ru.dbotthepony.mc.otm.core.asGetterSetter import ru.dbotthepony.mc.otm.core.maxScrollDivision import ru.dbotthepony.mc.otm.core.formatReadableNumber import ru.dbotthepony.mc.otm.core.formatSiComponent @@ -127,7 +128,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp val refillPriority = SmallEnumRectangleButtonPanel(this, arrowLine, enum = ItemMonitorPlayerSettings.IngredientPriority::class.java, - prop = menu.settings::ingredientPriority, + prop = menu.settings::ingredientPriority.asGetterSetter(), defaultValue = ItemMonitorPlayerSettings.IngredientPriority.SYSTEM, onChange = { menu.sendSettingsToServer() }) @@ -149,7 +150,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp val resultTarget = SmallEnumRectangleButtonPanel(this, resultAndButtons, y = 38f, enum = ItemMonitorPlayerSettings.ResultTarget::class.java, - prop = menu.settings::resultTarget, + prop = menu.settings::resultTarget.asGetterSetter(), defaultValue = ItemMonitorPlayerSettings.ResultTarget.MIXED, onChange = { menu.sendSettingsToServer() }) @@ -160,7 +161,7 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp val craftingAmount = SmallEnumRectangleButtonPanel(this, resultAndButtons, x = 10f, y = 38f, enum = ItemMonitorPlayerSettings.Amount::class.java, - prop = menu.settings::craftingAmount, + prop = menu.settings::craftingAmount.asGetterSetter(), defaultValue = ItemMonitorPlayerSettings.Amount.STACK, onChange = { menu.sendSettingsToServer() }) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt index 89c4b7e7c..99271f525 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/ButtonPanel.kt @@ -8,9 +8,11 @@ import net.minecraft.network.chat.Component import ru.dbotthepony.mc.otm.client.playGuiClickSound import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.client.render.* +import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.RGBAColor import ru.dbotthepony.mc.otm.core.next import ru.dbotthepony.mc.otm.core.prev +import ru.dbotthepony.mc.otm.core.value import java.util.* import kotlin.collections.ArrayList import kotlin.reflect.KMutableProperty0 @@ -201,13 +203,13 @@ abstract class EnumRectangleButtonPanel>( width: Float, height: Float, val enum: Class, - val prop: KMutableProperty0, + val prop: GetterSetter, val defaultValue: T, val onChange: ((newValue: T) -> Unit)? = null, ) : RectangleButtonPanel(screen, parent, x, y, width, height, null) { private var building = true - protected val enumMapping = EnumMap>(enum) + protected val enumMapping = EnumMap>(enum) protected val tooltipMapping = EnumMap(enum) fun addTooltip(value: T, component: Component): EnumRectangleButtonPanel { @@ -246,19 +248,19 @@ abstract class EnumRectangleButtonPanel>( return missing } - fun add(value: T, skinElement: SkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { + fun add(value: T, skinElement: AbstractSkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { return add(value, skinElement to winding) } - fun add(value: T, skinElement: SkinElement, component: Component, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { + fun add(value: T, skinElement: AbstractSkinElement, component: Component, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { return add(value, component, skinElement to winding) } - fun add(value: T, component: Component, skinElement: SkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { + fun add(value: T, component: Component, skinElement: AbstractSkinElement, winding: UVWindingOrder = UVWindingOrder.NORMAL): EnumRectangleButtonPanel { return add(value, component, skinElement to winding) } - fun add(value: T, pair: Pair): EnumRectangleButtonPanel { + fun add(value: T, pair: Pair): EnumRectangleButtonPanel { check(building) { "Not building" } check(enumMapping.put(value, pair) == null) { "Already has mapping for $value" } @@ -269,7 +271,7 @@ abstract class EnumRectangleButtonPanel>( return this } - fun add(value: T, component: Component, pair: Pair): EnumRectangleButtonPanel { + fun add(value: T, component: Component, pair: Pair): EnumRectangleButtonPanel { addTooltip(value, component) return add(value, pair) } @@ -304,18 +306,18 @@ abstract class EnumRectangleButtonPanel>( override fun onClick(clickButton: Int) { when (clickButton) { InputConstants.MOUSE_BUTTON_LEFT -> { - prop.set(prop.get().next(enum.enumConstants)) + prop.value = prop.value.next(enum.enumConstants) onChange?.invoke(prop.get()) } InputConstants.MOUSE_BUTTON_RIGHT -> { - prop.set(prop.get().prev(enum.enumConstants)) + prop.value = prop.value.prev(enum.enumConstants) onChange?.invoke(prop.get()) } InputConstants.MOUSE_BUTTON_MIDDLE -> { if (prop.get() != defaultValue) { - prop.set(defaultValue) + prop.value = defaultValue onChange?.invoke(prop.get()) } } @@ -362,6 +364,37 @@ abstract class EnumRectangleButtonPanel>( } } +abstract class BooleanRectangleButtonPanel( + screen: S, + parent: EditablePanel<*>?, + x: Float = 0f, + y: Float = 0f, + width: Float, + height: Float, + val prop: GetterSetter, + val skinElementActive: AbstractSkinElement? = null, + val skinElementInactive: AbstractSkinElement? = null, + val onChange: ((newValue: Boolean) -> Unit)? = null, +) : RectangleButtonPanel(screen, parent, x, y, width, height, null) { + override fun onClick(clickButton: Int) { + if (clickButton == InputConstants.MOUSE_BUTTON_LEFT) { + val newValue = !prop.value + prop.value = newValue + onChange?.invoke(newValue) + } + } + + override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) { + super.innerRender(stack, mouseX, mouseY, partialTick) + + if (prop.value) { + skinElementActive?.render(stack, width = width, height = height) + } else { + skinElementInactive?.render(stack, width = width, height = height) + } + } +} + open class LargeRectangleButtonPanel( screen: S, parent: EditablePanel<*>?, @@ -370,7 +403,7 @@ open class LargeRectangleButtonPanel( width: Float = SIZE, height: Float = SIZE, onPress: ((clickButton: Int) -> Unit)? = null, - val skinElement: SkinElement? = null, + val skinElement: AbstractSkinElement? = null, val skinElementWinding: UVWindingOrder? = null, ) : RectangleButtonPanel(screen, parent, x, y, width, height, onPress) { final override val IDLE = Widgets18.BUTTON_IDLE @@ -401,7 +434,7 @@ open class LargeEnumRectangleButtonPanel>( width: Float = SIZE, height: Float = SIZE, enum: Class, - prop: KMutableProperty0, + prop: GetterSetter, defaultValue: T, onChange: ((newValue: T) -> Unit)? = null, ) : EnumRectangleButtonPanel(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) { @@ -415,6 +448,28 @@ open class LargeEnumRectangleButtonPanel>( } } +open class LargeBooleanRectangleButtonPanel( + screen: S, + parent: EditablePanel<*>?, + x: Float = 0f, + y: Float = 0f, + width: Float = SIZE, + height: Float = SIZE, + prop: GetterSetter, + skinElementActive: AbstractSkinElement? = null, + skinElementInactive: AbstractSkinElement? = null, + onChange: ((newValue: Boolean) -> Unit)? = null, +) : BooleanRectangleButtonPanel(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange) { + final override val IDLE = Widgets18.BUTTON_IDLE + final override val HOVERED = Widgets18.BUTTON_HOVERED + final override val PRESSED = Widgets18.BUTTON_PRESSED + final override val DISABLED = Widgets18.BUTTON_DISABLED + + companion object { + const val SIZE = 18f + } +} + open class SmallRectangleButtonPanel( screen: S, parent: EditablePanel<*>?, @@ -454,7 +509,7 @@ open class SmallEnumRectangleButtonPanel>( width: Float = SIZE, height: Float = SIZE, enum: Class, - prop: KMutableProperty0, + prop: GetterSetter, defaultValue: T, onChange: ((newValue: T) -> Unit)? = null, ) : EnumRectangleButtonPanel(screen, parent, x, y, width, height, enum, prop, defaultValue, onChange) { @@ -467,3 +522,25 @@ open class SmallEnumRectangleButtonPanel>( const val SIZE = 8f } } + +open class SmallBooleanRectangleButtonPanel( + screen: S, + parent: EditablePanel<*>?, + x: Float = 0f, + y: Float = 0f, + width: Float = SIZE, + height: Float = SIZE, + prop: GetterSetter, + skinElementActive: AbstractSkinElement? = null, + skinElementInactive: AbstractSkinElement? = null, + onChange: ((newValue: Boolean) -> Unit)? = null, +) : BooleanRectangleButtonPanel(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange) { + final override val IDLE = Widgets8.BUTTON_IDLE + final override val HOVERED = Widgets8.BUTTON_HOVERED + final override val PRESSED = Widgets8.BUTTON_PRESSED + final override val DISABLED = Widgets8.BUTTON_DISABLED + + companion object { + const val SIZE = 8f + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt index 45f58d039..86db7000e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/EntityRendererPanel.kt @@ -6,10 +6,16 @@ import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen import net.minecraft.client.gui.screens.inventory.InventoryScreen import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.player.Player +import ru.dbotthepony.mc.otm.capability.matteryPlayer +import ru.dbotthepony.mc.otm.client.render.Widgets8 import ru.dbotthepony.mc.otm.client.render.element import ru.dbotthepony.mc.otm.client.screen.ExoSuitInventoryScreen import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleRenderButton import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorLoaded +import ru.dbotthepony.mc.otm.core.asGetterOnly +import ru.dbotthepony.mc.otm.network.DisplayExosuitPacket +import ru.dbotthepony.mc.otm.network.HideExosuitPacket +import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel private fun calculateScale(width: Float, height: Float): Int { val aspectRatio = width / height @@ -49,6 +55,25 @@ class EntityRendererPanel @JvmOverloads constructor( if (entity is Player && isCosmeticArmorLoaded) { CosmeticToggleRenderButton(screen, this, x = this.width - 7f, y = this.height - 7f) } + + if (entity is Player) { + val matteryPlayer = entity.matteryPlayer + + if (matteryPlayer != null && matteryPlayer.hasExoSuit) { + SmallBooleanRectangleButtonPanel(screen, this, this.width - 2f - SmallBooleanRectangleButtonPanel.SIZE, 2f, + prop = matteryPlayer::displayExoSuit.asGetterOnly(), + skinElementActive = Widgets8.EXOSUIT_SHOWN, + skinElementInactive = Widgets8.EXOSUIT_HIDDEN, + onChange = { + if (it) { + MatteryPlayerNetworkChannel.sendToServer(DisplayExosuitPacket) + } else { + MatteryPlayerNetworkChannel.sendToServer(HideExosuitPacket) + } + } + ) + } + } } override fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) { @@ -72,10 +97,19 @@ class EntityRendererPanel @JvmOverloads constructor( override fun performLayout() { super.performLayout() - val button = children.firstOrNull { it is CosmeticToggleRenderButton } as CosmeticToggleRenderButton? ?: return + val cosButton = children.firstOrNull { it is CosmeticToggleRenderButton } as CosmeticToggleRenderButton? - button.x = this.width - 7f - button.y = this.height - 7f + if (cosButton != null) { + cosButton.x = this.width - 7f + cosButton.y = this.height - 7f + } + + val toggleButton = children.firstOrNull { it is SmallBooleanRectangleButtonPanel } as SmallBooleanRectangleButtonPanel? + + if (toggleButton != null) { + toggleButton.x = this.width - 2f - toggleButton.width + toggleButton.y = 2f + } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt new file mode 100644 index 000000000..10de8c854 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt @@ -0,0 +1,63 @@ +package ru.dbotthepony.mc.otm.core + +import java.util.function.Consumer +import java.util.function.Supplier +import kotlin.reflect.KMutableProperty0 +import kotlin.reflect.KProperty + +inline var GetterSetter.value: V + get() = get() + set(value) { accept(value) } + +@Suppress("nothing_to_inline") +inline operator fun GetterSetter.getValue(thisRef: Any, property: KProperty<*>): V { + return get() +} + +@Suppress("nothing_to_inline") +inline operator fun GetterSetter.setValue(thisRef: Any, property: KProperty<*>, value: V) { + accept(value) +} + +interface GetterSetter : Supplier, Consumer { + companion object { + fun of(getter: Supplier, setter: Consumer): GetterSetter { + return object : GetterSetter { + override fun get(): V { + return getter.get() + } + + override fun accept(t: V) { + setter.accept(t) + } + } + } + + fun of(getter: () -> V, setter: (V) -> Unit): GetterSetter { + return object : GetterSetter { + override fun get(): V { + return getter.invoke() + } + + override fun accept(t: V) { + setter.invoke(t) + } + } + } + + fun of(property: KMutableProperty0): GetterSetter { + return object : GetterSetter { + override fun get(): V { + return property.get() + } + + override fun accept(t: V) { + property.set(t) + } + } + } + } +} + +fun KMutableProperty0.asGetterSetter() = GetterSetter.of(this) +fun KMutableProperty0.asGetterOnly() = GetterSetter.of(Supplier { this.get() }, Consumer { /* do nothing */ }) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt index e237c8703..ec10ba2a9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerNetworkChannel.kt @@ -492,6 +492,24 @@ class ShockwaveEffectPacket(val pos: Vector) : MatteryPacket { } } +object DisplayExosuitPacket : MatteryPacket { + override fun write(buff: FriendlyByteBuf) {} + + override fun play(context: Supplier) { + context.packetHandled = true + context.sender?.matteryPlayer?.displayExoSuit = true + } +} + +object HideExosuitPacket : MatteryPacket { + override fun write(buff: FriendlyByteBuf) {} + + override fun play(context: Supplier) { + context.packetHandled = true + context.sender?.matteryPlayer?.displayExoSuit = false + } +} + object MatteryPlayerNetworkChannel : MatteryNetworkChannel( version = "1", name = "player" @@ -522,5 +540,8 @@ object MatteryPlayerNetworkChannel : MatteryNetworkChannel( add(GlitchPacket::class, GlitchPacket.Companion::read, PLAY_TO_CLIENT) add(ShockwaveEffectPacket::class, ShockwaveEffectPacket.Companion::read, PLAY_TO_CLIENT) + + add(DisplayExosuitPacket::class, { DisplayExosuitPacket }, PLAY_TO_SERVER) + add(HideExosuitPacket::class, { HideExosuitPacket }, PLAY_TO_SERVER) } } diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.png index bb630b4da..8144a8fa6 100644 Binary files a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.png and b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.png differ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.xcf b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.xcf index ea8990555..594d60564 100644 Binary files a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.xcf and b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets_8.xcf differ