Update ItemFilter to behave like it did previously, with fixed amount of slots but still being immutable

This commit is contained in:
DBotThePony 2024-08-12 20:18:39 +07:00
parent aa5d36c488
commit 5b4fa2e9ed
Signed by: DBot
GPG Key ID: DCC23B5715498507
11 changed files with 161 additions and 89 deletions

View File

@ -122,13 +122,15 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
}) })
} }
val filter = ItemFilter(MAX_FILTERS) { var filter = ItemFilter(MAX_FILTERS)
component?.scan() set(value) {
markDirtyFast() field = value
} component?.scan()
markDirtyFast()
}
init { init {
savetables.stateful(::filter, FILTER_KEY) savetables.codec(::filter, ItemFilter.CODEC, FILTER_KEY)
} }
override fun setLevel(level: Level) { override fun setLevel(level: Level) {

View File

@ -97,10 +97,11 @@ abstract class AbstractStorageImportExport(
protected val target = CapabilityCache(RelativeSide.FRONT, Capabilities.ItemHandler.BLOCK) protected val target = CapabilityCache(RelativeSide.FRONT, Capabilities.ItemHandler.BLOCK)
var filter: ItemFilter = ItemFilter.EMPTY var filter: ItemFilter = ItemFilter(MAX_FILTERS)
set(value) { set(value) {
if (value != field) { if (value != field) {
field = value field = value
markDirtyFast()
itemFilterUpdated() itemFilterUpdated()
} }
} }
@ -115,6 +116,7 @@ abstract class AbstractStorageImportExport(
companion object { companion object {
const val FILTER_KEY = "filter" const val FILTER_KEY = "filter"
const val MAX_FILTERS = 6 * 3
} }
} }
@ -263,7 +265,6 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
} }
lastSlot = 0 lastSlot = 0
markDirtyFast()
} }
private var lastSlot = 0 private var lastSlot = 0

View File

@ -73,7 +73,7 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp
it.dock = Dock.LEFT it.dock = Dock.LEFT
CheckBoxLabelInputPanel(this, it, menu.isWhitelist, TranslatableComponent("otm.gui.filter.is_whitelist")).also { it.dockTop = 20f; it.dock = Dock.TOP } CheckBoxLabelInputPanel(this, it, menu.isWhitelist, TranslatableComponent("otm.gui.filter.is_whitelist")).also { it.dockTop = 20f; it.dock = Dock.TOP }
CheckBoxLabelInputPanel(this, it, menu.matchTag, TranslatableComponent("otm.gui.filter.match_tag")).also { it.dockTop = 4f; it.dock = Dock.TOP } CheckBoxLabelInputPanel(this, it, menu.matchTag, TranslatableComponent("otm.gui.filter.match_tag")).also { it.dockTop = 4f; it.dock = Dock.TOP }
CheckBoxLabelInputPanel(this, it, menu.matchNBT, TranslatableComponent("otm.gui.filter.match_nbt")).also { it.dockTop = 4f; it.dock = Dock.TOP } CheckBoxLabelInputPanel(this, it, menu.matchComponents, TranslatableComponent("otm.gui.filter.match_nbt")).also { it.dockTop = 4f; it.dock = Dock.TOP }
}) })
frame.Tab(view, activeIcon = ItemStackIcon(ItemStack(MItems.PORTABLE_CONDENSATION_DRIVE))) frame.Tab(view, activeIcon = ItemStackIcon(ItemStack(MItems.PORTABLE_CONDENSATION_DRIVE)))

View File

@ -8,10 +8,8 @@ import ru.dbotthepony.mc.otm.client.screen.panels.*
import ru.dbotthepony.mc.otm.client.screen.panels.button.CheckBoxLabelInputPanel import ru.dbotthepony.mc.otm.client.screen.panels.button.CheckBoxLabelInputPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.BatterySlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.FilterSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.FilterSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
import ru.dbotthepony.mc.otm.menu.storage.StorageImporterExporterMenu import ru.dbotthepony.mc.otm.menu.storage.StorageImporterExporterMenu
@ -26,23 +24,23 @@ class StorageImporterExporterScreen(menu: StorageImporterExporterMenu, inventory
val grid = GridPanel(this, right, columns = 6, rows = 3, height = AbstractSlotPanel.SIZE * 3f) val grid = GridPanel(this, right, columns = 6, rows = 3, height = AbstractSlotPanel.SIZE * 3f)
grid.dock = Dock.TOP grid.dock = Dock.TOP
for (slot in menu.filterSlots) { for (slot in menu.filter.slots) {
FilterSlotPanel(this, grid, slot) FilterSlotPanel(this, grid, slot)
} }
CheckBoxLabelInputPanel(this, right, menu.isWhitelist, TranslatableComponent("otm.gui.filter.is_whitelist")).also { CheckBoxLabelInputPanel(this, right, menu.filter.isWhitelist, TranslatableComponent("otm.gui.filter.is_whitelist")).also {
it.dock = Dock.BOTTOM it.dock = Dock.BOTTOM
it.dockTop = 2f it.dockTop = 2f
it.childrenOrder = -1 it.childrenOrder = -1
} }
CheckBoxLabelInputPanel(this, right, menu.matchNBT, TranslatableComponent("otm.gui.filter.match_nbt")).also { CheckBoxLabelInputPanel(this, right, menu.filter.matchComponents, TranslatableComponent("otm.gui.filter.match_nbt")).also {
it.dock = Dock.BOTTOM it.dock = Dock.BOTTOM
it.dockTop = 2f it.dockTop = 2f
it.childrenOrder = -2 it.childrenOrder = -2
} }
CheckBoxLabelInputPanel(this, right, menu.matchTag, TranslatableComponent("otm.gui.filter.match_tag")).also { CheckBoxLabelInputPanel(this, right, menu.filter.matchTag, TranslatableComponent("otm.gui.filter.match_tag")).also {
it.dock = Dock.BOTTOM it.dock = Dock.BOTTOM
it.dockTop = 2f it.dockTop = 2f
it.childrenOrder = -3 it.childrenOrder = -3

View File

@ -1,36 +1,48 @@
package ru.dbotthepony.mc.otm.container package ru.dbotthepony.mc.otm.container
import com.google.common.collect.ImmutableList
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import it.unimi.dsi.fastutil.objects.ObjectArrayList
import net.minecraft.tags.TagKey import net.minecraft.tags.TagKey
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
data class ItemFilter(val filter: List<ItemStack>, val isWhitelist: Boolean = false, val matchTag: Boolean = false, val matchComponents: Boolean = false) { class ItemFilter private constructor(private val filter: Array<ItemStack>, val isWhitelist: Boolean, val matchTag: Boolean, val matchComponents: Boolean) {
fun add(item: ItemStack): ItemFilter { constructor(size: Int, isWhitelist: Boolean = false, matchTag: Boolean = false, matchComponents: Boolean = false) : this(Array(size) { ItemStack.EMPTY }, isWhitelist, matchTag, matchComponents)
if (filter.any { ItemStack.isSameItemSameComponents(it, item) }) constructor(list: List<ItemStack>, isWhitelist: Boolean = false, matchTag: Boolean = false, matchComponents: Boolean = false) : this(list.toTypedArray(), isWhitelist, matchTag, matchComponents)
override fun equals(other: Any?): Boolean {
return this === other || other is ItemFilter &&
this.filter.contentEquals(other.filter) &&
this.isWhitelist == other.isWhitelist &&
this.matchTag == other.matchTag &&
this.matchComponents == other.matchComponents
}
override fun hashCode(): Int {
return filter.contentHashCode()
}
val size: Int
get() = filter.size
fun set(index: Int, value: ItemStack): ItemFilter {
if (ItemStack.isSameItemSameComponents(filter[index], value) || filter.any { ItemStack.isSameItemSameComponents(it, value) })
return this return this
return copy( return copy(filter.copyOf().also { it[index] = value })
filter = ArrayList(filter).also { it.add(item) }
)
} }
fun remove(item: ItemStack): ItemFilter { operator fun get(index: Int): ItemStack {
val indexOf = filter.indexOfFirst { ItemStack.isSameItemSameComponents(it, item) } return filter[index]
if (indexOf == -1)
return this
return copy(
filter = ArrayList(filter).also { it.removeAt(indexOf) }
)
} }
fun get(index: Int): ItemStack { private fun copy(
return filter.getOrElse(index) { ItemStack.EMPTY } filter: Array<ItemStack> = this.filter,
} isWhitelist: Boolean = this.isWhitelist,
matchTag: Boolean = this.matchTag,
matchComponents: Boolean = this.matchComponents,
) = ItemFilter(filter, isWhitelist, matchTag, matchComponents)
fun isWhitelist(flag: Boolean): ItemFilter { fun isWhitelist(flag: Boolean): ItemFilter {
if (flag == isWhitelist) if (flag == isWhitelist)
@ -96,12 +108,12 @@ data class ItemFilter(val filter: List<ItemStack>, val isWhitelist: Boolean = fa
} }
companion object { companion object {
val EMPTY = ItemFilter(ImmutableList.of()) val EMPTY = ItemFilter(0)
val CODEC: Codec<ItemFilter> by lazy { val CODEC: Codec<ItemFilter> by lazy {
RecordCodecBuilder.create<ItemFilter> { RecordCodecBuilder.create<ItemFilter> {
it.group( it.group(
Codec.list(ItemStack.CODEC, 0, 40).fieldOf("filter").forGetter { it.filter }, Codec.list(ItemStack.CODEC, 0, 40).fieldOf("filter").forGetter { ObjectArrayList.wrap(it.filter) },
Codec.BOOL.optionalFieldOf("isWhitelist", false).forGetter { it.isWhitelist }, Codec.BOOL.optionalFieldOf("isWhitelist", false).forGetter { it.isWhitelist },
Codec.BOOL.optionalFieldOf("matchTag", false).forGetter { it.matchTag }, Codec.BOOL.optionalFieldOf("matchTag", false).forGetter { it.matchTag },
Codec.BOOL.optionalFieldOf("matchComponents", false).forGetter { it.matchComponents }, Codec.BOOL.optionalFieldOf("matchComponents", false).forGetter { it.matchComponents },

View File

@ -55,8 +55,19 @@ class PortableCondensationDriveItem(capacity: Int) : Item(Properties().stacksTo(
}, this) }, this)
} }
fun getFilterSettings(item: ItemStack): ItemFilter {
return item.getOrDefault(MDataComponentTypes.ITEM_FILTER, EMPTY_FILTER)
}
fun setFilterSettings(item: ItemStack, filter: ItemFilter) {
item.set(MDataComponentTypes.ITEM_FILTER, filter)
}
@Suppress("unused") @Suppress("unused")
companion object { companion object {
const val MAX_FILTERS = 4 * 3
private val EMPTY_FILTER = ItemFilter(MAX_FILTERS)
fun onPickupEvent(event: ItemEntityPickupEvent.Pre) { fun onPickupEvent(event: ItemEntityPickupEvent.Pre) {
if (event.itemEntity.owner != null && event.itemEntity.owner != event.player && event.itemEntity.age < 200 || event.itemEntity.item.isEmpty) { if (event.itemEntity.owner != null && event.itemEntity.owner != event.player && event.itemEntity.age < 200 || event.itemEntity.item.isEmpty) {
return return

View File

@ -25,7 +25,6 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.enchantment.EnchantmentEffectComponents import net.minecraft.world.item.enchantment.EnchantmentEffectComponents
import net.minecraft.world.item.enchantment.EnchantmentHelper import net.minecraft.world.item.enchantment.EnchantmentHelper
import net.minecraft.world.item.enchantment.Enchantments
import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.entity.BlockEntity
import net.neoforged.neoforge.network.PacketDistributor import net.neoforged.neoforge.network.PacketDistributor
import net.neoforged.neoforge.network.handling.IPayloadContext import net.neoforged.neoforge.network.handling.IPayloadContext
@ -42,7 +41,6 @@ import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorSlots
import ru.dbotthepony.mc.otm.compat.curios.curiosSlots import ru.dbotthepony.mc.otm.compat.curios.curiosSlots
import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot
import ru.dbotthepony.mc.otm.container.IMatteryContainer 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.UpgradeContainer
import ru.dbotthepony.mc.otm.container.computeSortedIndices import ru.dbotthepony.mc.otm.container.computeSortedIndices
import ru.dbotthepony.mc.otm.container.sortWithIndices import ru.dbotthepony.mc.otm.container.sortWithIndices
@ -241,42 +239,6 @@ abstract class MatteryMenu(
protected var inventorySlotIndexStart = 0 protected var inventorySlotIndexStart = 0
protected var inventorySlotIndexEnd = 0 protected var inventorySlotIndexEnd = 0
fun addFilterSlots(slots: ItemFilter): List<Delegate<ItemStack>> {
val result = ArrayList<Delegate<ItemStack>>(slots.size)
for (i in 0 until slots.size) {
result.add(Delegate.Of(
mSynchronizer.computedItem { slots[i] },
itemStackInput { slots[i] = it }
))
}
return result
}
fun addFilterSlots(amount: Int): List<Delegate<ItemStack>> {
val result = ArrayList<Delegate<ItemStack>>(amount)
for (i in 0 until amount) {
result.add(Delegate.Of(
mSynchronizer.computedItem { ItemStack.EMPTY },
itemStackInput { throw UnsupportedOperationException() }
))
}
return result
}
fun addFilterSlots(slots: ItemFilter?, amount: Int): List<Delegate<ItemStack>> {
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, addFilter: Boolean = false) : UserFilteredSlot(container, index, 0, 0) { open inner class InventorySlot(container: Container, index: Int, addFilter: Boolean = false) : UserFilteredSlot(container, index, 0, 0) {
override fun mayPlace(itemStack: ItemStack): Boolean { override fun mayPlace(itemStack: ItemStack): Boolean {
return !isInventorySlotLocked(index) && super.mayPlace(itemStack) return !isInventorySlotLocked(index) && super.mayPlace(itemStack)

View File

@ -9,14 +9,19 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.neoforged.neoforge.capabilities.Capabilities import net.neoforged.neoforge.capabilities.Capabilities
import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy import ru.dbotthepony.mc.otm.capability.energy
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.container.IMatteryContainer import ru.dbotthepony.mc.otm.container.IMatteryContainer
import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.runOnClient import ru.dbotthepony.mc.otm.runOnClient
import java.util.ArrayList
import java.util.function.Predicate import java.util.function.Predicate
import kotlin.reflect.KMutableProperty0
/** /**
* Make slots for single container * Make slots for single container
@ -159,3 +164,62 @@ open class DriveSlot(container: Container, index: Int, x: Int = 0, y: Int = 0) :
return super.mayPlace(itemStack) && itemStack.getCapability(MatteryCapability.CONDENSATION_DRIVE) != null return super.mayPlace(itemStack) && itemStack.getCapability(MatteryCapability.CONDENSATION_DRIVE) != null
} }
} }
fun MatteryMenu.addFilterSlots(slots: Delegate<ItemFilter>): List<Delegate<ItemStack>> {
val result = ArrayList<Delegate<ItemStack>>(slots.value.size)
for (i in 0 until slots.value.size) {
result.add(Delegate.Of(
mSynchronizer.computedItem { slots.value[i] },
itemStackInput { slots.value = slots.value.set(i, it) }
))
}
return result
}
fun MatteryMenu.addFilterSlots(amount: Int): List<Delegate<ItemStack>> {
val result = ArrayList<Delegate<ItemStack>>(amount)
for (i in 0 until amount) {
result.add(Delegate.Of(
mSynchronizer.computedItem { ItemStack.EMPTY },
itemStackInput { throw UnsupportedOperationException() }
))
}
return result
}
fun MatteryMenu.addFilterSlots(slots: Delegate<ItemFilter>?, amount: Int): List<Delegate<ItemStack>> {
if (slots != null && amount != slots.value.size)
throw IllegalStateException("Provided ItemFiler has different amount of slots than expected: ${slots.value.size} != $amount")
if (slots == null)
return addFilterSlots(amount)
else
return addFilterSlots(slots)
}
fun MatteryMenu.addFilterSlots(slots: KMutableProperty0<ItemFilter>?, amount: Int): List<Delegate<ItemStack>> {
return addFilterSlots(if (slots == null) null else Delegate.Of(slots), amount)
}
data class FilterControls(val slots: List<Delegate<ItemStack>>, val isWhitelist: BooleanInputWithFeedback, val matchComponents: BooleanInputWithFeedback, val matchTag: BooleanInputWithFeedback)
fun MatteryMenu.addFilterControls(slots: Delegate<ItemFilter>?, amount: Int): FilterControls {
if (slots == null) {
return FilterControls(addFilterSlots(amount), BooleanInputWithFeedback(this), BooleanInputWithFeedback(this), BooleanInputWithFeedback(this))
} else {
return FilterControls(
addFilterSlots(slots, amount),
BooleanInputWithFeedback.dispatch(this, slots, ItemFilter::isWhitelist, ItemFilter::isWhitelist),
BooleanInputWithFeedback.dispatch(this, slots, ItemFilter::matchComponents, ItemFilter::matchComponents),
BooleanInputWithFeedback.dispatch(this, slots, ItemFilter::matchTag, ItemFilter::matchTag),
)
}
}
fun MatteryMenu.addFilterControls(slots: KMutableProperty0<ItemFilter>?, amount: Int): FilterControls {
return addFilterControls(slots?.let { Delegate.Of(it) }, amount)
}

View File

@ -3,6 +3,8 @@ package ru.dbotthepony.mc.otm.menu.input
import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatteryMenu
import java.util.function.BooleanSupplier import java.util.function.BooleanSupplier
import java.util.function.Consumer
import java.util.function.Supplier
import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KMutableProperty0
class BooleanInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean = false) : AbstractPlayerInputWithFeedback<Boolean>() { class BooleanInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean = false) : AbstractPlayerInputWithFeedback<Boolean>() {
@ -32,4 +34,28 @@ class BooleanInputWithFeedback(menu: MatteryMenu, allowSpectators: Boolean = fal
fun switchValue() { fun switchValue() {
accept(!value) accept(!value)
} }
companion object {
fun <T> dispatch(menu: MatteryMenu, property: Delegate<T>, getter: (T) -> Boolean, setter: (T, Boolean) -> T): BooleanInputWithFeedback {
return BooleanInputWithFeedback(
menu,
Delegate.Of(
{ getter(property.get()) },
{ property.accept(setter(property.get(), it)) }
)
)
}
fun <T> dispatch(menu: MatteryMenu, property: KMutableProperty0<T>, getter: (T) -> Boolean, setter: (T, Boolean) -> T): BooleanInputWithFeedback {
return BooleanInputWithFeedback(
menu,
Delegate.Of(
{ getter(property.get()) },
{ property.set(setter(property.get(), it)) }
)
)
}
}
} }

View File

@ -15,7 +15,6 @@ import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter
import ru.dbotthepony.mc.otm.core.util.computedItem
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.MatterySlot
@ -81,23 +80,21 @@ class DriveViewerMenu(
return (stack?.item as? PortableCondensationDriveItem)?.getFilterSettings(stack) return (stack?.item as? PortableCondensationDriveItem)?.getFilterSettings(stack)
} }
private fun setFilter(value: ItemFilter) {
val stack = (tile as? DriveViewerBlockEntity)?.container?.getItem(0)
(stack?.item as? PortableCondensationDriveItem)?.setFilterSettings(stack, value)
}
val driveFilterSlots = immutableList(PortableCondensationDriveItem.MAX_FILTERS) { i -> val driveFilterSlots = immutableList(PortableCondensationDriveItem.MAX_FILTERS) { i ->
Delegate.Of( Delegate.Of(
mSynchronizer.computedItem { getFilter()?.get(i) ?: ItemStack.EMPTY }, mSynchronizer.computedItem { getFilter()?.get(i) ?: ItemStack.EMPTY },
itemStackInput { getFilter()?.set(i, it) } itemStackInput { getFilter()?.set(i, it) }.filter { drivePresent }
) )
} }
private fun make(mapper: (ItemFilter) -> Delegate<Boolean>): Delegate<Boolean> { val isWhitelist = BooleanInputWithFeedback.dispatch(this, Delegate.Of({ getFilter() }, { setFilter(it!!) }), { it?.isWhitelist ?: false }, { it, v -> it?.isWhitelist(v) }).also { it.filter { drivePresent } }
return Delegate.Of( val matchTag = BooleanInputWithFeedback.dispatch(this, Delegate.Of({ getFilter() }, { setFilter(it!!) }), { it?.matchTag ?: false }, { it, v -> it?.matchTag(v) }).also { it.filter { drivePresent } }
{ getFilter()?.let(mapper)?.get() ?: false }, val matchComponents = BooleanInputWithFeedback.dispatch(this, Delegate.Of({ getFilter() }, { setFilter(it!!) }), { it?.matchComponents ?: false }, { it, v -> it?.matchComponents(v) }).also { it.filter { drivePresent } }
{ getFilter()?.let(mapper)?.accept(it) }
)
}
val isWhitelist = BooleanInputWithFeedback(this, make { Delegate.Of(it::isWhitelist) }).also { it.filter { drivePresent } }
val matchTag = BooleanInputWithFeedback(this, make { Delegate.Of(it::matchTag) }).also { it.filter { drivePresent } }
val matchNBT = BooleanInputWithFeedback(this, make { Delegate.Of(it::matchComponents) }).also { it.filter { drivePresent } }
override fun broadcastChanges() { override fun broadcastChanges() {
super.broadcastChanges() super.broadcastChanges()

View File

@ -2,7 +2,9 @@ package ru.dbotthepony.mc.otm.menu.storage
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.block.entity.storage.AbstractStorageImportExport import ru.dbotthepony.mc.otm.block.entity.storage.AbstractStorageImportExport
import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.addFilterControls
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
@ -11,10 +13,7 @@ import ru.dbotthepony.mc.otm.registry.MMenus
class StorageImporterExporterMenu( class StorageImporterExporterMenu(
containerId: Int, inventory: Inventory, tile: AbstractStorageImportExport? = null containerId: Int, inventory: Inventory, tile: AbstractStorageImportExport? = null
) : MatteryPoweredMenu(MMenus.STORAGE_IMPORTER_EXPORTER, containerId, inventory, tile) { ) : MatteryPoweredMenu(MMenus.STORAGE_IMPORTER_EXPORTER, containerId, inventory, tile) {
val filterSlots = addFilterSlots(tile?.filter, AbstractStorageImportExport.MAX_FILTERS) val filter = addFilterControls(tile?.let { it::filter }, AbstractStorageImportExport.MAX_FILTERS)
val isWhitelist = BooleanInputWithFeedback(this, tile?.let { it.filter::isWhitelist })
val matchNBT = BooleanInputWithFeedback(this, tile?.let { it.filter::matchComponents })
val matchTag = BooleanInputWithFeedback(this, tile?.let { it.filter::matchTag })
val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget) val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget)
val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig) val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)