Update ItemFilter to behave like it did previously, with fixed amount of slots but still being immutable
This commit is contained in:
parent
aa5d36c488
commit
5b4fa2e9ed
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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)))
|
||||||
|
@ -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
|
||||||
|
@ -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 },
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
@ -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)) }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user