From 1afa8e3d215a3192543795f9e8985252a8bdc231 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 12 Aug 2023 11:44:49 +0700 Subject: [PATCH] Flatten filter slots to just gettersetter --- .../entity/storage/StorageBusBlockEntity.kt | 2 +- .../block/entity/storage/StorageInterfaces.kt | 4 +- .../panels/input/NetworkNumberInputPanel.kt | 2 +- .../screen/panels/slot/FilterSlotPanel.kt | 15 +-- .../screen/storage/DriveViewerScreen.kt | 1 - .../client/screen/tech/EnergyCounterScreen.kt | 3 +- .../screen/tech/EssenceStorageScreen.kt | 28 ++--- .../mc/otm/container/ItemFilter.kt | 119 ++---------------- .../otm/core/collect/JsonArraySpliterator.kt | 2 +- .../otm/item/PortableCondensationDriveItem.kt | 6 +- .../ru/dbotthepony/mc/otm/menu/MatteryMenu.kt | 65 +++++----- .../input/AbstractPlayerInputWithFeedback.kt | 3 +- .../mc/otm/menu/input/InstantBooleanInput.kt | 2 +- .../mc/otm/menu/matter/MatterPanelMenu.kt | 4 +- .../mc/otm/menu/storage/DriveViewerMenu.kt | 61 ++++----- .../mc/otm/menu/storage/StorageBusMenu.kt | 9 +- .../otm/menu/storage/StorageExporterMenu.kt | 16 +-- .../otm/menu/storage/StorageImporterMenu.kt | 24 +--- .../mc/otm/network/MenuNetworkChannel.kt | 5 +- 19 files changed, 108 insertions(+), 263 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt index 45d3a1716..dd37cadf8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt @@ -121,7 +121,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter } } - val filter = ItemFilter(MAX_FILTERS) { _, _, _ -> + val filter = ItemFilter(MAX_FILTERS) { component?.scan() setChangedLight() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt index 2a5db7efc..1b2ed459e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt @@ -113,7 +113,7 @@ abstract class AbstractStorageImportExport( class StorageImporterBlockEntity( blockPos: BlockPos, blockState: BlockState ) : AbstractStorageImportExport(MBlockEntities.STORAGE_IMPORTER, blockPos, blockState), IItemHandler { - override val filter = ItemFilter(MAX_FILTERS) { _, _, _ -> + override val filter = ItemFilter(MAX_FILTERS) { setChangedLight() } @@ -262,7 +262,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : relevantTuples.remove(id) } - override val filter = ItemFilter(MAX_FILTERS) { _, _, _ -> + override val filter = ItemFilter(MAX_FILTERS) { relevantTuples.clear() val component = cell.graph.getVirtualComponent(StorageStack.ITEMS) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkNumberInputPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkNumberInputPanel.kt index 53d3ac70d..f37fc4501 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkNumberInputPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/input/NetworkNumberInputPanel.kt @@ -34,7 +34,7 @@ open class NetworkNumberInputPanel @JvmOverloads constructor( ) : this( screen = screen, parent = parent, - callback = widget::input, + callback = widget::accept, isAvailable = { widget.allowSpectators || minecraft.player?.isSpectator != true }, networkValue = networkValue, x = x, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/FilterSlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/FilterSlotPanel.kt index 5cb0b7ef5..e3f67d5ea 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/FilterSlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/FilterSlotPanel.kt @@ -3,14 +3,12 @@ package ru.dbotthepony.mc.otm.client.screen.panels.slot import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot -import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket -import ru.dbotthepony.mc.otm.network.MenuNetworkChannel +import ru.dbotthepony.mc.otm.core.GetterSetter open class FilterSlotPanel> @JvmOverloads constructor( screen: S, parent: EditablePanel<*>?, - val slot: ItemFilterNetworkSlot, + val slot: GetterSetter, x: Float = 0f, y: Float = 0f, width: Float = SIZE, @@ -21,14 +19,7 @@ open class FilterSlotPanel> @JvmOverloads constructor( } override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { - if (!screen.menu.ply.isSpectator) { - if (screen.menu.carried.isEmpty) { - MenuNetworkChannel.sendToServer(ItemFilterSlotPacket(slot.networkID, ItemStack.EMPTY)) - } else { - MenuNetworkChannel.sendToServer(ItemFilterSlotPacket(slot.networkID, screen.menu.carried)) - } - } - + slot.accept(screen.menu.carried) return true } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/DriveViewerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/DriveViewerScreen.kt index c82f8b38e..95769454c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/DriveViewerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/storage/DriveViewerScreen.kt @@ -63,7 +63,6 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp val filterGrid = GridPanel(this, frame, width = AbstractSlotPanel.SIZE * 3f, height = AbstractSlotPanel.SIZE * 4f, rows = 3, columns = 4) filterGrid.dock = Dock.FILL filterGrid.dockResize = DockResizeMode.NONE - filterGrid.dockTop = 20f settings.add(filterGrid) for (i in 0 until PortableCondensationDriveItem.MAX_FILTERS) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyCounterScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyCounterScreen.kt index b21634eb0..b8a2c2060 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyCounterScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EnergyCounterScreen.kt @@ -11,7 +11,6 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkNumberInputPanel import ru.dbotthepony.mc.otm.core.util.formatPower import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu -import java.util.function.Supplier class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title: Component) : MatteryScreen(menu, inventory, title) { override fun makeMainFrame(): FramePanel> { @@ -43,7 +42,7 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title: } if (!menu.ply.isSpectator) { - val button = ButtonPanel(this, frame, 0f, 0f, 0f, 20f, TranslatableComponent("block.overdrive_that_matters.energy_counter.switch"), onPress = Runnable { menu.switchDirection.input(null) }) + val button = ButtonPanel(this, frame, 0f, 0f, 0f, 20f, TranslatableComponent("block.overdrive_that_matters.energy_counter.switch"), onPress = Runnable { menu.switchDirection.accept(null) }) button.dock = Dock.TOP button.setDockMargin(4f, 5f, 4f, 0f) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EssenceStorageScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EssenceStorageScreen.kt index f1bd75821..b7d3b7a2e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EssenceStorageScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/EssenceStorageScreen.kt @@ -100,7 +100,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title } override fun onClick(mouseButton: Int) { - menu.storeLevels.input(1) + menu.storeLevels.accept(1) } override var isDisabled: Boolean @@ -115,7 +115,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title } override fun onClick(mouseButton: Int) { - menu.storeLevels.input(10) + menu.storeLevels.accept(10) } override var isDisabled: Boolean @@ -130,7 +130,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title } override fun onClick(mouseButton: Int) { - menu.storeLevels.input((minecraft?.player?.experienceLevel ?: 0) + 1) + menu.storeLevels.accept((minecraft?.player?.experienceLevel ?: 0) + 1) } override var isDisabled: Boolean @@ -145,7 +145,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title } override fun onClick(mouseButton: Int) { - menu.dispenseLevels.input(1) + menu.dispenseLevels.accept(1) } override var isDisabled: Boolean @@ -160,7 +160,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title } override fun onClick(mouseButton: Int) { - menu.dispenseLevels.input(10) + menu.dispenseLevels.accept(10) } override var isDisabled: Boolean @@ -175,7 +175,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title } override fun onClick(mouseButton: Int) { - menu.dispenseLevels.input(getLevelFromXp(menu.experienceStored) + 1) + menu.dispenseLevels.accept(getLevelFromXp(menu.experienceStored) + 1) } override var isDisabled: Boolean @@ -192,7 +192,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title } override fun onClick(mouseButton: Int) { - menu.storeLevels.input(customDispense) + menu.storeLevels.accept(customDispense) } override var isDisabled: Boolean @@ -211,12 +211,12 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title if (player.experienceLevel == customDispense) { if (player.experienceProgress > 0f) { - menu.storeLevels.input(1) + menu.storeLevels.accept(1) } } else if (player.experienceLevel > customDispense) { - menu.storeLevels.input(player.experienceLevel - customDispense) + menu.storeLevels.accept(player.experienceLevel - customDispense) } else { - menu.dispenseLevels.input(customDispense - player.experienceLevel) + menu.dispenseLevels.accept(customDispense - player.experienceLevel) } playGuiClickSound() @@ -233,7 +233,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title } override fun onClick(mouseButton: Int) { - menu.dispenseLevels.input(customDispense) + menu.dispenseLevels.accept(customDispense) } override var isDisabled: Boolean @@ -253,12 +253,12 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title if (player.experienceLevel == customDispense) { if (player.experienceProgress > 0f) { - menu.storeLevels.input(1) + menu.storeLevels.accept(1) } } else if (player.experienceLevel > customDispense) { - menu.storeLevels.input(player.experienceLevel - customDispense) + menu.storeLevels.accept(player.experienceLevel - customDispense) } else { - menu.dispenseLevels.input(customDispense - player.experienceLevel) + menu.dispenseLevels.accept(customDispense - player.experienceLevel) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt index 668f7d1c5..da7ab048f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt @@ -17,98 +17,13 @@ import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.core.nbt.set import java.util.Arrays import java.util.LinkedList +import java.util.function.Consumer import java.util.function.Supplier -data class ItemFilterSlotPacket(val slotID: Int, val newValue: ItemStack) : MatteryPacket { - override fun write(buff: FriendlyByteBuf) { - buff.writeInt(slotID) - buff.writeItemStack(newValue, true) - } - - override fun play(context: Supplier) { - context.get().packetHandled = true - - if (context.get().sender != null) { - context.get().enqueueWork { - playServer(context.get().sender!!) - } - } else { - context.get().enqueueWork { - playClient() - } - } - } - - fun playClient() { - val menu = minecraft.player?.containerMenu as? MatteryMenu ?: throw IllegalStateException("No MatteryMenu is open right now, can't handle ItemFilterSlotReplicaPacket") - menu.filterSlots[slotID].set(newValue) - } - - fun playServer(player: ServerPlayer) { - if (player.isSpectator) { - return - } - - val menu = player.containerMenu as? MatteryMenu ?: return LOGGER.error("No MatteryMenu is open right now, can't handle ItemFilterSlotReplicaPacket from $player") - val slot = menu.filterSlots.getOrNull(slotID) ?: return LOGGER.error("ItemFilterSlotReplicaPacket: unknown slot $slotID from $player in $menu!") - - if (slot.filter?.isLocked == true) - return - - slot.set(newValue) - } - - companion object { - fun read(buff: FriendlyByteBuf): ItemFilterSlotPacket { - return ItemFilterSlotPacket(buff.readInt(), buff.readItem()) - } - - private val LOGGER = LogManager.getLogger() - } -} - -data class ItemFilterNetworkSlot(val slotID: Int, val networkID: Int, var filter: ItemFilter?) { - fun get() = filter?.get(slotID) ?: remote - fun set(value: ItemStack) { - if (filter != null) - filter!![slotID] = value - else - remote = value - } - - private var remote: ItemStack = ItemStack.EMPTY - - fun sendChanges(full: Boolean = false): ItemFilterSlotPacket? { - requireNotNull(filter) { "Invalid side" } - - if (full || !ItemStack.isSameItemSameTags(remote, get())) { - remote = get() - return ItemFilterSlotPacket(networkID, get()) - } - - return null - } -} - -fun interface ItemFilterCallback { - fun invoke(slot: Int?, oldValue: ItemStack?, newValue: ItemStack?) -} - -fun interface ItemFilterFullCallback { - fun invoke(self: ItemFilter, slot: Int?, oldValue: ItemStack?, newValue: ItemStack?) -} - class ItemFilter( val size: Int, - private val modified: ItemFilterFullCallback? = null + private val modified: Consumer? = null ) : INBTSerializable { - constructor(size: Int, modified: ItemFilterCallback?) : - this(size, - modified?.let { - fn -> - return@let ItemFilterFullCallback { _: ItemFilter, slot: Int?, oldValue: ItemStack?, newValue: ItemStack? -> fn.invoke(slot, oldValue, newValue) } - }) - private val filter = Array(size) { ItemStack.EMPTY } private val linkedFilter = LinkedList() @@ -118,7 +33,7 @@ class ItemFilter( set(value) { if (value != field) { field = value - modified?.invoke(this, null, null, null) + modified?.accept(this) } } @@ -126,7 +41,7 @@ class ItemFilter( set(value) { if (value != field) { field = value - modified?.invoke(this, null, null, null) + modified?.accept(this) } } @@ -134,7 +49,7 @@ class ItemFilter( set(value) { if (value != field) { field = value - modified?.invoke(this, null, null, null) + modified?.accept(this) } } @@ -146,27 +61,7 @@ class ItemFilter( Arrays.fill(filter, ItemStack.EMPTY) linkedFilter.clear() - modified?.invoke(this, null, null, null) - } - - fun copyFrom(other: ItemFilter) { - require(other.size == size) { "Size differs (this filter has size of $size, other has size of ${other.size})" } - - linkedFilter.clear() - - for (i in 0 until size) { - filter[i] = other.filter[i] - - if (!filter[i].isEmpty) { - linkedFilter.add(filter[i]) - } - } - - isWhitelist = other.isWhitelist - matchTag = other.matchTag - matchNBT = other.matchNBT - - modified?.invoke(this, null, null, null) + modified?.accept(this) } operator fun set(index: Int, value: ItemStack) { @@ -187,7 +82,7 @@ class ItemFilter( if (!filter[index].isEmpty) linkedFilter.add(filter[index]) - modified?.invoke(this, index, old, filter[index]) + modified?.accept(this) } operator fun get(index: Int): ItemStack = filter[index].copy() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/collect/JsonArraySpliterator.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/collect/JsonArraySpliterator.kt index c6ac299d3..86eda1eb5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/collect/JsonArraySpliterator.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/collect/JsonArraySpliterator.kt @@ -27,4 +27,4 @@ class JsonArraySpliterator(private val obj: JsonArray, offset: Int = 0, private } fun JsonArray.elementSpliterator() = JsonArraySpliterator(this) -fun JsonArray.stream(): Stream = StreamSupport.stream(elementSpliterator(), false) +fun JsonArray.stream(): Stream = StreamSupport.stream(elementSpliterator(), false) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/PortableCondensationDriveItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/PortableCondensationDriveItem.kt index 4a4823dfe..74e64c601 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/PortableCondensationDriveItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/PortableCondensationDriveItem.kt @@ -22,6 +22,8 @@ import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.capability.drive.DrivePool import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.core.nbt.map +import ru.dbotthepony.mc.otm.core.nbt.set +import ru.dbotthepony.mc.otm.core.tagNotNull import java.math.BigInteger import java.util.* @@ -86,9 +88,11 @@ class PortableCondensationDriveItem(capacity: Int) : } fun getFilterSettings(drive: ItemStack): ItemFilter { - val filter = ItemFilter(MAX_FILTERS) + var ignore = true + val filter = ItemFilter(MAX_FILTERS) { if (!ignore) drive.tagNotNull[FILTER_PATH] = it.serializeNBT() } filter.isWhitelist = true drive.tag?.map(FILTER_PATH, filter::deserializeNBT) + ignore = false return filter } 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 5a0bc74e8..99dffd41f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -34,7 +34,6 @@ import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorSlots import ru.dbotthepony.mc.otm.compat.curios.curiosSlots 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.container.MatteryContainer import ru.dbotthepony.mc.otm.container.UpgradeContainer import ru.dbotthepony.mc.otm.core.GetterSetter @@ -46,6 +45,7 @@ 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.ItemStackValueCodec import ru.dbotthepony.mc.otm.core.util.ItemValueCodec import ru.dbotthepony.mc.otm.core.util.NullValueCodec import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec @@ -66,6 +66,7 @@ import java.io.DataOutputStream import java.math.BigDecimal import java.util.* import java.util.function.BooleanSupplier +import java.util.function.Consumer import java.util.function.DoubleSupplier import java.util.function.IntSupplier import java.util.function.Predicate @@ -90,7 +91,7 @@ data class UpgradeSlots( val currentStats: IMatteryUpgrade ) -abstract class MatteryMenu @JvmOverloads protected constructor( +abstract class MatteryMenu( menuType: MenuType<*>?, containerId: Int, val inventory: Inventory, @@ -137,7 +138,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor( /** * Client->Server input */ - inner class PlayerInput(val codec: IStreamCodec, allowSpectators: Boolean = false, val handler: (V) -> Unit) : Predicate { + inner class PlayerInput(val codec: IStreamCodec, allowSpectators: Boolean = false, val handler: (V) -> Unit) : Consumer, Predicate { val id = playerInputs.size var allowSpectators by mSynchronizer.bool(allowSpectators).property @@ -161,7 +162,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor( return filters.all { it.test(player) } } - fun input(value: V) { + override fun accept(value: V) { if (test(minecraft.player as Player?)) { val stream = FastByteArrayOutputStream() codec.write(DataOutputStream(stream), value) @@ -183,6 +184,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 itemInput(allowSpectators: Boolean = false, handler: (Item) -> Unit) = PlayerInput(ItemValueCodec, allowSpectators, handler) + fun itemStackInput(allowSpectators: Boolean = false, handler: (ItemStack) -> Unit) = PlayerInput(ItemStackValueCodec, allowSpectators, handler) fun nullableItemInput(allowSpectators: Boolean = false, handler: (Item?) -> Unit) = PlayerInput(ItemValueCodec.nullable, allowSpectators, handler) fun stringInput(allowSpectators: Boolean = false, handler: (String) -> Unit) = PlayerInput(BinaryStringCodec, allowSpectators, handler) fun intInput(allowSpectators: Boolean = false, handler: (Int) -> Unit) = PlayerInput(VarIntValueCodec, allowSpectators, handler) @@ -230,34 +232,47 @@ abstract class MatteryMenu @JvmOverloads protected constructor( protected val lockedInventorySlots: MutableSet = HashSet() protected open fun isInventorySlotLocked(index: Int): Boolean = lockedInventorySlots.contains(index) - private val _filterSlots = ArrayList() - val filterSlots: List = Collections.unmodifiableList(_filterSlots) - protected var inventorySlotIndexStart = 0 protected var inventorySlotIndexEnd = 0 private val playerPacketDistributor = PacketDistributor.PLAYER.with { ply as ServerPlayer } - fun addFilterSlots(slots: ItemFilter): List { - val result = ArrayList(slots.size) + fun addFilterSlots(slots: ItemFilter): List> { + val result = ArrayList>(slots.size) for (i in 0 until slots.size) { - _filterSlots.add(ItemFilterNetworkSlot(i, _filterSlots.size, slots).also(result::add)) + result.add(GetterSetter.of( + mSynchronizer.computedItem { slots[i] }, + itemStackInput { slots[i] = it } + )) } return result } - fun addFilterSlots(amount: Int): List { - val result = ArrayList(amount) + fun addFilterSlots(amount: Int): List> { + val result = ArrayList>(amount) for (i in 0 until amount) { - _filterSlots.add(ItemFilterNetworkSlot(i, _filterSlots.size, null).also(result::add)) + result.add(GetterSetter.of( + mSynchronizer.computedItem { ItemStack.EMPTY }, + itemStackInput { throw UnsupportedOperationException() } + )) } return result } + fun addFilterSlots(slots: ItemFilter?, amount: Int): List> { + if (slots != null && amount != slots.size) + throw IllegalStateException("Provided ItemFiler has different amount of slots than expected: ${slots.size} != $amount") + + if (slots == null) + return addFilterSlots(amount) + else + return addFilterSlots(slots) + } + open inner class InventorySlot(container: Container, index: Int, x: Int = 0, y: Int = 0) : UserFilteredSlot(container, index, x, y) { override fun mayPlace(itemStack: ItemStack): Boolean { return !isInventorySlotLocked(index) && super.mayPlace(itemStack) @@ -285,7 +300,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor( if (slotIndex in mattery.regularSlotFilters.indices) { filter = GetterSetter.of( getter = { mattery.regularSlotFilters[slotIndex].value }, - setter = nullableItemInput(true) { mattery.regularSlotFilters[slotIndex].value = it }::input + setter = nullableItemInput(true) { mattery.regularSlotFilters[slotIndex].value = it }::accept ) } @@ -294,20 +309,20 @@ abstract class MatteryMenu @JvmOverloads protected constructor( chargeFlag = GetterSetter.of( getter = { mattery.regularSlotChargeFlag[slotIndex].boolean }, - setter = input::input + setter = input::accept ) } } else if (container === mattery.exopackContainer) { filter = GetterSetter.of( getter = { mattery.exopackContainer.getSlotFilter(slotIndex) }, - setter = nullableItemInput(true) { mattery.exopackContainer.setSlotFilter(slotIndex, it) }::input + setter = nullableItemInput(true) { mattery.exopackContainer.setSlotFilter(slotIndex, it) }::accept ) val input = booleanInput(true) { if (it) mattery.exoPackSlotsChargeFlag.add(slotIndex) else mattery.exoPackSlotsChargeFlag.remove(slotIndex) } chargeFlag = GetterSetter.of( getter = { slotIndex in mattery.exoPackSlotsChargeFlag }, - setter = input::input + setter = input::accept ) } else { filter = null @@ -422,20 +437,6 @@ abstract class MatteryMenu @JvmOverloads protected constructor( } } - val consumer = PacketDistributor.PLAYER.with { ply as ServerPlayer } - - for (slot in _filterSlots) { - val packet = slot.sendChanges() - - if (packet != null) { - if (broadcastOnce) { - MenuNetworkChannel.send(consumer, packet) - } else { - MenuNetworkChannel.sendNow(consumer, packet) - } - } - } - broadcastOnce = true } @@ -494,7 +495,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor( field = mSynchronizer.ComputedField(getter = { null }, ItemValueCodec.nullable) } - pSlot.filter = GetterSetter.of(getter = field::value, setter = input::input) + pSlot.filter = GetterSetter.of(getter = field::value, setter = input::accept) } return super.addSlot(pSlot) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractPlayerInputWithFeedback.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractPlayerInputWithFeedback.kt index 12480f58e..66c9fbfc8 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractPlayerInputWithFeedback.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/AbstractPlayerInputWithFeedback.kt @@ -1,7 +1,6 @@ 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.core.GetterSetter import ru.dbotthepony.mc.otm.core.ISubscriptable import ru.dbotthepony.mc.otm.core.SentientGetterSetter @@ -39,7 +38,7 @@ abstract class AbstractPlayerInputWithFeedback : IPlayerInputWithFeedback } final override fun accept(t: V) { - input.input(t) + input.accept(t) } override fun test(player: Player?) = input.test(player) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt index 49204ce6b..2b1b7e85c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/input/InstantBooleanInput.kt @@ -20,6 +20,6 @@ class InstantBooleanInput(menu: MatteryMenu) : GetterSetter, BooleanSup override fun accept(t: Boolean) { value = t - input.input(t) + input.accept(t) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt index 67fdf18e4..44a315958 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt @@ -187,8 +187,8 @@ class MatterPanelMenu( val changeIsAscending = booleanInput(allowSpectators = true) { tile?.getPlayerSettings(ply)?.ascending = it } val changeSorting = PlayerInput(ItemSorter::class.codec(), allowSpectators = true) { tile?.getPlayerSettings(ply)?.sorter = it } - val sortingGS = GetterSetter.of(::sorting, changeSorting::input) - val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::input) + val sortingGS = GetterSetter.of(::sorting, changeSorting::accept) + val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::accept) private val actualComparator = Comparator { o1, o2 -> sorting.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) } private val actualTaskComparator = Comparator { o1, o2 -> sorting.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/DriveViewerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/DriveViewerMenu.kt index ebad3143d..9a5e139e9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/DriveViewerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/DriveViewerMenu.kt @@ -10,7 +10,10 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage import ru.dbotthepony.mc.otm.container.ItemFilter +import ru.dbotthepony.mc.otm.core.GetterSetter +import ru.dbotthepony.mc.otm.core.asGetterSetter import ru.dbotthepony.mc.otm.core.ifPresentK +import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu @@ -70,17 +73,30 @@ class DriveViewerMenu( addInventorySlots() } - val driveFilter = ItemFilter(PortableCondensationDriveItem.MAX_FILTERS) { self, _, _, _ -> - if (tile?.container?.get(0)?.item is PortableCondensationDriveItem) { - tile.container[0].getOrCreateTag().put(PortableCondensationDriveItem.FILTER_PATH, self.serializeNBT()) - } + var drivePresent by mSynchronizer.bool().property + + private fun getFilter(): ItemFilter? { + val stack = (tile as? DriveViewerBlockEntity)?.container?.getItem(0) + return (stack?.item as? PortableCondensationDriveItem)?.getFilterSettings(stack) } - val driveFilterSlots = addFilterSlots(driveFilter) + val driveFilterSlots = immutableList(PortableCondensationDriveItem.MAX_FILTERS) { i -> + GetterSetter.of( + mSynchronizer.computedItem { getFilter()?.get(i) ?: ItemStack.EMPTY }, + itemStackInput { getFilter()?.set(i, it) } + ) + } - val isWhitelist = BooleanInputWithFeedback(this) - val matchTag = BooleanInputWithFeedback(this) - val matchNBT = BooleanInputWithFeedback(this) + private fun make(mapper: (ItemFilter) -> GetterSetter): GetterSetter { + return GetterSetter.of( + { getFilter()?.let(mapper)?.get() ?: false }, + { getFilter()?.let(mapper)?.accept(it) } + ) + } + + val isWhitelist = BooleanInputWithFeedback(this, make { it::isWhitelist.asGetterSetter() }).also { it.filter { drivePresent } } + val matchTag = BooleanInputWithFeedback(this, make { it::matchTag.asGetterSetter() }).also { it.filter { drivePresent } } + val matchNBT = BooleanInputWithFeedback(this, make { it::matchNBT.asGetterSetter() }).also { it.filter { drivePresent } } override fun broadcastChanges() { super.broadcastChanges() @@ -99,37 +115,12 @@ class DriveViewerMenu( } } + drivePresent = lastDrive != null + if (prev != lastDrive) { prev?.let(powered!!::remove) this.networkedItemView.clear() lastDrive?.let(powered!!::add) - - if (lastDrive != null) { - val filter = (itemStack.item as? PortableCondensationDriveItem)?.getFilterSettings(itemStack) - - if (filter != null) { - driveFilter.copyFrom(filter) - driveFilter.isLocked = false - - isWhitelist.with(driveFilter::isWhitelist) - matchTag.with(driveFilter::matchTag) - matchNBT.with(driveFilter::matchNBT) - } else { - driveFilter.clear() - driveFilter.isLocked = true - - isWhitelist.clear() - matchTag.clear() - matchNBT.clear() - } - } else { - driveFilter.clear() - driveFilter.isLocked = true - - isWhitelist.clear() - matchTag.clear() - matchNBT.clear() - } } this.networkedItemView.network() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageBusMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageBusMenu.kt index f4efb96b0..c4fe3c48d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageBusMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageBusMenu.kt @@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.menu.storage import net.minecraft.world.entity.player.Inventory import ru.dbotthepony.mc.otm.block.entity.storage.StorageBusBlockEntity import ru.dbotthepony.mc.otm.capability.FlowDirection -import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback @@ -16,7 +15,7 @@ class StorageBusMenu( inventory: Inventory, tile: StorageBusBlockEntity? = null ) : MatteryPoweredMenu(MMenus.STORAGE_BUS, containerId, inventory, tile) { - val busFilterSlots: List + val busFilterSlots = addFilterSlots(tile?.filter, StorageBusBlockEntity.MAX_FILTERS) val busFilterState = BooleanInputWithFeedback(this, tile?.let { it.filter::isWhitelist }) val insertPriority = IntInputWithFeedback(this, tile?.let { it::insertPriority }) val extractPriority = IntInputWithFeedback(this, tile?.let { it::extractPriority }) @@ -24,12 +23,6 @@ class StorageBusMenu( val mode = EnumInputWithFeedback(this, tile?.let { it::mode }, FlowDirection.WITHOUT_NONE) init { - if (tile != null) { - busFilterSlots = addFilterSlots(tile.filter) - } else { - busFilterSlots = addFilterSlots(StorageBusBlockEntity.MAX_FILTERS) - } - addStorageSlot(batterySlot) addInventorySlots() } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageExporterMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageExporterMenu.kt index 168a26c07..b669facf2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageExporterMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageExporterMenu.kt @@ -1,32 +1,22 @@ package ru.dbotthepony.mc.otm.menu.storage 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.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.registry.MMenus -class StorageExporterMenu @JvmOverloads constructor( +class StorageExporterMenu( p_38852_: Int, inventory: Inventory, tile: StorageExporterBlockEntity? = null ) : MatteryPoweredMenu( MMenus.STORAGE_EXPORTER, p_38852_, inventory, tile ) { - val busFilterSlots: List - val busFilterState: BooleanInputWithFeedback + val busFilterSlots = addFilterSlots(tile?.filter, StorageExporterBlockEntity.MAX_FILTERS) + val busFilterState = BooleanInputWithFeedback(this, tile?.let { it.filter::isWhitelist }) init { - if (tile != null) { - busFilterSlots = addFilterSlots(tile.filter) - busFilterState = BooleanInputWithFeedback(this, tile.filter::isWhitelist) - } else { - busFilterSlots = addFilterSlots(StorageExporterBlockEntity.MAX_FILTERS) - busFilterState = BooleanInputWithFeedback(this) - } - addInventorySlots() } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageImporterMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageImporterMenu.kt index 36415e95a..401bf92e6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageImporterMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/storage/StorageImporterMenu.kt @@ -1,32 +1,18 @@ package ru.dbotthepony.mc.otm.menu.storage 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.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.registry.MMenus -class StorageImporterMenu @JvmOverloads constructor( - p_38852_: Int, - inventory: Inventory, - tile: StorageImporterBlockEntity? = null -) : MatteryPoweredMenu( - MMenus.STORAGE_IMPORTER, p_38852_, inventory, tile -) { - val busFilterSlots: List - val busFilterState: BooleanInputWithFeedback +class StorageImporterMenu( + containerId: Int, inventory: Inventory, tile: StorageImporterBlockEntity? = null +) : MatteryPoweredMenu(MMenus.STORAGE_IMPORTER, containerId, inventory, tile) { + val busFilterSlots = addFilterSlots(tile?.filter, StorageImporterBlockEntity.MAX_FILTERS) + val busFilterState = BooleanInputWithFeedback(this, tile?.let { it.filter::isWhitelist }) init { - if (tile != null) { - busFilterSlots = addFilterSlots(tile.filter) - busFilterState = BooleanInputWithFeedback(this, tile.filter::isWhitelist) - } else { - busFilterSlots = addFilterSlots(StorageImporterBlockEntity.MAX_FILTERS) - busFilterState = BooleanInputWithFeedback(this) - } - addInventorySlots() } } 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 829d0fc6d..c49564815 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MenuNetworkChannel.kt @@ -5,11 +5,9 @@ import net.minecraft.network.FriendlyByteBuf import net.minecraft.world.item.ItemStack import net.minecraftforge.network.NetworkDirection import net.minecraftforge.network.NetworkEvent -import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.compat.InventoryScrollPacket -import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu import ru.dbotthepony.mc.otm.menu.matter.CancelTaskPacket import ru.dbotthepony.mc.otm.menu.MatteryMenu @@ -74,12 +72,11 @@ class SetCarriedPacket(val item: ItemStack) : MatteryPacket { } object MenuNetworkChannel : MatteryNetworkChannel( - version = "3", + version = "4", name = "menu" ) { fun register() { add(SetCarriedPacket::class.java, SetCarriedPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT) - add(ItemFilterSlotPacket::class.java, ItemFilterSlotPacket.Companion::read) // networked item view add(ClearItemViewPacket::class.java, { ClearItemViewPacket }, NetworkDirection.PLAY_TO_CLIENT)