From f79b49d4221b63b7c6758396393424b4c9bdf721 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 28 Feb 2025 21:57:28 +0700 Subject: [PATCH] Move CargoCrate to SlottedContainer implement necessary changes to MatteryMenu, MatterySlot and panels to reflect networking slot filters as part of container state, and not as part of menu slot --- .../decorative/CargoCrateBlockEntity.kt | 30 +++-- .../mc/otm/client/screen/MatteryScreen.kt | 2 - .../screen/decorative/CargoCrateScreen.kt | 2 +- .../screen/panels/slot/InventorySlotPanel.kt | 4 - .../client/screen/panels/slot/SlotPanel.kt | 70 ++++++++++ .../panels/slot/UserFilteredSlotPanel.kt | 125 ++---------------- .../otm/client/screen/tech/ItemHatchScreen.kt | 2 +- .../otm/container/IAutomatedContainerSlot.kt | 2 +- .../otm/container/IFilteredContainerSlot.kt | 2 - .../mc/otm/container/slotted/ContainerSlot.kt | 2 +- .../mc/otm/container/util/Iterators.kt | 20 +++ .../ru/dbotthepony/mc/otm/menu/MatteryMenu.kt | 46 ++----- .../ru/dbotthepony/mc/otm/menu/Slots.kt | 61 ++++----- .../mc/otm/menu/decorative/CargoCrateMenu.kt | 3 +- 14 files changed, 170 insertions(+), 201 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/CargoCrateBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/CargoCrateBlockEntity.kt index 6d7b5c27c..fd17ee839 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/CargoCrateBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/decorative/CargoCrateBlockEntity.kt @@ -32,6 +32,8 @@ import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.HandlerFilter +import ru.dbotthepony.mc.otm.container.slotted.FilteredContainerSlot +import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.nbt.map import ru.dbotthepony.mc.otm.core.nbt.set @@ -43,20 +45,24 @@ class CargoCrateBlockEntity( p_155229_: BlockPos, p_155230_: BlockState ) : MatteryDeviceBlockEntity(MBlockEntities.CARGO_CRATE, p_155229_, p_155230_) { - val container = MatteryContainer(this::setChanged, CAPACITY).also(::addDroppableContainer) + private inner class Slot(container: SlottedContainer, slot: Int) : FilteredContainerSlot(container, slot) { + override fun canAutomationPlaceItem(itemStack: ItemStack): Boolean { + return super.canAutomationPlaceItem(itemStack) && lootTable == null + } + + override fun canAutomationTakeItem(desired: Int): Boolean { + return super.canAutomationTakeItem(desired) && lootTable == null + } + } + + val container = SlottedContainer.Builder() + .add(CAPACITY, ::Slot) + .onChanged(::setChanged) + .build() + .also(::addDroppableContainer) private var interactingPlayers = 0 - val handler = container.handler(object : HandlerFilter { - override fun canInsert(slot: Int, stack: ItemStack): Boolean { - return lootTable == null - } - - override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean { - return lootTable == null - } - }) - override fun beforeDroppingItems(oldBlockState: BlockState, level: Level, blockPos: BlockPos, newBlockState: BlockState, movedByPiston: Boolean) { unpackLootTable() } @@ -88,7 +94,7 @@ class CargoCrateBlockEntity( } init { - exposeGlobally(Capabilities.ItemHandler.BLOCK, handler) + exposeGlobally(Capabilities.ItemHandler.BLOCK, container) savetablesLevel.stateful(::container, INVENTORY_KEY) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt index 2eeccb3e4..b0fed5874 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatteryScreen.kt @@ -348,8 +348,6 @@ abstract class MatteryScreen(menu: T, inventory: Inventory, tit override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { return false } - - override var slotFilter: Item? by slot.filter!! } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/CargoCrateScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/CargoCrateScreen.kt index 26bb90d13..974878362 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/CargoCrateScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/decorative/CargoCrateScreen.kt @@ -20,7 +20,7 @@ class CargoCrateScreen(menu: CargoCrateMenu, inventory: Inventory, title: Compon val grid = GridPanel(this, frame, 8f, 18f, 9f * 18f, 6f * 18f, 9, 6) for (slot in menu.storageSlots) - UserFilteredSlotPanel.of(this, grid, slot) + UserFilteredSlotPanel(this, grid, slot) val controls = DeviceControls(this, frame) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/InventorySlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/InventorySlotPanel.kt index caa01f6aa..09588c48d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/InventorySlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/InventorySlotPanel.kt @@ -18,10 +18,6 @@ open class InventorySlotPanel, out T : MatteryMenu.Inve x: Float = 0f, y: Float = 0f, ) : UserFilteredSlotPanel(screen, parent, slot, x, y, SIZE, SIZE) { - override var slotFilter: Item? - get() = slot.filter?.get() - set(value) { slot.filter?.accept(value) } - override fun renderBackgroundBeforeFilter(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { if (slot.chargeFlag?.get() == true) { Widgets18.CHARGE_SLOT_BACKGROUND.render(graphics, 0f, 0f, width, height) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/SlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/SlotPanel.kt index e7139cff1..6453b8d7b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/SlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/SlotPanel.kt @@ -5,9 +5,13 @@ package ru.dbotthepony.mc.otm.client.screen.panels.slot import com.mojang.blaze3d.systems.RenderSystem import net.minecraft.ChatFormatting import net.minecraft.client.renderer.GameRenderer +import net.minecraft.network.chat.Component import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.inventory.Slot import net.minecraft.world.item.ItemStack +import net.minecraft.world.item.Items +import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions +import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.render.Widgets18 @@ -15,6 +19,10 @@ import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.compat.itemborders.isItemBordersLoaded import ru.dbotthepony.mc.otm.compat.itemborders.renderSlotBorder +import ru.dbotthepony.mc.otm.container.IFilteredContainerSlot +import ru.dbotthepony.mc.otm.container.util.containerSlotOrNull +import ru.dbotthepony.mc.otm.core.TextComponent +import ru.dbotthepony.mc.otm.core.TranslatableComponent import javax.annotation.Nonnull import kotlin.math.roundToInt @@ -52,6 +60,31 @@ open class SlotPanel, out T : Slot>( } } + protected open fun renderBackgroundBeforeFilter(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {} + + override fun renderSlotBackground(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { + super.renderSlotBackground(graphics, mouseX, mouseY, partialTick) + + val containerSlot = slot.container.containerSlotOrNull(slot.slotIndex) + + if (containerSlot is IFilteredContainerSlot) { + renderBackgroundBeforeFilter(graphics, mouseX, mouseY, partialTick) + + if (containerSlot.filter !== null) { + if (containerSlot.filter !== Items.AIR) { + val itemStack = ItemStack(containerSlot.filter!!, 1) + + screen.renderItemStack(graphics, itemStack, null) + clearDepth(graphics) + + graphics.renderRect(0f, 0f, width, height, color = SLOT_FILTER_COLOR) + } else { + graphics.renderRect(0f, 0f, width, height, color = SLOT_BLOCK_COLOR) + } + } + } + } + override fun innerRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { slot.x = absoluteX.roundToInt() - screen.guiLeft slot.y = absoluteY.roundToInt() - screen.guiTop @@ -121,9 +154,46 @@ open class SlotPanel, out T : Slot>( } override fun innerRenderTooltips(@Nonnull graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean { + val slot = slot.container.containerSlotOrNull(slot.containerSlot) as? IFilteredContainerSlot + + if (isHovered && slot?.filter != null && slot.filter !== Items.AIR && itemStack.isEmpty) { + val itemstack = ItemStack(slot.filter!!, 1) + + graphics.renderComponentTooltip( + IClientItemExtensions.of(itemstack).getFont(itemstack, IClientItemExtensions.FontContext.TOOLTIP) ?: font, + getItemStackTooltip(itemstack).toMutableList().also { + it.add(0, TranslatableComponent("otm.gui.slot_filter.filtered").withStyle(ChatFormatting.GRAY)) + it.add(1, TranslatableComponent("otm.gui.slot_filter.hint").withStyle(ChatFormatting.GRAY)) + it.add(2, TextComponent("")) + }, + mouseX.toInt(), + mouseY.toInt(), + itemstack + ) + + return true + } else if (isHovered && slot?.filter === Items.AIR && itemStack.isEmpty) { + graphics.renderComponentTooltip( + font, + ArrayList().also { + it.add(TranslatableComponent("otm.gui.slot_filter.forbidden").withStyle(ChatFormatting.GRAY)) + it.add(TranslatableComponent("otm.gui.slot_filter.hint").withStyle(ChatFormatting.GRAY)) + }, + mouseX.toInt(), + mouseY.toInt() + ) + + return true + } + // no op, screen does it for us (completely) return false } + + companion object { + val SLOT_FILTER_COLOR = RGBAColor(85, 113, 216, 150) + val SLOT_BLOCK_COLOR = RGBAColor(219, 113, 113, 150) + } } fun , T : Slot> BatterySlotPanel( diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/UserFilteredSlotPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/UserFilteredSlotPanel.kt index 86c93d76a..8fdb61822 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/UserFilteredSlotPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/slot/UserFilteredSlotPanel.kt @@ -1,28 +1,16 @@ package ru.dbotthepony.mc.otm.client.screen.panels.slot import com.mojang.blaze3d.platform.InputConstants -import net.minecraft.ChatFormatting -import net.minecraft.network.chat.Component -import net.minecraft.world.inventory.Slot -import net.minecraft.world.item.Item -import net.minecraft.world.item.ItemStack -import net.minecraft.world.item.Items -import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions -import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.isCtrlDown import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.playGuiClickSound import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel -import ru.dbotthepony.mc.otm.core.TextComponent -import ru.dbotthepony.mc.otm.core.TranslatableComponent -import ru.dbotthepony.kommons.math.RGBAColor -import ru.dbotthepony.kommons.util.Delegate -import ru.dbotthepony.kommons.util.getValue -import ru.dbotthepony.kommons.util.setValue +import ru.dbotthepony.mc.otm.container.IFilteredContainerSlot +import ru.dbotthepony.mc.otm.container.util.containerSlot import ru.dbotthepony.mc.otm.menu.UserFilteredSlot -abstract class UserFilteredSlotPanel, out T : Slot>( +open class UserFilteredSlotPanel, out T : UserFilteredSlot>( screen: S, parent: EditablePanel<*>?, slot: T, @@ -31,77 +19,24 @@ abstract class UserFilteredSlotPanel, out T : Slot>( width: Float = SIZE, height: Float = SIZE, ) : SlotPanel(screen, parent, slot, x, y, width, height) { - abstract var slotFilter: Item? - - protected open fun renderBackgroundBeforeFilter(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {} - - override fun renderSlotBackground(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) { - super.renderSlotBackground(graphics, mouseX, mouseY, partialTick) - - renderBackgroundBeforeFilter(graphics, mouseX, mouseY, partialTick) - - if (slotFilter != null) { - if (slotFilter !== Items.AIR) { - val itemStack = ItemStack(slotFilter!!, 1) - - screen.renderItemStack(graphics, itemStack, null) - clearDepth(graphics) - - graphics.renderRect(0f, 0f, width, height, color = SLOT_FILTER_COLOR) - } else { - graphics.renderRect(0f, 0f, width, height, color = SLOT_BLOCK_COLOR) - } - } - } - - override fun innerRenderTooltips(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean { - if (isHovered && slotFilter != null && slotFilter !== Items.AIR && itemStack.isEmpty) { - val itemstack = ItemStack(slotFilter!!, 1) - - graphics.renderComponentTooltip( - IClientItemExtensions.of(itemstack).getFont(itemstack, IClientItemExtensions.FontContext.TOOLTIP) ?: font, - getItemStackTooltip(itemstack).toMutableList().also { - it.add(0, TranslatableComponent("otm.gui.slot_filter.filtered").withStyle(ChatFormatting.GRAY)) - it.add(1, TranslatableComponent("otm.gui.slot_filter.hint").withStyle(ChatFormatting.GRAY)) - it.add(2, TextComponent("")) - }, - mouseX.toInt(), - mouseY.toInt(), - itemstack - ) - - return true - } else if (isHovered && slotFilter === Items.AIR && itemStack.isEmpty) { - graphics.renderComponentTooltip( - font, - ArrayList().also { - it.add(TranslatableComponent("otm.gui.slot_filter.forbidden").withStyle(ChatFormatting.GRAY)) - it.add(TranslatableComponent("otm.gui.slot_filter.hint").withStyle(ChatFormatting.GRAY)) - }, - mouseX.toInt(), - mouseY.toInt() - ) - - return true - } - - return super.innerRenderTooltips(graphics, mouseX, mouseY, partialTick) - } - override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { + if (slot.filterInput == null) + return super.mouseClickedInner(x, y, button) + + val containerSlot = slot.containerSlot() as IFilteredContainerSlot + if (button == InputConstants.MOUSE_BUTTON_LEFT && minecraft.window.isCtrlDown) { - if (slotFilter === null) { + if (containerSlot.filter === null) { if (screen.menu.carried.isEmpty) { - slotFilter = slot.item.item + slot.filterInput!!.accept(slot.item.item) } else { - slotFilter = screen.menu.carried.item + slot.filterInput!!.accept(screen.menu.carried.item) } } else { - slotFilter = null + slot.filterInput!!.accept(null) } playGuiClickSound() - return true } else { return super.mouseClickedInner(x, y, button) @@ -115,40 +50,4 @@ abstract class UserFilteredSlotPanel, out T : Slot>( return super.mouseReleasedInner(x, y, button) } - - companion object { - val SLOT_FILTER_COLOR = RGBAColor(85, 113, 216, 150) - val SLOT_BLOCK_COLOR = RGBAColor(219, 113, 113, 150) - - fun , T : Slot> of( - screen: S, - parent: EditablePanel<*>?, - slot: T, - x: Float = 0f, - y: Float = 0f, - width: Float = SIZE, - height: Float = SIZE, - filter: Delegate - ): UserFilteredSlotPanel { - return object : UserFilteredSlotPanel(screen, parent, slot, x, y, width, height) { - override var slotFilter: Item? by filter - } - } - - fun , T : UserFilteredSlot> of( - screen: S, - parent: EditablePanel<*>?, - slot: T, - x: Float = 0f, - y: Float = 0f, - width: Float = SIZE, - height: Float = SIZE, - ): UserFilteredSlotPanel { - return object : UserFilteredSlotPanel(screen, parent, slot, x, y, width, height) { - override var slotFilter: Item? - get() = slot.filter?.get() - set(value) { slot.filter?.accept(value) } - } - } - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ItemHatchScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ItemHatchScreen.kt index 7408515ea..913f5bdbf 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ItemHatchScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/tech/ItemHatchScreen.kt @@ -20,7 +20,7 @@ class ItemHatchScreen(menu: ItemHatchMenu, inventory: Inventory, title: Componen val grid = GridPanel(this, frame, 8f, 18f, 9f * 18f, 6f * 18f, 9, 6) for (slot in menu.storageSlots) - UserFilteredSlotPanel.of(this, grid, slot) + UserFilteredSlotPanel(this, grid, slot) if (menu.isInput) { val controls = DeviceControls(this, frame) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainerSlot.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainerSlot.kt index 16ca182f2..2c7df2085 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainerSlot.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IAutomatedContainerSlot.kt @@ -4,7 +4,7 @@ import net.minecraft.world.item.ItemStack import net.neoforged.neoforge.items.IItemHandler /** - * Slot of [ISlottedContainer], with additional methods to implement interaction behavior for both for players and mechanisms + * Slot of [IAutomatedContainer], with additional methods to implement interaction behavior for both for players and mechanisms */ interface IAutomatedContainerSlot : IContainerSlot { fun canAutomationPlaceItem(itemStack: ItemStack): Boolean { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredContainerSlot.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredContainerSlot.kt index 0eaa8ee8f..1a6c6f250 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredContainerSlot.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/IFilteredContainerSlot.kt @@ -1,6 +1,5 @@ package ru.dbotthepony.mc.otm.container -import net.minecraft.world.Container import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Items @@ -15,7 +14,6 @@ interface IFilteredContainerSlot : IContainerSlot { val hasFilter: Boolean get() = filter != null - fun testSlotFilter(itemStack: ItemStack): Boolean { return testSlotFilter(itemStack.item) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/ContainerSlot.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/ContainerSlot.kt index 7ab61cebd..18109d9be 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/ContainerSlot.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/slotted/ContainerSlot.kt @@ -83,7 +83,7 @@ open class ContainerSlot( return ItemStack.EMPTY } - if (item.count >= count) { + if (item.count <= count) { this.item = ItemStack.EMPTY return item } else { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/util/Iterators.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/util/Iterators.kt index 64f4a9b73..9160415c9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/util/Iterators.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/util/Iterators.kt @@ -1,6 +1,7 @@ package ru.dbotthepony.mc.otm.container.util import net.minecraft.world.Container +import net.minecraft.world.inventory.Slot import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.container.IContainerSlot @@ -19,6 +20,25 @@ fun Container.containerSlot(slot: Int): IContainerSlot { } } +/** + * Returns [IContainerSlot] only if this container is [IEnhancedContainer] + */ +fun Container.containerSlotOrNull(slot: Int): IContainerSlot? { + if (this is IEnhancedContainer) { + return containerSlot(slot) + } else { + return null + } +} + +fun Slot.containerSlot(): IContainerSlot { + return container.containerSlot(slotIndex) +} + +fun Slot.containerSlotOrNull(): IContainerSlot? { + return container.containerSlotOrNull(slotIndex) +} + operator fun Container.iterator(): Iterator { if (this is IEnhancedContainer) { return iterator() 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 5c7ed9174..9bff7873a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatteryMenu.kt @@ -38,9 +38,11 @@ import ru.dbotthepony.mc.otm.capability.matteryPlayer 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.IFilteredContainerSlot import ru.dbotthepony.mc.otm.container.IMatteryContainer import ru.dbotthepony.mc.otm.container.computeSortedIndices import ru.dbotthepony.mc.otm.container.sortWithIndices +import ru.dbotthepony.mc.otm.container.util.containerSlotOrNull import ru.dbotthepony.mc.otm.core.ResourceLocation import ru.dbotthepony.mc.otm.core.collect.ConditionalSet import ru.dbotthepony.mc.otm.core.math.Decimal @@ -207,7 +209,7 @@ abstract class MatteryMenu( var sortInventoryInput: SortInput? = null private set - val playerSortSettings = IItemStackSortingSettings.inputs(this, player.matteryPlayer?.sortingSettings) + val playerSortSettings = IItemStackSortingSettings.inputs(this, player.matteryPlayer.sortingSettings) var offhandSlot: InventorySlot? = null protected set @@ -221,7 +223,7 @@ abstract class MatteryMenu( protected var inventorySlotIndexStart = 0 protected var inventorySlotIndexEnd = 0 - open inner class InventorySlot(container: Container, index: Int, addFilter: Boolean = false) : UserFilteredSlot(container, index, 0, 0) { + open inner class InventorySlot(container: Container, index: Int) : UserFilteredSlot(container, index, 0, 0) { override fun mayPlace(itemStack: ItemStack): Boolean { return !isInventorySlotLocked(index) && super.mayPlace(itemStack) } @@ -236,15 +238,6 @@ abstract class MatteryMenu( init { val mattery = player.matteryPlayer - if (addFilter) { - val mContainer = container as IMatteryContainer - - filter = Delegate.Of( - getter = { mContainer.getSlotFilter(slotIndex) }, - setter = nullableItemInput(true) { mContainer.setSlotFilter(slotIndex, it) }::accept - ) - } - if (mattery.hasExopack) { chargeFlag = Delegate.Of( getter = { slotIndex in mattery.slotsChargeFlag }, @@ -302,7 +295,7 @@ abstract class MatteryMenu( for (i in 0 until if (mattery.hasExopack) mattery.combinedInventory.containerSize else mattery.wrappedItemInventory.containerSize) { if (i in Inventory.INVENTORY_SIZE until player.inventory.containerSize) continue - val slot = InventorySlot(mattery.combinedInventory, i, true) + val slot = InventorySlot(mattery.combinedInventory, i) _playerInventorySlots.add(slot) @@ -392,21 +385,8 @@ abstract class MatteryMenu( if (!seenSlots.add(pSlot)) return pSlot - if (pSlot is UserFilteredSlot && !pSlot.hasSetFilter) { - val container = pSlot.container - - val input: PlayerInput - val field: Delegate - - if (container is IMatteryContainer) { - input = PlayerInput(StreamCodecs.ITEM_TYPE_NULLABLE, handler = { container.setSlotFilter(pSlot.slotIndex, it) }) - field = mSynchronizer.add(delegate = { container.getSlotFilter(pSlot.slotIndex) }, StreamCodecs.ITEM_TYPE_NULLABLE) - } else { - input = PlayerInput(StreamCodecs.ITEM_TYPE_NULLABLE, handler = { throw UnsupportedOperationException() }) - field = mSynchronizer.add(delegate = { null }, StreamCodecs.ITEM_TYPE_NULLABLE) - } - - pSlot.filter = Delegate.Of(getter = field::get, setter = input::accept) + if (pSlot is MatterySlot) { + pSlot.setupNetworkControls(this) } return super.addSlot(pSlot) @@ -487,7 +467,7 @@ abstract class MatteryMenu( val copy = slot.item.copy() var any = false - if (target.any { it.any { it is UserFilteredSlot && it.filter != null } }) { + if (target.any { it.any { it.containerSlotOrNull() is IFilteredContainerSlot } }) { for (collection in target) { if (moveItemStackTo(slot, collection, onlyFiltered = true)) { any = true @@ -582,9 +562,9 @@ abstract class MatteryMenu( // first pass - stack with existing slots if (copy.isStackable) { for (slot in slots) { - if (onlyFiltered && (slot !is UserFilteredSlot || !slot.test(item))) { + if (onlyFiltered && slot.containerSlotOrNull().let { it !is IFilteredContainerSlot || it.filter == null || !it.testSlotFilter(item) }) { continue - } else if (!onlyFiltered && slot is UserFilteredSlot && !slot.test(item)) { + } else if (!onlyFiltered && slot.containerSlotOrNull().let { it is IFilteredContainerSlot && it.filter != null }) { continue } @@ -609,9 +589,9 @@ abstract class MatteryMenu( // second pass - drop stack into first free slot for (slot in slots) { - if (onlyFiltered && (slot !is UserFilteredSlot || slot.filter == null || slot.filter!!.get() != item.item)) { + if (onlyFiltered && slot.containerSlotOrNull().let { it !is IFilteredContainerSlot || it.filter == null || !it.testSlotFilter(item) }) { continue - } else if (!onlyFiltered && slot is UserFilteredSlot && slot.filter != null && slot.filter!!.get() != null && slot.filter!!.get() != item.item) { + } else if (!onlyFiltered && slot.containerSlotOrNull().let { it is IFilteredContainerSlot && it.filter != null }) { continue } @@ -651,7 +631,7 @@ abstract class MatteryMenu( val slot = slots[i] slots.add(slot) - if (slot is InventorySlot && slot.filter != null) { + if (slot.containerSlotOrNull() is IFilteredContainerSlot) { filters = true } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt index bf6ee95a6..e436740f1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt @@ -17,20 +17,22 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.UpgradeType import ru.dbotthepony.mc.otm.capability.energy import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.mc.otm.container.IFilteredContainerSlot import ru.dbotthepony.mc.otm.container.IMatteryContainer import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.UpgradeContainer +import ru.dbotthepony.mc.otm.container.util.containerSlotOrNull import ru.dbotthepony.mc.otm.core.collect.ConditionalEnumSet import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.InstantBooleanInput +import ru.dbotthepony.mc.otm.network.StreamCodecs import ru.dbotthepony.mc.otm.runOnClient import java.util.* import java.util.function.BooleanSupplier import java.util.function.DoubleSupplier import java.util.function.IntSupplier -import java.util.function.Predicate import java.util.function.Supplier import kotlin.reflect.KMutableProperty0 @@ -51,6 +53,14 @@ inline fun makeSlots(containers: List?, size: Int, initial open class MatterySlot(container: Container, index: Int, x: Int = 0, y: Int = 0) : Slot(container, index, x, y) { var ignoreSpectators = true + open fun setupNetworkControls(menu: MatteryMenu) { + val slot = containerSlotOrNull() + + if (slot is IFilteredContainerSlot) { + menu.mSynchronizer.add(Delegate.Of(slot::filter), StreamCodecs.ITEM_TYPE_NULLABLE) + } + } + override fun setChanged() { if (container is IMatteryContainer) { (container as IMatteryContainer).setChanged(containerSlot) @@ -68,7 +78,7 @@ open class MatterySlot(container: Container, index: Int, x: Int = 0, y: Int = 0) } open fun canTakeItemForPickAll(): Boolean { - return true + return (container.containerSlotOrNull(slotIndex) as? IFilteredContainerSlot)?.filter == null } override fun getMaxStackSize(): Int { @@ -90,38 +100,29 @@ open class MatterySlot(container: Container, index: Int, x: Int = 0, y: Int = 0) return super.getMaxStackSize(itemStack) } } -} -open class UserFilteredSlot(container: Container, index: Int, x: Int = 0, y: Int = 0) : MatterySlot(container, index, x, y), Predicate { - var hasSetFilter = false - private set - - var filter: Delegate? = null - set(value) { - hasSetFilter = true - field = value - } - - override fun canTakeItemForPickAll(): Boolean { - return filter?.get() == null - } - - override fun test(t: ItemStack): Boolean { - return filter?.get() == null || filter?.get() == t.item - } - - fun isSameFilter(other: Slot): Boolean { - if (other !is UserFilteredSlot) - return filter?.get() == null - - return ( - (other.filter == null && filter == null) || - (other.filter != null && filter != null && other.filter!!.get() == filter!!.get()) - ) + private fun isSameFilter(other: Slot): Boolean { + val sSelf = containerSlotOrNull() as? IFilteredContainerSlot + val sOther = other.containerSlotOrNull() as? IFilteredContainerSlot + return sSelf?.filter == sOther?.filter } override fun isSameInventory(other: Slot): Boolean { - return isSameFilter(other) && super.isSameInventory(other) + return super.isSameInventory(other) && isSameFilter(other) + } +} + +open class UserFilteredSlot(container: Container, index: Int, x: Int = 0, y: Int = 0) : MatterySlot(container, index, x, y) { + var filterInput: MatteryMenu.PlayerInput? = null + private set + + override fun setupNetworkControls(menu: MatteryMenu) { + super.setupNetworkControls(menu) + val slot = containerSlotOrNull() + + if (slot is IFilteredContainerSlot) { + filterInput = menu.PlayerInput(StreamCodecs.ITEM_TYPE_NULLABLE, handler = { slot.filter = it }) + } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/CargoCrateMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/CargoCrateMenu.kt index 2dc02ccf9..4d997dcf9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/CargoCrateMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/decorative/CargoCrateMenu.kt @@ -5,6 +5,7 @@ import net.minecraft.world.SimpleContainer import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity +import ru.dbotthepony.mc.otm.container.slotted.SlottedContainer import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.UserFilteredSlot import ru.dbotthepony.mc.otm.menu.makeSlots @@ -15,7 +16,7 @@ class CargoCrateMenu( inventory: Inventory, tile: CargoCrateBlockEntity? = null ) : MatteryMenu(MMenus.CARGO_CRATE, containerId, inventory, tile) { - val actualContainer: Container = tile?.container ?: SimpleContainer(CargoCrateBlockEntity.CAPACITY) + val actualContainer = tile?.container ?: SlottedContainer.filtered(CargoCrateBlockEntity.CAPACITY) val storageSlots = makeSlots(actualContainer, ::UserFilteredSlot) private val trackedPlayerOpen = !inventory.player.isSpectator