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
This commit is contained in:
parent
30263bf30e
commit
f79b49d422
@ -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<FilteredContainerSlot>.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)
|
||||
}
|
||||
|
||||
|
@ -348,8 +348,6 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
|
||||
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override var slotFilter: Item? by slot.filter!!
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -18,10 +18,6 @@ open class InventorySlotPanel<out S : MatteryScreen<*>, out T : MatteryMenu.Inve
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
) : UserFilteredSlotPanel<S, T>(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)
|
||||
|
@ -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 S : MatteryScreen<*>, 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 S : MatteryScreen<*>, 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<Component>().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 <S : MatteryScreen<*>, T : Slot> BatterySlotPanel(
|
||||
|
@ -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 S : MatteryScreen<*>, out T : Slot>(
|
||||
open class UserFilteredSlotPanel<out S : MatteryScreen<*>, out T : UserFilteredSlot>(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
slot: T,
|
||||
@ -31,77 +19,24 @@ abstract class UserFilteredSlotPanel<out S : MatteryScreen<*>, out T : Slot>(
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
) : SlotPanel<S, T>(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<Component>().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 S : MatteryScreen<*>, 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 <S : MatteryScreen<*>, T : Slot> of(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
slot: T,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
filter: Delegate<Item?>
|
||||
): UserFilteredSlotPanel<S, T> {
|
||||
return object : UserFilteredSlotPanel<S, T>(screen, parent, slot, x, y, width, height) {
|
||||
override var slotFilter: Item? by filter
|
||||
}
|
||||
}
|
||||
|
||||
fun <S : MatteryScreen<*>, T : UserFilteredSlot> of(
|
||||
screen: S,
|
||||
parent: EditablePanel<*>?,
|
||||
slot: T,
|
||||
x: Float = 0f,
|
||||
y: Float = 0f,
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
): UserFilteredSlotPanel<S, T> {
|
||||
return object : UserFilteredSlotPanel<S, T>(screen, parent, slot, x, y, width, height) {
|
||||
override var slotFilter: Item?
|
||||
get() = slot.filter?.get()
|
||||
set(value) { slot.filter?.accept(value) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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<ItemStack> {
|
||||
if (this is IEnhancedContainer) {
|
||||
return iterator()
|
||||
|
@ -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<Item?>
|
||||
val field: Delegate<Item?>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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 <S : Slot> makeSlots(containers: List<Container>?, 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<ItemStack> {
|
||||
var hasSetFilter = false
|
||||
private set
|
||||
|
||||
var filter: Delegate<Item?>? = 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<Item?>? = 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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user