From 117e59e0284d2e853d016242af6390e91c996935 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 26 Jan 2023 21:46:02 +0700 Subject: [PATCH] NetworkedStringInput --- .../mc/otm/client/screen/HoloSignScreen.kt | 25 ++--------- .../client/screen/panels/TextInputPanel.kt | 17 +++++-- .../panels/buttons/CheckBoxInputPanel.kt | 2 +- .../panels/input/NetworkedStringInputPanel.kt | 45 +++++++++++++++++++ .../dbotthepony/mc/otm/menu/HoloSignMenu.kt | 15 +------ .../ru/dbotthepony/mc/otm/menu/MatteryMenu.kt | 2 + .../dbotthepony/mc/otm/menu/StorageBusMenu.kt | 3 +- .../mc/otm/menu/StorageExporterMenu.kt | 3 +- .../mc/otm/menu/StorageImporterMenu.kt | 3 +- .../otm/menu/input/AbstractNetworkedInput.kt | 12 ++++- .../otm/menu/input/NetworkedBooleanInput.kt | 2 +- .../mc/otm/menu/input/NetworkedStringInput.kt | 13 ++++++ .../mc/otm/network/FieldSynchronizer.kt | 3 ++ 13 files changed, 101 insertions(+), 44 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkedStringInputPanel.kt create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/NetworkedStringInput.kt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/HoloSignScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/HoloSignScreen.kt index b2742e0f3..bedffd2d8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/HoloSignScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/HoloSignScreen.kt @@ -5,6 +5,7 @@ import net.minecraft.world.entity.player.Inventory import ru.dbotthepony.mc.otm.client.screen.panels.Dock import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel import ru.dbotthepony.mc.otm.client.screen.panels.TextInputPanel +import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkedStringInputPanel import ru.dbotthepony.mc.otm.menu.HoloSignMenu import ru.dbotthepony.mc.otm.milliTime @@ -12,27 +13,9 @@ class HoloSignScreen(menu: HoloSignMenu, inventory: Inventory, title: Component) override fun makeMainFrame(): FramePanel> { val frame = FramePanel(this, null, 0f, 0f, 200f, 200f, getTitle()) - object : TextInputPanel(this@HoloSignScreen, frame) { - init { - dock = Dock.FILL - multiLine = true - } - - private var lastChanges = 0L - - override fun onTextChanged(old: String, new: String) { - lastChanges = milliTime + 1000L - menu.textInput.input(new) - } - - override fun tick() { - super.tick() - - if (milliTime >= lastChanges) { - text = menu.text - } - } - } + val input = NetworkedStringInputPanel(this, frame, backend = menu.text) + input.dock = Dock.FILL + input.multiLine = true return frame } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/TextInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/TextInputPanel.kt index 7d2620312..286b6c9cd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/TextInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/TextInputPanel.kt @@ -138,9 +138,10 @@ open class TextInputPanel( var cursorLine = 0 var cursorCharacter = 0 - var textColor = RGBAColor.WHITE - var cursorColor = RGBAColor.GREEN - var backgroundColor = RGBAColor.BLACK + open var textColor = RGBAColor.WHITE + open var cursorColor = RGBAColor.GREEN + open var backgroundColor = RGBAColor.BLACK + open var isActive = true private var oldText = ArrayList() private var textCache: String? = null @@ -626,7 +627,7 @@ open class TextInputPanel( } override fun keyPressedInternal(key: Int, scancode: Int, mods: Int): Boolean { - if (key == InputConstants.KEY_ESCAPE) { + if (key == InputConstants.KEY_ESCAPE || !isActive) { killFocus() return true } @@ -967,6 +968,11 @@ open class TextInputPanel( } override fun charTypedInternal(codepoint: Char, mods: Int): Boolean { + if (!isActive) { + killFocus() + return true + } + wipeSelection() if (!multiLine) @@ -1117,6 +1123,9 @@ open class TextInputPanel( protected set override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { + if (!isActive) + return true + selections.clear() requestFocus() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/buttons/CheckBoxInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/buttons/CheckBoxInputPanel.kt index 7e705b038..016d91545 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/buttons/CheckBoxInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/buttons/CheckBoxInputPanel.kt @@ -23,6 +23,6 @@ open class CheckBoxInputPanel @JvmOverloads constructor( set(value) {} override fun onClick() { - widget.userInput(!checked, minecraft.player) + widget.input(!checked, minecraft.player) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkedStringInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkedStringInputPanel.kt new file mode 100644 index 000000000..b21bd5682 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkedStringInputPanel.kt @@ -0,0 +1,45 @@ +package ru.dbotthepony.mc.otm.client.screen.panels.input + +import net.minecraft.client.gui.screens.Screen +import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel +import ru.dbotthepony.mc.otm.client.screen.panels.TextInputPanel +import ru.dbotthepony.mc.otm.menu.input.AbstractNetworkedInput +import ru.dbotthepony.mc.otm.menu.input.NetworkedStringInput +import ru.dbotthepony.mc.otm.milliTime + +open class NetworkedStringInputPanel( + screen: S, + parent: EditablePanel<*>?, + val backend: AbstractNetworkedInput, + x: Float = 0f, + y: Float = 0f, + width: Float = 60f, + height: Float = 11f, +) : TextInputPanel(screen, parent, x, y, width, height) { + override var isActive: Boolean + get() = backend.checkClient() + set(value) {} + + override fun onFocusChanged(new: Boolean, old: Boolean) { + super.onFocusChanged(new, old) + + if (new && !backend.checkClient()) { + killFocus() + } + } + + private var lastChanges = 0L + + override fun onTextChanged(old: String, new: String) { + lastChanges = milliTime + 1000L + backend.clientInput(new) + } + + override fun tick() { + super.tick() + + if (milliTime >= lastChanges) { + text = backend.value + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/HoloSignMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/HoloSignMenu.kt index 0d6dba642..babf9e1d0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/HoloSignMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/HoloSignMenu.kt @@ -4,6 +4,7 @@ import net.minecraft.world.entity.player.Inventory import net.minecraft.world.inventory.Slot import ru.dbotthepony.mc.otm.block.entity.decorative.HoloSignBlockEntity import ru.dbotthepony.mc.otm.core.util.BinaryStringCodec +import ru.dbotthepony.mc.otm.menu.input.NetworkedStringInput import ru.dbotthepony.mc.otm.registry.MMenus class HoloSignMenu @JvmOverloads constructor( @@ -11,20 +12,8 @@ class HoloSignMenu @JvmOverloads constructor( inventory: Inventory, tile: HoloSignBlockEntity? = null ) : MatteryMenu(MMenus.HOLO_SIGN, containerId, inventory, tile) { - var text by mSynchronizer.string(name = "text") - - val textInput = PlayerInput(BinaryStringCodec) { - if (tile is HoloSignBlockEntity) - tile.text = it - } + val text = if (tile != null) NetworkedStringInput(this, tile::text) else NetworkedStringInput(this).asClient() override val storageSlots: Collection get() = listOf() - - override fun broadcastChanges() { - super.broadcastChanges() - - if (tile is HoloSignBlockEntity) - text = tile.text - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt index d5b09478f..fb1734cec 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -23,6 +23,7 @@ import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot import ru.dbotthepony.mc.otm.core.util.BigDecimalValueCodec +import ru.dbotthepony.mc.otm.core.util.BinaryStringCodec import ru.dbotthepony.mc.otm.core.util.BooleanValueCodec import ru.dbotthepony.mc.otm.core.util.IStreamCodec import ru.dbotthepony.mc.otm.core.util.NullValueCodec @@ -123,6 +124,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor( fun bigDecimalInput(allowSpectators: Boolean = false, handler: (BigDecimal) -> Unit) = PlayerInput(BigDecimalValueCodec, allowSpectators, handler) fun booleanInput(allowSpectators: Boolean = false, handler: (Boolean) -> Unit) = PlayerInput(BooleanValueCodec, allowSpectators, handler) + fun stringInput(allowSpectators: Boolean = false, handler: (String) -> Unit) = PlayerInput(BinaryStringCodec, allowSpectators, handler) /** * inventory + exosuit + hotbar (in this order) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageBusMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageBusMenu.kt index 56d8a394a..1ba27a8b0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageBusMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageBusMenu.kt @@ -23,7 +23,8 @@ class StorageBusMenu @JvmOverloads constructor( busFilterState = NetworkedBooleanInput(this, tile.filter::isWhitelist) } else { busFilterSlots = addFilterSlots(StorageBusBlockEntity.MAX_FILTERS) - busFilterState = NetworkedBooleanInput(this).asClient() + busFilterState = NetworkedBooleanInput(this) + busFilterState.asClient() } addInventorySlots() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageExporterMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageExporterMenu.kt index 6902e798e..adb914d72 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageExporterMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageExporterMenu.kt @@ -23,7 +23,8 @@ class StorageExporterMenu @JvmOverloads constructor( busFilterState = NetworkedBooleanInput(this, tile.filter::isWhitelist) } else { busFilterSlots = addFilterSlots(StorageExporterBlockEntity.MAX_FILTERS) - busFilterState = NetworkedBooleanInput(this).asClient() + busFilterState = NetworkedBooleanInput(this) + busFilterState.asClient() } addInventorySlots() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageImporterMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageImporterMenu.kt index b821aaaa6..28372779a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageImporterMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageImporterMenu.kt @@ -23,7 +23,8 @@ class StorageImporterMenu @JvmOverloads constructor( busFilterState = NetworkedBooleanInput(this, tile.filter::isWhitelist) } else { busFilterSlots = addFilterSlots(StorageImporterBlockEntity.MAX_FILTERS) - busFilterState = NetworkedBooleanInput(this).asClient() + busFilterState = NetworkedBooleanInput(this) + busFilterState.asClient() } addInventorySlots() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractNetworkedInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractNetworkedInput.kt index 567fbaf7c..f37129057 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractNetworkedInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractNetworkedInput.kt @@ -1,6 +1,7 @@ package ru.dbotthepony.mc.otm.menu.input import net.minecraft.world.entity.player.Player +import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.menu.MatteryMenu import kotlin.reflect.KMutableProperty0 @@ -42,7 +43,7 @@ abstract class AbstractNetworkedInput { return this } - fun userInput(newValue: V, ply: Player? = null) { + fun input(newValue: V, ply: Player? = null) { if (isClient) { input.checkedInput(newValue, ply) } else { @@ -50,4 +51,13 @@ abstract class AbstractNetworkedInput { } } + fun clientInput(newValue: V) { + if (isClient) { + input.checkedInput(newValue, minecraft.player) + } + } + + fun checkClient(): Boolean { + return input.allowSpectators || minecraft.player?.isSpectator == false + } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/NetworkedBooleanInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/NetworkedBooleanInput.kt index 63fb35eb9..676636e0b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/NetworkedBooleanInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/NetworkedBooleanInput.kt @@ -13,6 +13,6 @@ class NetworkedBooleanInput(menu: MatteryMenu) : AbstractNetworkedInput } fun switchValue(ply: Player? = null) { - userInput(!value, ply) + input(!value, ply) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/NetworkedStringInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/NetworkedStringInput.kt new file mode 100644 index 000000000..de365c103 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/NetworkedStringInput.kt @@ -0,0 +1,13 @@ +package ru.dbotthepony.mc.otm.menu.input + +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import kotlin.reflect.KMutableProperty0 + +class NetworkedStringInput(menu: MatteryMenu) : AbstractNetworkedInput() { + override val input = menu.stringInput { consumer?.invoke(it.replace('\u0000', ' ')) } + override val value by menu.mSynchronizer.string(getter = { supplier?.invoke() ?: "" }) + + constructor(menu: MatteryMenu, state: KMutableProperty0) : this(menu) { + with(state) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt index 9ac6c20c1..258c199af 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/FieldSynchronizer.kt @@ -171,6 +171,7 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa fun fraction(getter: () -> Decimal, name: String = nextFieldName()) = ComputedField(getter, ImpreciseFractionValueCodec, name) fun bigDecimal(getter: () -> BigDecimal, name: String = nextFieldName()) = ComputedField(getter, BigDecimalValueCodec, name) fun item(getter: () -> ItemStack, name: String = nextFieldName()) = ComputedField(getter, ItemStackValueCodec, name) + fun string(getter: () -> String, name: String = nextFieldName()) = ComputedField(getter, BinaryStringCodec, name) fun byte(getter: KProperty0, name: String = nextFieldName()) = ComputedField(getter, ByteValueCodec, name) fun bool(getter: KProperty0, name: String = nextFieldName()) = ComputedField(getter, BooleanValueCodec, name) @@ -185,6 +186,7 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa fun fraction(getter: KProperty0, name: String = nextFieldName()) = ComputedField(getter, ImpreciseFractionValueCodec, name) fun bigDecimal(getter: KProperty0, name: String = nextFieldName()) = ComputedField(getter, BigDecimalValueCodec, name) fun item(getter: KProperty0, name: String = nextFieldName()) = ComputedField(getter, ItemStackValueCodec, name) + fun string(getter: KProperty0, name: String = nextFieldName()) = ComputedField(getter, BinaryStringCodec, name) fun byte(getter: Supplier, name: String = nextFieldName()) = ComputedField(getter::get, ByteValueCodec, name) fun bool(getter: Supplier, name: String = nextFieldName()) = ComputedField(getter::get, BooleanValueCodec, name) @@ -199,6 +201,7 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa fun fraction(getter: Supplier, name: String = nextFieldName()) = ComputedField(getter::get, ImpreciseFractionValueCodec, name) fun bigDecimal(getter: Supplier, name: String = nextFieldName()) = ComputedField(getter::get, BigDecimalValueCodec, name) fun item(getter: Supplier, name: String = nextFieldName()) = ComputedField(getter::get, ItemStackValueCodec, name) + fun string(getter: Supplier, name: String = nextFieldName()) = ComputedField(getter::get, BinaryStringCodec, name) fun > enum(type: Class, getter: () -> T, name: String = nextFieldName()) = ComputedField(getter, EnumValueCodec(type), name) inline fun > enum(noinline getter: () -> T, name: String = nextFieldName()) = ComputedField(getter, EnumValueCodec(T::class.java), name)