diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/EnergyCounterScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/EnergyCounterScreen.kt index 913440b37..46955192e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/EnergyCounterScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/EnergyCounterScreen.kt @@ -82,7 +82,7 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title: val button = ButtonPanel(this, frame, 0f, 0f, 0f, 20f, TranslatableComponent("block.overdrive_that_matters.energy_counter.switch")) button.dock = Dock.TOP button.setDockMargin(4f, 0f, 4f, 0f) - button.bind { menu.switchDirection.userInput(minecraft?.player) } + button.bind { menu.switchDirection.input(null) } } val infoPanels = frame.fetchChildren() @@ -91,7 +91,7 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title: label.dock = Dock.TOP label.setDockMargin(4f, 0f, 0f, 0f) - val inputPanel = NumberInputPanel(this, frame, menu.maxIO) + val inputPanel = NetworkNumberInputPanel(this, frame, widget = menu.maxIOInput, networkValue = menu::maxIO) inputPanel.dock = Dock.TOP inputPanel.setDockMargin(4f, 0f, 4f, 0f) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/NumberInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/NetworkNumberInputPanel.kt similarity index 51% rename from src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/NumberInputPanel.kt rename to src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/NetworkNumberInputPanel.kt index 79883527b..ded232d00 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/NumberInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/NetworkNumberInputPanel.kt @@ -4,25 +4,50 @@ import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.core.TextComponent -import ru.dbotthepony.mc.otm.client.screen.MatteryScreen -import ru.dbotthepony.mc.otm.menu.widget.NumberPlayerInputWidget +import ru.dbotthepony.mc.otm.menu.MatteryMenu import java.math.BigDecimal +import java.util.function.BooleanSupplier -open class NumberInputPanel @JvmOverloads constructor( +open class NetworkNumberInputPanel @JvmOverloads constructor( screen: S, parent: EditablePanel<*>?, - val inputWidget: NumberPlayerInputWidget, + val networkValue: () -> BigDecimal, + val callback: (BigDecimal) -> Unit, + val isAvailable: BooleanSupplier = BooleanSupplier { true }, x: Float = 0f, y: Float = 0f, width: Float = 0f, height: Float = 20f, defaultText: Component = TextComponent("") ) : EditBoxPanel(screen, parent, x, y, width, height, defaultText) { + constructor( + screen: S, + parent: EditablePanel<*>?, + widget: MatteryMenu.PlayerInput, + networkValue: () -> BigDecimal, + x: Float = 0f, + y: Float = 0f, + width: Float = 0f, + height: Float = 20f, + defaultText: Component = TextComponent("") + ) : this( + screen = screen, + parent = parent, + callback = widget::input, + isAvailable = { widget.allowSpectators || minecraft.player?.isSpectator != true }, + networkValue = networkValue, + x = x, + y = y, + width = width, + height = height, + defaultText = defaultText, + ) + protected var nextUpdateFromServer = 0L protected var inputStr = "" override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { - if (inputWidget.ignoreSpectators && minecraft.player?.isSpectator == true) { + if (!isAvailable.asBoolean) { return true } @@ -33,7 +58,7 @@ open class NumberInputPanel @JvmOverloads constructor( super.tick() if (isFocused) { - if (inputWidget.ignoreSpectators && minecraft.player?.isSpectator == true) { + if (!isAvailable.asBoolean) { killFocus() return } @@ -42,14 +67,14 @@ open class NumberInputPanel @JvmOverloads constructor( } if (nextUpdateFromServer < System.currentTimeMillis()) { - getOrCreateWidget().value = inputWidget.value.toPlainString() + getOrCreateWidget().value = networkValue.invoke().toPlainString() inputStr = getOrCreateWidget().value - } else if (!inputWidget.ignoreSpectators || minecraft.player?.isSpectator != true) { + } else if (isAvailable.asBoolean) { if (inputStr != getOrCreateWidget().value) { inputStr = getOrCreateWidget().value try { - inputWidget.userInput(BigDecimal(inputStr), minecraft.player) + callback.invoke(BigDecimal(inputStr)) } catch (_: Throwable) { } } } 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 a5bfd55fa..3c2210d1f 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 @@ -3,12 +3,12 @@ package ru.dbotthepony.mc.otm.client.screen.panels.buttons import net.minecraft.client.gui.screens.Screen import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget +import ru.dbotthepony.mc.otm.menu.widget.NetworkedBooleanInput open class CheckBoxInputPanel @JvmOverloads constructor( screen: S, parent: EditablePanel<*>?, - val widget: BooleanPlayerInputWidget, + val widget: NetworkedBooleanInput, x: Float = 0f, y: Float = 0f, width: Float = REGULAR_DIMENSIONS + 120f, @@ -19,7 +19,7 @@ open class CheckBoxInputPanel @JvmOverloads constructor( set(value) {} override var isDisabled: Boolean - get() = !widget.ignoreSpectators || minecraft.player?.isSpectator == true + get() = widget.input.allowSpectators || minecraft.player?.isSpectator == true set(value) {} override fun onClick() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/buttons/CheckBoxLabelInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/buttons/CheckBoxLabelInputPanel.kt index d42d56c43..106c63ea8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/buttons/CheckBoxLabelInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/buttons/CheckBoxLabelInputPanel.kt @@ -4,12 +4,12 @@ import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.client.screen.panels.Label -import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget +import ru.dbotthepony.mc.otm.menu.widget.NetworkedBooleanInput open class CheckBoxLabelInputPanel @JvmOverloads constructor( screen: S, parent: EditablePanel<*>?, - widget: BooleanPlayerInputWidget, + widget: NetworkedBooleanInput, text: Component, x: Float = 0f, y: Float = 0f, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt index 81ee77c47..8c1487933 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt @@ -15,7 +15,7 @@ import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewProvider import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView -import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget +import ru.dbotthepony.mc.otm.menu.widget.NetworkedBooleanInput import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.storage.ITEM_STORAGE import ru.dbotthepony.mc.otm.storage.ItemStackWrapper @@ -68,15 +68,15 @@ class DriveViewerMenu @JvmOverloads constructor( val driveFilterSlots = addFilterSlots(driveFilter) - val isWhitelist = BooleanPlayerInputWidget(this) - val matchTag = BooleanPlayerInputWidget(this) - val matchNBT = BooleanPlayerInputWidget(this) + val isWhitelist = NetworkedBooleanInput(this) + val matchTag = NetworkedBooleanInput(this) + val matchNBT = NetworkedBooleanInput(this) init { if (tile == null) { - isWhitelist.asClient() - matchTag.asClient() - matchNBT.asClient() + isWhitelist.isClient = true + matchTag.isClient = true + matchNBT.isClient = true } } @@ -109,24 +109,24 @@ class DriveViewerMenu @JvmOverloads constructor( driveFilter.copyFrom(filter) driveFilter.isLocked = false - isWhitelist.withProperty(driveFilter::isWhitelist) - matchTag.withProperty(driveFilter::matchTag) - matchNBT.withProperty(driveFilter::matchNBT) + isWhitelist.with(driveFilter::isWhitelist) + matchTag.with(driveFilter::matchTag) + matchNBT.with(driveFilter::matchNBT) } else { driveFilter.clear() driveFilter.isLocked = true - isWhitelist.withoutAnything() - matchTag.withoutAnything() - matchNBT.withoutAnything() + isWhitelist.clear() + matchTag.clear() + matchNBT.clear() } } else { driveFilter.clear() driveFilter.isLocked = true - isWhitelist.withoutAnything() - matchTag.withoutAnything() - matchNBT.withoutAnything() + isWhitelist.clear() + matchTag.clear() + matchNBT.clear() } } @@ -170,4 +170,4 @@ class DriveViewerMenu @JvmOverloads constructor( slot.setChanged() return copy } -} \ No newline at end of file +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/EnergyCounterMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/EnergyCounterMenu.kt index f480dbbd2..106203c19 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/EnergyCounterMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/EnergyCounterMenu.kt @@ -8,8 +8,6 @@ import net.minecraft.world.level.block.Block import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock import ru.dbotthepony.mc.otm.block.entity.tech.EnergyCounterBlockEntity import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.menu.widget.NumberPlayerInputWidget -import ru.dbotthepony.mc.otm.menu.widget.OneWayPlayerInputWidget import ru.dbotthepony.mc.otm.registry.MMenus import java.math.BigDecimal @@ -22,36 +20,28 @@ class EnergyCounterMenu @JvmOverloads constructor( var average by mSynchronizer.fraction() var last20Ticks by mSynchronizer.fraction() var lastTick by mSynchronizer.fraction() + var maxIO by mSynchronizer.bigDecimal() + + val switchDirection = oneWayInput { + if (tile is EnergyCounterBlockEntity) + tile.level?.setBlock(tile.blockPos, tile.blockState.setValue(EnergyCounterBlock.INPUT_DIRECTION, tile.blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION).opposite), Block.UPDATE_ALL) + } - val switchDirection: OneWayPlayerInputWidget var inputDirection by mSynchronizer.enum(Direction::class.java) - val maxIO = NumberPlayerInputWidget(this) - - // TODO: Graph and proper networking for it - private var ticksPassed = 0 - - init { - if (tile == null) { - switchDirection = OneWayPlayerInputWidget(this) - maxIO.asClient() - } else { - switchDirection = OneWayPlayerInputWidget(this) { - tile.level?.setBlock(tile.blockPos, tile.blockState.setValue(EnergyCounterBlock.INPUT_DIRECTION, tile.blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION).opposite), Block.UPDATE_ALL) - } - - maxIO.withSupplier { - return@withSupplier if (tile.ioLimit == null) MINUS_ONE else tile.ioLimit!!.toBigDecmial() - }.withConsumer { - if (it.signum() < 0) { - tile.ioLimit = null - } else { - tile.ioLimit = Decimal(it) - } + val maxIOInput = bigDecimalInput { + if (tile is EnergyCounterBlockEntity) { + if (it.signum() < 0) { + tile.ioLimit = null + } else { + tile.ioLimit = Decimal(it) } } } + // TODO: Graph and proper networking for it + private var ticksPassed = 0 + override fun broadcastChanges() { if (tile is EnergyCounterBlockEntity) { passed = tile.passed @@ -64,6 +54,8 @@ class EnergyCounterMenu @JvmOverloads constructor( ticksPassed = (ticksPassed + 1) % 20 inputDirection = tile.blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION) + + maxIO = tile.ioLimit?.toBigDecmial() ?: -BigDecimal.ONE } super.broadcastChanges() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterBottlerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterBottlerMenu.kt index 784cdde72..ab79c71da 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterBottlerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterBottlerMenu.kt @@ -8,7 +8,7 @@ import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.matter.canExtractMatter import ru.dbotthepony.mc.otm.capability.matter.canReceiveMatter -import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget +import ru.dbotthepony.mc.otm.menu.widget.NetworkedBooleanInput import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.core.orNull @@ -21,7 +21,7 @@ class MatterBottlerMenu @JvmOverloads constructor( ) : MatteryPoweredMenu( MMenus.MATTER_BOTTLER, p_38852_, inventory, tile ) { - val workFlow: BooleanPlayerInputWidget + val workFlow: NetworkedBooleanInput val progressWidget: ProgressGaugeWidget val matterWidget: LevelGaugeWidget @@ -34,11 +34,11 @@ class MatterBottlerMenu @JvmOverloads constructor( if (tile == null) { progressWidget = ProgressGaugeWidget(this) matterWidget = LevelGaugeWidget(this) - workFlow = BooleanPlayerInputWidget(this).asClient() + workFlow = NetworkedBooleanInput(this).asClient() } else { progressWidget = ProgressGaugeWidget(this) { tile.getWorkProgress() } matterWidget = LevelGaugeWidget(this, tile.matter) - workFlow = BooleanPlayerInputWidget(this, tile::isBottling) + workFlow = NetworkedBooleanInput(this, tile::isBottling) } storageSlots = ImmutableList(6) { index -> @@ -58,9 +58,4 @@ class MatterBottlerMenu @JvmOverloads constructor( storageSlots.forEach(this::addSlot) addInventorySlots() } - - override fun broadcastChanges() { - super.broadcastChanges() - workFlow.value = (tile as MatterBottlerBlockEntity).isBottling - } } 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 ea481dc3f..d5b09478f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -22,7 +22,10 @@ import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorSlots 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.BooleanValueCodec import ru.dbotthepony.mc.otm.core.util.IStreamCodec +import ru.dbotthepony.mc.otm.core.util.NullValueCodec import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget import ru.dbotthepony.mc.otm.network.FieldSynchronizer import ru.dbotthepony.mc.otm.network.MatteryPacket @@ -33,6 +36,7 @@ import ru.dbotthepony.mc.otm.network.packetHandled import ru.dbotthepony.mc.otm.network.sender import java.io.DataInputStream import java.io.DataOutputStream +import java.math.BigDecimal import java.util.* import java.util.function.Supplier import kotlin.collections.ArrayList @@ -43,6 +47,9 @@ abstract class MatteryMenu @JvmOverloads protected constructor( val inventory: Inventory, val tile: BlockEntity? = null ) : AbstractContainerMenu(menuType, containerId) { + /** + * Server->Client field synchronizer + */ val mSynchronizer = FieldSynchronizer() val ply: Player get() = inventory.player @@ -80,8 +87,12 @@ abstract class MatteryMenu @JvmOverloads protected constructor( } } - inner class PlayerInput(val codec: IStreamCodec, val allowSpectators: Boolean = false, val handler: (V) -> Unit) { + /** + * Client->Server handler + */ + inner class PlayerInput(val codec: IStreamCodec, allowSpectators: Boolean = false, val handler: (V) -> Unit) { val id = playerInputs.size + var allowSpectators by mSynchronizer.bool(allowSpectators) init { playerInputs.add(this) @@ -93,11 +104,26 @@ abstract class MatteryMenu @JvmOverloads protected constructor( MenuNetworkChannel.sendToServer(PlayerInputPacket(containerId, id, stream.array.copyOfRange(0, stream.length))) } + fun checkedInput(value: V, player: Player?) { + if (allowSpectators || player?.isSpectator == false) { + return input(value) + } + } + internal fun invoke(value: Any?) { handler.invoke(value as V) } } + fun oneWayInput(allowSpectators: Boolean = false, handler: () -> Unit): PlayerInput { + return PlayerInput(NullValueCodec, allowSpectators) { + handler.invoke() + } + } + + fun bigDecimalInput(allowSpectators: Boolean = false, handler: (BigDecimal) -> Unit) = PlayerInput(BigDecimalValueCodec, allowSpectators, handler) + fun booleanInput(allowSpectators: Boolean = false, handler: (Boolean) -> Unit) = PlayerInput(BooleanValueCodec, 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 f7dfd875b..6f13278d0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageBusMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageBusMenu.kt @@ -4,7 +4,7 @@ import net.minecraft.world.entity.player.Inventory import net.minecraft.world.inventory.Slot import ru.dbotthepony.mc.otm.block.entity.storage.StorageBusBlockEntity import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot -import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget +import ru.dbotthepony.mc.otm.menu.widget.NetworkedBooleanInput import ru.dbotthepony.mc.otm.registry.MMenus class StorageBusMenu @JvmOverloads constructor( @@ -15,15 +15,15 @@ class StorageBusMenu @JvmOverloads constructor( MMenus.STORAGE_BUS, p_38852_, inventory, tile ) { val busFilterSlots: List - val busFilterState: BooleanPlayerInputWidget + val busFilterState: NetworkedBooleanInput init { if (tile != null) { busFilterSlots = addFilterSlots(tile.filter) - busFilterState = BooleanPlayerInputWidget(this, tile.filter::isWhitelist) + busFilterState = NetworkedBooleanInput(this, tile.filter::isWhitelist) } else { busFilterSlots = addFilterSlots(StorageBusBlockEntity.MAX_FILTERS) - busFilterState = BooleanPlayerInputWidget(this).asClient() + busFilterState = NetworkedBooleanInput(this).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 777118f53..d16a7c3c7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageExporterMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageExporterMenu.kt @@ -4,7 +4,7 @@ import net.minecraft.world.entity.player.Inventory import net.minecraft.world.inventory.Slot import ru.dbotthepony.mc.otm.block.entity.storage.StorageExporterBlockEntity import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot -import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget +import ru.dbotthepony.mc.otm.menu.widget.NetworkedBooleanInput import ru.dbotthepony.mc.otm.registry.MMenus class StorageExporterMenu @JvmOverloads constructor( @@ -15,15 +15,15 @@ class StorageExporterMenu @JvmOverloads constructor( MMenus.STORAGE_EXPORTER, p_38852_, inventory, tile ) { val busFilterSlots: List - val busFilterState: BooleanPlayerInputWidget + val busFilterState: NetworkedBooleanInput init { if (tile != null) { busFilterSlots = addFilterSlots(tile.filter) - busFilterState = BooleanPlayerInputWidget(this, tile.filter::isWhitelist) + busFilterState = NetworkedBooleanInput(this, tile.filter::isWhitelist) } else { busFilterSlots = addFilterSlots(StorageExporterBlockEntity.MAX_FILTERS) - busFilterState = BooleanPlayerInputWidget(this).asClient() + busFilterState = NetworkedBooleanInput(this).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 554153aef..3ccd5fa1e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageImporterMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageImporterMenu.kt @@ -4,7 +4,7 @@ import net.minecraft.world.entity.player.Inventory import net.minecraft.world.inventory.Slot import ru.dbotthepony.mc.otm.block.entity.storage.StorageImporterBlockEntity import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot -import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget +import ru.dbotthepony.mc.otm.menu.widget.NetworkedBooleanInput import ru.dbotthepony.mc.otm.registry.MMenus class StorageImporterMenu @JvmOverloads constructor( @@ -15,15 +15,15 @@ class StorageImporterMenu @JvmOverloads constructor( MMenus.STORAGE_IMPORTER, p_38852_, inventory, tile ) { val busFilterSlots: List - val busFilterState: BooleanPlayerInputWidget + val busFilterState: NetworkedBooleanInput init { if (tile != null) { busFilterSlots = addFilterSlots(tile.filter) - busFilterState = BooleanPlayerInputWidget(this, tile.filter::isWhitelist) + busFilterState = NetworkedBooleanInput(this, tile.filter::isWhitelist) } else { busFilterSlots = addFilterSlots(StorageImporterBlockEntity.MAX_FILTERS) - busFilterState = BooleanPlayerInputWidget(this).asClient() + busFilterState = NetworkedBooleanInput(this).asClient() } addInventorySlots() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/BooleanPlayerInputWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/BooleanPlayerInputWidget.kt deleted file mode 100644 index da5988ed8..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/BooleanPlayerInputWidget.kt +++ /dev/null @@ -1,101 +0,0 @@ -package ru.dbotthepony.mc.otm.menu.widget - -import net.minecraft.network.FriendlyByteBuf -import net.minecraft.world.entity.player.Player -import net.minecraftforge.network.NetworkEvent -import ru.dbotthepony.mc.otm.menu.MatteryMenu -import ru.dbotthepony.mc.otm.network.MatteryPacket -import ru.dbotthepony.mc.otm.network.MenuNetworkChannel -import ru.dbotthepony.mc.otm.network.sender -import java.util.function.Supplier -import kotlin.reflect.KMutableProperty0 - -class BooleanPlayerInputPacket(val id: Int, val value: Boolean) : MatteryPacket { - override fun play(context: Supplier) { - context.get().packetHandled = true - - context.get().enqueueWork { - ((context.get().sender?.containerMenu as? MatteryMenu)?.getWidget(id) as? BooleanPlayerInputWidget)?.userInput(value, context.sender!!) - } - } - - override fun write(buff: FriendlyByteBuf) { - buff.writeInt(id) - buff.writeBoolean(value) - } - - companion object { - fun read(buff: FriendlyByteBuf): BooleanPlayerInputPacket { - return BooleanPlayerInputPacket(buff.readInt(), buff.readBoolean()) - } - } -} - -class BooleanPlayerInputWidget(menu: MatteryMenu) : AbstractWidget(menu) { - var value by menu.mSynchronizer.bool() - var ignoreSpectators by menu.mSynchronizer.bool(true) - - constructor(menu: MatteryMenu, state: KMutableProperty0) : this(menu) { - withClicker { state.set(it) } - withSupplier { state.get() } - } - - var supplier: (() -> Boolean)? = null - var clicker: ((Boolean) -> Unit)? = null - - fun withSupplier(func: () -> Boolean): BooleanPlayerInputWidget { - supplier = func - return this - } - - fun withClicker(func: (Boolean) -> Unit): BooleanPlayerInputWidget { - clicker = func - return this - } - - fun withProperty(state: KMutableProperty0): BooleanPlayerInputWidget { - withClicker { state.set(it) } - withSupplier { state.get() } - return this - } - - fun withoutAnything(): BooleanPlayerInputWidget { - supplier = null - clicker = null - return this - } - - fun asClient(): BooleanPlayerInputWidget { - supplier = null - clicker = { - MenuNetworkChannel.sendToServer(BooleanPlayerInputPacket(slotID, it)) - } - - return this - } - - fun userInput(newValue: Boolean, ply: Player? = null) { - if (ply?.isSpectator == true && ignoreSpectators) { - return - } - - val clicker = clicker - - if (clicker != null) { - clicker.invoke(newValue) - updateServer() - } - } - - fun switchValue(ply: Player? = null) { - userInput(!value, ply) - } - - override fun updateServer() { - val supplier = supplier - - if (supplier != null) { - value = supplier.invoke() - } - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/NetworkedBooleanInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/NetworkedBooleanInput.kt new file mode 100644 index 000000000..52d705aa0 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/NetworkedBooleanInput.kt @@ -0,0 +1,60 @@ +package ru.dbotthepony.mc.otm.menu.widget + +import net.minecraft.world.entity.player.Player +import ru.dbotthepony.mc.otm.menu.MatteryMenu +import kotlin.reflect.KMutableProperty0 + +class NetworkedBooleanInput(menu: MatteryMenu) { + val input = menu.booleanInput { consumer?.invoke(it) } + val value by menu.mSynchronizer.bool(getter = { supplier?.invoke() ?: false }) + + constructor(menu: MatteryMenu, state: KMutableProperty0) : this(menu) { + with(state) + } + + var isClient = false + + fun asClient(): NetworkedBooleanInput { + isClient = true + supplier = null + consumer = null + return this + } + + var supplier: (() -> Boolean)? = null + var consumer: ((Boolean) -> Unit)? = null + + fun withSupplier(func: () -> Boolean): NetworkedBooleanInput { + supplier = func + return this + } + + fun withConsumer(func: (Boolean) -> Unit): NetworkedBooleanInput { + consumer = func + return this + } + + fun with(state: KMutableProperty0): NetworkedBooleanInput { + withConsumer { state.set(it) } + withSupplier { state.get() } + return this + } + + fun clear(): NetworkedBooleanInput { + supplier = null + consumer = null + return this + } + + fun userInput(newValue: Boolean, ply: Player? = null) { + if (isClient) { + input.checkedInput(newValue, ply) + } else { + consumer?.invoke(newValue) + } + } + + fun switchValue(ply: Player? = null) { + userInput(!value, ply) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/NumberPlayerInputWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/NumberPlayerInputWidget.kt deleted file mode 100644 index 7489a7e97..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/NumberPlayerInputWidget.kt +++ /dev/null @@ -1,92 +0,0 @@ -package ru.dbotthepony.mc.otm.menu.widget - -import net.minecraft.network.FriendlyByteBuf -import net.minecraft.world.entity.player.Player -import net.minecraftforge.network.NetworkEvent -import ru.dbotthepony.mc.otm.menu.MatteryMenu -import ru.dbotthepony.mc.otm.network.* -import java.math.BigDecimal -import java.util.function.Supplier - -class NumberPlayerInputPacket(val id: Int, val value: BigDecimal) : MatteryPacket { - override fun play(context: Supplier) { - context.get().packetHandled = true - - context.get().enqueueWork { - ((context.get().sender?.containerMenu as? MatteryMenu)?.getWidget(id) as? NumberPlayerInputWidget)?.userInput(value, context.sender!!) - } - } - - override fun write(buff: FriendlyByteBuf) { - buff.writeInt(id) - buff.writeDecimal(value) - } - - companion object { - fun read(buff: FriendlyByteBuf): NumberPlayerInputPacket { - return NumberPlayerInputPacket(buff.readInt(), buff.readDecimal()) - } - } -} - -class NumberPlayerInputWidget(menu: MatteryMenu) : AbstractWidget(menu) { - var value by menu.mSynchronizer.bigDecimal() - var ignoreSpectators by menu.mSynchronizer.bool(true) - - var supplier: (() -> BigDecimal)? = null - var consumer: ((BigDecimal) -> Unit)? = null - var minValue: BigDecimal? = null - var maxValue: BigDecimal? = null - - fun withSupplier(func: () -> BigDecimal): NumberPlayerInputWidget { - supplier = func - return this - } - - fun withConsumer(func: (BigDecimal) -> Unit): NumberPlayerInputWidget { - consumer = func - return this - } - - fun asClient(): NumberPlayerInputWidget { - supplier = null - - consumer = { - MenuNetworkChannel.sendToServer(NumberPlayerInputPacket(slotID, it)) - } - - return this - } - - fun userInput(newValue: BigDecimal, ply: Player? = null) { - if (ply?.isSpectator == true && ignoreSpectators) { - return - } - - val consumer = consumer - - if (consumer != null) { - @Suppress("name_shadowing") - var newValue = newValue - - if (minValue != null) { - newValue = newValue.max(minValue!!) - } - - if (maxValue != null) { - newValue = newValue.min(maxValue!!) - } - - consumer.invoke(newValue) - updateServer() - } - } - - override fun updateServer() { - val supplier = supplier - - if (supplier != null) { - value = supplier.invoke() - } - } -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/OneWayPlayerInputWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/OneWayPlayerInputWidget.kt deleted file mode 100644 index 203eae69c..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/OneWayPlayerInputWidget.kt +++ /dev/null @@ -1,53 +0,0 @@ -package ru.dbotthepony.mc.otm.menu.widget - -import net.minecraft.network.FriendlyByteBuf -import net.minecraft.world.entity.player.Player -import net.minecraftforge.network.NetworkEvent -import ru.dbotthepony.mc.otm.client.minecraft -import ru.dbotthepony.mc.otm.menu.MatteryMenu -import ru.dbotthepony.mc.otm.network.MatteryPacket -import ru.dbotthepony.mc.otm.network.MenuNetworkChannel -import ru.dbotthepony.mc.otm.network.sender -import ru.dbotthepony.mc.otm.runIfClient -import java.util.function.Supplier - -class OneWayPlayerInputPacket(val id: Int) : MatteryPacket { - override fun play(context: Supplier) { - context.get().packetHandled = true - - context.get().enqueueWork { - ((context.get().sender?.containerMenu as? MatteryMenu)?.getWidget(id) as? OneWayPlayerInputWidget)?.userInput(context.sender!!) - } - } - - override fun write(buff: FriendlyByteBuf) { - buff.writeInt(id) - } - - companion object { - fun read(buff: FriendlyByteBuf): OneWayPlayerInputPacket { - return OneWayPlayerInputPacket(buff.readInt()) - } - } -} - -class OneWayPlayerInputWidget(menu: MatteryMenu, clicker: (() -> Unit)? = null) : AbstractWidget(menu) { - val clicker: () -> Unit - var ignoreSpectators by menu.mSynchronizer.bool(true) - - init { - if (clicker != null) { - this.clicker = clicker - } else { - this.clicker = { MenuNetworkChannel.sendToServer(OneWayPlayerInputPacket(slotID)) } - } - } - - fun userInput(ply: Player? = null) { - if (ply?.isSpectator != true || !ignoreSpectators) { - clicker.invoke() - } - } - - override fun updateServer() {} -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt index b22cae9f8..e6fa318e0 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt @@ -19,9 +19,6 @@ import ru.dbotthepony.mc.otm.menu.data.ItemViewInteractPacket import ru.dbotthepony.mc.otm.menu.data.StackAddPacket import ru.dbotthepony.mc.otm.menu.data.StackChangePacket import ru.dbotthepony.mc.otm.menu.data.StackRemovePacket -import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputPacket -import ru.dbotthepony.mc.otm.menu.widget.NumberPlayerInputPacket -import ru.dbotthepony.mc.otm.menu.widget.OneWayPlayerInputPacket import java.io.ByteArrayInputStream import java.util.function.Supplier @@ -79,17 +76,12 @@ object MenuNetworkChannel : MatteryNetworkChannel( add(StackChangePacket::class.java, StackChangePacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT) add(StackRemovePacket::class.java, StackRemovePacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT) - // container data + // Menu data + // Server->Client add(MenuFieldPacket::class.java, MenuFieldPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT) - - // Player input in menus - add(NumberPlayerInputPacket::class.java, NumberPlayerInputPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER) - add(OneWayPlayerInputPacket::class.java, OneWayPlayerInputPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER) - add(BooleanPlayerInputPacket::class.java, BooleanPlayerInputPacket.Companion::read, NetworkDirection.PLAY_TO_SERVER) + // Client->Server add(MatteryMenu.PlayerInputPacket::class.java, MatteryMenu::PlayerInputPacket, NetworkDirection.PLAY_TO_SERVER) - // menu specific - // Item monitor add(ItemMonitorPlayerSettings::class.java, ItemMonitorPlayerSettings.Companion::read)