Flatten filter slots to just gettersetter

This commit is contained in:
DBotThePony 2023-08-12 11:44:49 +07:00
parent 839e7cc503
commit 1afa8e3d21
Signed by: DBot
GPG Key ID: DCC23B5715498507
19 changed files with 108 additions and 263 deletions

View File

@ -121,7 +121,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
} }
} }
val filter = ItemFilter(MAX_FILTERS) { _, _, _ -> val filter = ItemFilter(MAX_FILTERS) {
component?.scan() component?.scan()
setChangedLight() setChangedLight()
} }

View File

@ -113,7 +113,7 @@ abstract class AbstractStorageImportExport<T>(
class StorageImporterBlockEntity( class StorageImporterBlockEntity(
blockPos: BlockPos, blockState: BlockState blockPos: BlockPos, blockState: BlockState
) : AbstractStorageImportExport<IItemHandler>(MBlockEntities.STORAGE_IMPORTER, blockPos, blockState), IItemHandler { ) : AbstractStorageImportExport<IItemHandler>(MBlockEntities.STORAGE_IMPORTER, blockPos, blockState), IItemHandler {
override val filter = ItemFilter(MAX_FILTERS) { _, _, _ -> override val filter = ItemFilter(MAX_FILTERS) {
setChangedLight() setChangedLight()
} }
@ -262,7 +262,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
relevantTuples.remove(id) relevantTuples.remove(id)
} }
override val filter = ItemFilter(MAX_FILTERS) { _, _, _ -> override val filter = ItemFilter(MAX_FILTERS) {
relevantTuples.clear() relevantTuples.clear()
val component = cell.graph.getVirtualComponent(StorageStack.ITEMS) val component = cell.graph.getVirtualComponent(StorageStack.ITEMS)

View File

@ -34,7 +34,7 @@ open class NetworkNumberInputPanel<out S : Screen> @JvmOverloads constructor(
) : this( ) : this(
screen = screen, screen = screen,
parent = parent, parent = parent,
callback = widget::input, callback = widget::accept,
isAvailable = { widget.allowSpectators || minecraft.player?.isSpectator != true }, isAvailable = { widget.allowSpectators || minecraft.player?.isSpectator != true },
networkValue = networkValue, networkValue = networkValue,
x = x, x = x,

View File

@ -3,14 +3,12 @@ package ru.dbotthepony.mc.otm.client.screen.panels.slot
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket
import ru.dbotthepony.mc.otm.network.MenuNetworkChannel
open class FilterSlotPanel<out S : MatteryScreen<*>> @JvmOverloads constructor( open class FilterSlotPanel<out S : MatteryScreen<*>> @JvmOverloads constructor(
screen: S, screen: S,
parent: EditablePanel<*>?, parent: EditablePanel<*>?,
val slot: ItemFilterNetworkSlot, val slot: GetterSetter<ItemStack>,
x: Float = 0f, x: Float = 0f,
y: Float = 0f, y: Float = 0f,
width: Float = SIZE, width: Float = SIZE,
@ -21,14 +19,7 @@ open class FilterSlotPanel<out S : MatteryScreen<*>> @JvmOverloads constructor(
} }
override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean { override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
if (!screen.menu.ply.isSpectator) { slot.accept(screen.menu.carried)
if (screen.menu.carried.isEmpty) {
MenuNetworkChannel.sendToServer(ItemFilterSlotPacket(slot.networkID, ItemStack.EMPTY))
} else {
MenuNetworkChannel.sendToServer(ItemFilterSlotPacket(slot.networkID, screen.menu.carried))
}
}
return true return true
} }
} }

View File

@ -63,7 +63,6 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp
val filterGrid = GridPanel(this, frame, width = AbstractSlotPanel.SIZE * 3f, height = AbstractSlotPanel.SIZE * 4f, rows = 3, columns = 4) val filterGrid = GridPanel(this, frame, width = AbstractSlotPanel.SIZE * 3f, height = AbstractSlotPanel.SIZE * 4f, rows = 3, columns = 4)
filterGrid.dock = Dock.FILL filterGrid.dock = Dock.FILL
filterGrid.dockResize = DockResizeMode.NONE filterGrid.dockResize = DockResizeMode.NONE
filterGrid.dockTop = 20f
settings.add(filterGrid) settings.add(filterGrid)
for (i in 0 until PortableCondensationDriveItem.MAX_FILTERS) { for (i in 0 until PortableCondensationDriveItem.MAX_FILTERS) {

View File

@ -11,7 +11,6 @@ import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkNumberInputPanel import ru.dbotthepony.mc.otm.client.screen.panels.input.NetworkNumberInputPanel
import ru.dbotthepony.mc.otm.core.util.formatPower import ru.dbotthepony.mc.otm.core.util.formatPower
import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu
import java.util.function.Supplier
class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title: Component) : MatteryScreen<EnergyCounterMenu>(menu, inventory, title) { class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title: Component) : MatteryScreen<EnergyCounterMenu>(menu, inventory, title) {
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> { override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
@ -43,7 +42,7 @@ class EnergyCounterScreen(menu: EnergyCounterMenu, inventory: Inventory, title:
} }
if (!menu.ply.isSpectator) { if (!menu.ply.isSpectator) {
val button = ButtonPanel(this, frame, 0f, 0f, 0f, 20f, TranslatableComponent("block.overdrive_that_matters.energy_counter.switch"), onPress = Runnable { menu.switchDirection.input(null) }) val button = ButtonPanel(this, frame, 0f, 0f, 0f, 20f, TranslatableComponent("block.overdrive_that_matters.energy_counter.switch"), onPress = Runnable { menu.switchDirection.accept(null) })
button.dock = Dock.TOP button.dock = Dock.TOP
button.setDockMargin(4f, 5f, 4f, 0f) button.setDockMargin(4f, 5f, 4f, 0f)
} }

View File

@ -100,7 +100,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
} }
override fun onClick(mouseButton: Int) { override fun onClick(mouseButton: Int) {
menu.storeLevels.input(1) menu.storeLevels.accept(1)
} }
override var isDisabled: Boolean override var isDisabled: Boolean
@ -115,7 +115,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
} }
override fun onClick(mouseButton: Int) { override fun onClick(mouseButton: Int) {
menu.storeLevels.input(10) menu.storeLevels.accept(10)
} }
override var isDisabled: Boolean override var isDisabled: Boolean
@ -130,7 +130,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
} }
override fun onClick(mouseButton: Int) { override fun onClick(mouseButton: Int) {
menu.storeLevels.input((minecraft?.player?.experienceLevel ?: 0) + 1) menu.storeLevels.accept((minecraft?.player?.experienceLevel ?: 0) + 1)
} }
override var isDisabled: Boolean override var isDisabled: Boolean
@ -145,7 +145,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
} }
override fun onClick(mouseButton: Int) { override fun onClick(mouseButton: Int) {
menu.dispenseLevels.input(1) menu.dispenseLevels.accept(1)
} }
override var isDisabled: Boolean override var isDisabled: Boolean
@ -160,7 +160,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
} }
override fun onClick(mouseButton: Int) { override fun onClick(mouseButton: Int) {
menu.dispenseLevels.input(10) menu.dispenseLevels.accept(10)
} }
override var isDisabled: Boolean override var isDisabled: Boolean
@ -175,7 +175,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
} }
override fun onClick(mouseButton: Int) { override fun onClick(mouseButton: Int) {
menu.dispenseLevels.input(getLevelFromXp(menu.experienceStored) + 1) menu.dispenseLevels.accept(getLevelFromXp(menu.experienceStored) + 1)
} }
override var isDisabled: Boolean override var isDisabled: Boolean
@ -192,7 +192,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
} }
override fun onClick(mouseButton: Int) { override fun onClick(mouseButton: Int) {
menu.storeLevels.input(customDispense) menu.storeLevels.accept(customDispense)
} }
override var isDisabled: Boolean override var isDisabled: Boolean
@ -211,12 +211,12 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
if (player.experienceLevel == customDispense) { if (player.experienceLevel == customDispense) {
if (player.experienceProgress > 0f) { if (player.experienceProgress > 0f) {
menu.storeLevels.input(1) menu.storeLevels.accept(1)
} }
} else if (player.experienceLevel > customDispense) { } else if (player.experienceLevel > customDispense) {
menu.storeLevels.input(player.experienceLevel - customDispense) menu.storeLevels.accept(player.experienceLevel - customDispense)
} else { } else {
menu.dispenseLevels.input(customDispense - player.experienceLevel) menu.dispenseLevels.accept(customDispense - player.experienceLevel)
} }
playGuiClickSound() playGuiClickSound()
@ -233,7 +233,7 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
} }
override fun onClick(mouseButton: Int) { override fun onClick(mouseButton: Int) {
menu.dispenseLevels.input(customDispense) menu.dispenseLevels.accept(customDispense)
} }
override var isDisabled: Boolean override var isDisabled: Boolean
@ -253,12 +253,12 @@ class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title
if (player.experienceLevel == customDispense) { if (player.experienceLevel == customDispense) {
if (player.experienceProgress > 0f) { if (player.experienceProgress > 0f) {
menu.storeLevels.input(1) menu.storeLevels.accept(1)
} }
} else if (player.experienceLevel > customDispense) { } else if (player.experienceLevel > customDispense) {
menu.storeLevels.input(player.experienceLevel - customDispense) menu.storeLevels.accept(player.experienceLevel - customDispense)
} else { } else {
menu.dispenseLevels.input(customDispense - player.experienceLevel) menu.dispenseLevels.accept(customDispense - player.experienceLevel)
} }
} }

View File

@ -17,98 +17,13 @@ import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
import java.util.Arrays import java.util.Arrays
import java.util.LinkedList import java.util.LinkedList
import java.util.function.Consumer
import java.util.function.Supplier import java.util.function.Supplier
data class ItemFilterSlotPacket(val slotID: Int, val newValue: ItemStack) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeInt(slotID)
buff.writeItemStack(newValue, true)
}
override fun play(context: Supplier<NetworkEvent.Context>) {
context.get().packetHandled = true
if (context.get().sender != null) {
context.get().enqueueWork {
playServer(context.get().sender!!)
}
} else {
context.get().enqueueWork {
playClient()
}
}
}
fun playClient() {
val menu = minecraft.player?.containerMenu as? MatteryMenu ?: throw IllegalStateException("No MatteryMenu is open right now, can't handle ItemFilterSlotReplicaPacket")
menu.filterSlots[slotID].set(newValue)
}
fun playServer(player: ServerPlayer) {
if (player.isSpectator) {
return
}
val menu = player.containerMenu as? MatteryMenu ?: return LOGGER.error("No MatteryMenu is open right now, can't handle ItemFilterSlotReplicaPacket from $player")
val slot = menu.filterSlots.getOrNull(slotID) ?: return LOGGER.error("ItemFilterSlotReplicaPacket: unknown slot $slotID from $player in $menu!")
if (slot.filter?.isLocked == true)
return
slot.set(newValue)
}
companion object {
fun read(buff: FriendlyByteBuf): ItemFilterSlotPacket {
return ItemFilterSlotPacket(buff.readInt(), buff.readItem())
}
private val LOGGER = LogManager.getLogger()
}
}
data class ItemFilterNetworkSlot(val slotID: Int, val networkID: Int, var filter: ItemFilter?) {
fun get() = filter?.get(slotID) ?: remote
fun set(value: ItemStack) {
if (filter != null)
filter!![slotID] = value
else
remote = value
}
private var remote: ItemStack = ItemStack.EMPTY
fun sendChanges(full: Boolean = false): ItemFilterSlotPacket? {
requireNotNull(filter) { "Invalid side" }
if (full || !ItemStack.isSameItemSameTags(remote, get())) {
remote = get()
return ItemFilterSlotPacket(networkID, get())
}
return null
}
}
fun interface ItemFilterCallback {
fun invoke(slot: Int?, oldValue: ItemStack?, newValue: ItemStack?)
}
fun interface ItemFilterFullCallback {
fun invoke(self: ItemFilter, slot: Int?, oldValue: ItemStack?, newValue: ItemStack?)
}
class ItemFilter( class ItemFilter(
val size: Int, val size: Int,
private val modified: ItemFilterFullCallback? = null private val modified: Consumer<ItemFilter>? = null
) : INBTSerializable<CompoundTag?> { ) : INBTSerializable<CompoundTag?> {
constructor(size: Int, modified: ItemFilterCallback?) :
this(size,
modified?.let {
fn ->
return@let ItemFilterFullCallback { _: ItemFilter, slot: Int?, oldValue: ItemStack?, newValue: ItemStack? -> fn.invoke(slot, oldValue, newValue) }
})
private val filter = Array<ItemStack>(size) { ItemStack.EMPTY } private val filter = Array<ItemStack>(size) { ItemStack.EMPTY }
private val linkedFilter = LinkedList<ItemStack>() private val linkedFilter = LinkedList<ItemStack>()
@ -118,7 +33,7 @@ class ItemFilter(
set(value) { set(value) {
if (value != field) { if (value != field) {
field = value field = value
modified?.invoke(this, null, null, null) modified?.accept(this)
} }
} }
@ -126,7 +41,7 @@ class ItemFilter(
set(value) { set(value) {
if (value != field) { if (value != field) {
field = value field = value
modified?.invoke(this, null, null, null) modified?.accept(this)
} }
} }
@ -134,7 +49,7 @@ class ItemFilter(
set(value) { set(value) {
if (value != field) { if (value != field) {
field = value field = value
modified?.invoke(this, null, null, null) modified?.accept(this)
} }
} }
@ -146,27 +61,7 @@ class ItemFilter(
Arrays.fill(filter, ItemStack.EMPTY) Arrays.fill(filter, ItemStack.EMPTY)
linkedFilter.clear() linkedFilter.clear()
modified?.invoke(this, null, null, null) modified?.accept(this)
}
fun copyFrom(other: ItemFilter) {
require(other.size == size) { "Size differs (this filter has size of $size, other has size of ${other.size})" }
linkedFilter.clear()
for (i in 0 until size) {
filter[i] = other.filter[i]
if (!filter[i].isEmpty) {
linkedFilter.add(filter[i])
}
}
isWhitelist = other.isWhitelist
matchTag = other.matchTag
matchNBT = other.matchNBT
modified?.invoke(this, null, null, null)
} }
operator fun set(index: Int, value: ItemStack) { operator fun set(index: Int, value: ItemStack) {
@ -187,7 +82,7 @@ class ItemFilter(
if (!filter[index].isEmpty) if (!filter[index].isEmpty)
linkedFilter.add(filter[index]) linkedFilter.add(filter[index])
modified?.invoke(this, index, old, filter[index]) modified?.accept(this)
} }
operator fun get(index: Int): ItemStack = filter[index].copy() operator fun get(index: Int): ItemStack = filter[index].copy()

View File

@ -27,4 +27,4 @@ class JsonArraySpliterator(private val obj: JsonArray, offset: Int = 0, private
} }
fun JsonArray.elementSpliterator() = JsonArraySpliterator(this) fun JsonArray.elementSpliterator() = JsonArraySpliterator(this)
fun JsonArray.stream(): Stream<out JsonElement> = StreamSupport.stream(elementSpliterator(), false) fun JsonArray.stream(): Stream<JsonElement> = StreamSupport.stream(elementSpliterator(), false)

View File

@ -22,6 +22,8 @@ import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.capability.drive.DrivePool import ru.dbotthepony.mc.otm.capability.drive.DrivePool
import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.core.nbt.map import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.tagNotNull
import java.math.BigInteger import java.math.BigInteger
import java.util.* import java.util.*
@ -86,9 +88,11 @@ class PortableCondensationDriveItem(capacity: Int) :
} }
fun getFilterSettings(drive: ItemStack): ItemFilter { fun getFilterSettings(drive: ItemStack): ItemFilter {
val filter = ItemFilter(MAX_FILTERS) var ignore = true
val filter = ItemFilter(MAX_FILTERS) { if (!ignore) drive.tagNotNull[FILTER_PATH] = it.serializeNBT() }
filter.isWhitelist = true filter.isWhitelist = true
drive.tag?.map(FILTER_PATH, filter::deserializeNBT) drive.tag?.map(FILTER_PATH, filter::deserializeNBT)
ignore = false
return filter return filter
} }

View File

@ -34,7 +34,6 @@ import ru.dbotthepony.mc.otm.compat.cos.cosmeticArmorSlots
import ru.dbotthepony.mc.otm.compat.curios.curiosSlots import ru.dbotthepony.mc.otm.compat.curios.curiosSlots
import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot import ru.dbotthepony.mc.otm.compat.curios.isCurioSlot
import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.UpgradeContainer import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.GetterSetter
@ -46,6 +45,7 @@ import ru.dbotthepony.mc.otm.core.util.BigDecimalValueCodec
import ru.dbotthepony.mc.otm.core.util.BinaryStringCodec import ru.dbotthepony.mc.otm.core.util.BinaryStringCodec
import ru.dbotthepony.mc.otm.core.util.BooleanValueCodec import ru.dbotthepony.mc.otm.core.util.BooleanValueCodec
import ru.dbotthepony.mc.otm.core.util.IStreamCodec import ru.dbotthepony.mc.otm.core.util.IStreamCodec
import ru.dbotthepony.mc.otm.core.util.ItemStackValueCodec
import ru.dbotthepony.mc.otm.core.util.ItemValueCodec import ru.dbotthepony.mc.otm.core.util.ItemValueCodec
import ru.dbotthepony.mc.otm.core.util.NullValueCodec import ru.dbotthepony.mc.otm.core.util.NullValueCodec
import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec
@ -66,6 +66,7 @@ import java.io.DataOutputStream
import java.math.BigDecimal import java.math.BigDecimal
import java.util.* import java.util.*
import java.util.function.BooleanSupplier import java.util.function.BooleanSupplier
import java.util.function.Consumer
import java.util.function.DoubleSupplier import java.util.function.DoubleSupplier
import java.util.function.IntSupplier import java.util.function.IntSupplier
import java.util.function.Predicate import java.util.function.Predicate
@ -90,7 +91,7 @@ data class UpgradeSlots(
val currentStats: IMatteryUpgrade val currentStats: IMatteryUpgrade
) )
abstract class MatteryMenu @JvmOverloads protected constructor( abstract class MatteryMenu(
menuType: MenuType<*>?, menuType: MenuType<*>?,
containerId: Int, containerId: Int,
val inventory: Inventory, val inventory: Inventory,
@ -137,7 +138,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
/** /**
* Client->Server input * Client->Server input
*/ */
inner class PlayerInput<V>(val codec: IStreamCodec<V>, allowSpectators: Boolean = false, val handler: (V) -> Unit) : Predicate<Player?> { inner class PlayerInput<V>(val codec: IStreamCodec<V>, allowSpectators: Boolean = false, val handler: (V) -> Unit) : Consumer<V>, Predicate<Player?> {
val id = playerInputs.size val id = playerInputs.size
var allowSpectators by mSynchronizer.bool(allowSpectators).property var allowSpectators by mSynchronizer.bool(allowSpectators).property
@ -161,7 +162,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
return filters.all { it.test(player) } return filters.all { it.test(player) }
} }
fun input(value: V) { override fun accept(value: V) {
if (test(minecraft.player as Player?)) { if (test(minecraft.player as Player?)) {
val stream = FastByteArrayOutputStream() val stream = FastByteArrayOutputStream()
codec.write(DataOutputStream(stream), value) codec.write(DataOutputStream(stream), value)
@ -183,6 +184,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
fun bigDecimalInput(allowSpectators: Boolean = false, handler: (BigDecimal) -> Unit) = PlayerInput(BigDecimalValueCodec, allowSpectators, handler) fun bigDecimalInput(allowSpectators: Boolean = false, handler: (BigDecimal) -> Unit) = PlayerInput(BigDecimalValueCodec, allowSpectators, handler)
fun booleanInput(allowSpectators: Boolean = false, handler: (Boolean) -> Unit) = PlayerInput(BooleanValueCodec, allowSpectators, handler) fun booleanInput(allowSpectators: Boolean = false, handler: (Boolean) -> Unit) = PlayerInput(BooleanValueCodec, allowSpectators, handler)
fun itemInput(allowSpectators: Boolean = false, handler: (Item) -> Unit) = PlayerInput(ItemValueCodec, allowSpectators, handler) fun itemInput(allowSpectators: Boolean = false, handler: (Item) -> Unit) = PlayerInput(ItemValueCodec, allowSpectators, handler)
fun itemStackInput(allowSpectators: Boolean = false, handler: (ItemStack) -> Unit) = PlayerInput(ItemStackValueCodec, allowSpectators, handler)
fun nullableItemInput(allowSpectators: Boolean = false, handler: (Item?) -> Unit) = PlayerInput(ItemValueCodec.nullable, allowSpectators, handler) fun nullableItemInput(allowSpectators: Boolean = false, handler: (Item?) -> Unit) = PlayerInput(ItemValueCodec.nullable, allowSpectators, handler)
fun stringInput(allowSpectators: Boolean = false, handler: (String) -> Unit) = PlayerInput(BinaryStringCodec, allowSpectators, handler) fun stringInput(allowSpectators: Boolean = false, handler: (String) -> Unit) = PlayerInput(BinaryStringCodec, allowSpectators, handler)
fun intInput(allowSpectators: Boolean = false, handler: (Int) -> Unit) = PlayerInput(VarIntValueCodec, allowSpectators, handler) fun intInput(allowSpectators: Boolean = false, handler: (Int) -> Unit) = PlayerInput(VarIntValueCodec, allowSpectators, handler)
@ -230,34 +232,47 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
protected val lockedInventorySlots: MutableSet<Int> = HashSet() protected val lockedInventorySlots: MutableSet<Int> = HashSet()
protected open fun isInventorySlotLocked(index: Int): Boolean = lockedInventorySlots.contains(index) protected open fun isInventorySlotLocked(index: Int): Boolean = lockedInventorySlots.contains(index)
private val _filterSlots = ArrayList<ItemFilterNetworkSlot>()
val filterSlots: List<ItemFilterNetworkSlot> = Collections.unmodifiableList(_filterSlots)
protected var inventorySlotIndexStart = 0 protected var inventorySlotIndexStart = 0
protected var inventorySlotIndexEnd = 0 protected var inventorySlotIndexEnd = 0
private val playerPacketDistributor = PacketDistributor.PLAYER.with { ply as ServerPlayer } private val playerPacketDistributor = PacketDistributor.PLAYER.with { ply as ServerPlayer }
fun addFilterSlots(slots: ItemFilter): List<ItemFilterNetworkSlot> { fun addFilterSlots(slots: ItemFilter): List<GetterSetter<ItemStack>> {
val result = ArrayList<ItemFilterNetworkSlot>(slots.size) val result = ArrayList<GetterSetter<ItemStack>>(slots.size)
for (i in 0 until slots.size) { for (i in 0 until slots.size) {
_filterSlots.add(ItemFilterNetworkSlot(i, _filterSlots.size, slots).also(result::add)) result.add(GetterSetter.of(
mSynchronizer.computedItem { slots[i] },
itemStackInput { slots[i] = it }
))
} }
return result return result
} }
fun addFilterSlots(amount: Int): List<ItemFilterNetworkSlot> { fun addFilterSlots(amount: Int): List<GetterSetter<ItemStack>> {
val result = ArrayList<ItemFilterNetworkSlot>(amount) val result = ArrayList<GetterSetter<ItemStack>>(amount)
for (i in 0 until amount) { for (i in 0 until amount) {
_filterSlots.add(ItemFilterNetworkSlot(i, _filterSlots.size, null).also(result::add)) result.add(GetterSetter.of(
mSynchronizer.computedItem { ItemStack.EMPTY },
itemStackInput { throw UnsupportedOperationException() }
))
} }
return result return result
} }
fun addFilterSlots(slots: ItemFilter?, amount: Int): List<GetterSetter<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, x: Int = 0, y: Int = 0) : UserFilteredSlot(container, index, x, y) { open inner class InventorySlot(container: Container, index: Int, x: Int = 0, y: Int = 0) : UserFilteredSlot(container, index, x, y) {
override fun mayPlace(itemStack: ItemStack): Boolean { override fun mayPlace(itemStack: ItemStack): Boolean {
return !isInventorySlotLocked(index) && super.mayPlace(itemStack) return !isInventorySlotLocked(index) && super.mayPlace(itemStack)
@ -285,7 +300,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
if (slotIndex in mattery.regularSlotFilters.indices) { if (slotIndex in mattery.regularSlotFilters.indices) {
filter = GetterSetter.of( filter = GetterSetter.of(
getter = { mattery.regularSlotFilters[slotIndex].value }, getter = { mattery.regularSlotFilters[slotIndex].value },
setter = nullableItemInput(true) { mattery.regularSlotFilters[slotIndex].value = it }::input setter = nullableItemInput(true) { mattery.regularSlotFilters[slotIndex].value = it }::accept
) )
} }
@ -294,20 +309,20 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
chargeFlag = GetterSetter.of( chargeFlag = GetterSetter.of(
getter = { mattery.regularSlotChargeFlag[slotIndex].boolean }, getter = { mattery.regularSlotChargeFlag[slotIndex].boolean },
setter = input::input setter = input::accept
) )
} }
} else if (container === mattery.exopackContainer) { } else if (container === mattery.exopackContainer) {
filter = GetterSetter.of( filter = GetterSetter.of(
getter = { mattery.exopackContainer.getSlotFilter(slotIndex) }, getter = { mattery.exopackContainer.getSlotFilter(slotIndex) },
setter = nullableItemInput(true) { mattery.exopackContainer.setSlotFilter(slotIndex, it) }::input setter = nullableItemInput(true) { mattery.exopackContainer.setSlotFilter(slotIndex, it) }::accept
) )
val input = booleanInput(true) { if (it) mattery.exoPackSlotsChargeFlag.add(slotIndex) else mattery.exoPackSlotsChargeFlag.remove(slotIndex) } val input = booleanInput(true) { if (it) mattery.exoPackSlotsChargeFlag.add(slotIndex) else mattery.exoPackSlotsChargeFlag.remove(slotIndex) }
chargeFlag = GetterSetter.of( chargeFlag = GetterSetter.of(
getter = { slotIndex in mattery.exoPackSlotsChargeFlag }, getter = { slotIndex in mattery.exoPackSlotsChargeFlag },
setter = input::input setter = input::accept
) )
} else { } else {
filter = null filter = null
@ -422,20 +437,6 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
} }
} }
val consumer = PacketDistributor.PLAYER.with { ply as ServerPlayer }
for (slot in _filterSlots) {
val packet = slot.sendChanges()
if (packet != null) {
if (broadcastOnce) {
MenuNetworkChannel.send(consumer, packet)
} else {
MenuNetworkChannel.sendNow(consumer, packet)
}
}
}
broadcastOnce = true broadcastOnce = true
} }
@ -494,7 +495,7 @@ abstract class MatteryMenu @JvmOverloads protected constructor(
field = mSynchronizer.ComputedField(getter = { null }, ItemValueCodec.nullable) field = mSynchronizer.ComputedField(getter = { null }, ItemValueCodec.nullable)
} }
pSlot.filter = GetterSetter.of(getter = field::value, setter = input::input) pSlot.filter = GetterSetter.of(getter = field::value, setter = input::accept)
} }
return super.addSlot(pSlot) return super.addSlot(pSlot)

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.menu.input package ru.dbotthepony.mc.otm.menu.input
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.ISubscriptable import ru.dbotthepony.mc.otm.core.ISubscriptable
import ru.dbotthepony.mc.otm.core.SentientGetterSetter import ru.dbotthepony.mc.otm.core.SentientGetterSetter
@ -39,7 +38,7 @@ abstract class AbstractPlayerInputWithFeedback<V> : IPlayerInputWithFeedback<V>
} }
final override fun accept(t: V) { final override fun accept(t: V) {
input.input(t) input.accept(t)
} }
override fun test(player: Player?) = input.test(player) override fun test(player: Player?) = input.test(player)

View File

@ -20,6 +20,6 @@ class InstantBooleanInput(menu: MatteryMenu) : GetterSetter<Boolean>, BooleanSup
override fun accept(t: Boolean) { override fun accept(t: Boolean) {
value = t value = t
input.input(t) input.accept(t)
} }
} }

View File

@ -187,8 +187,8 @@ class MatterPanelMenu(
val changeIsAscending = booleanInput(allowSpectators = true) { tile?.getPlayerSettings(ply)?.ascending = it } val changeIsAscending = booleanInput(allowSpectators = true) { tile?.getPlayerSettings(ply)?.ascending = it }
val changeSorting = PlayerInput(ItemSorter::class.codec(), allowSpectators = true) { tile?.getPlayerSettings(ply)?.sorter = it } val changeSorting = PlayerInput(ItemSorter::class.codec(), allowSpectators = true) { tile?.getPlayerSettings(ply)?.sorter = it }
val sortingGS = GetterSetter.of(::sorting, changeSorting::input) val sortingGS = GetterSetter.of(::sorting, changeSorting::accept)
val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::input) val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::accept)
private val actualComparator = Comparator<PatternState> { o1, o2 -> sorting.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) } private val actualComparator = Comparator<PatternState> { o1, o2 -> sorting.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) }
private val actualTaskComparator = Comparator<ReplicationTask> { o1, o2 -> sorting.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) } private val actualTaskComparator = Comparator<ReplicationTask> { o1, o2 -> sorting.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) }

View File

@ -10,7 +10,10 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage 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.GetterSetter
import ru.dbotthepony.mc.otm.core.asGetterSetter
import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter
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
@ -70,17 +73,30 @@ class DriveViewerMenu(
addInventorySlots() addInventorySlots()
} }
val driveFilter = ItemFilter(PortableCondensationDriveItem.MAX_FILTERS) { self, _, _, _ -> var drivePresent by mSynchronizer.bool().property
if (tile?.container?.get(0)?.item is PortableCondensationDriveItem) {
tile.container[0].getOrCreateTag().put(PortableCondensationDriveItem.FILTER_PATH, self.serializeNBT()) private fun getFilter(): ItemFilter? {
} val stack = (tile as? DriveViewerBlockEntity)?.container?.getItem(0)
return (stack?.item as? PortableCondensationDriveItem)?.getFilterSettings(stack)
} }
val driveFilterSlots = addFilterSlots(driveFilter) val driveFilterSlots = immutableList(PortableCondensationDriveItem.MAX_FILTERS) { i ->
GetterSetter.of(
mSynchronizer.computedItem { getFilter()?.get(i) ?: ItemStack.EMPTY },
itemStackInput { getFilter()?.set(i, it) }
)
}
val isWhitelist = BooleanInputWithFeedback(this) private fun make(mapper: (ItemFilter) -> GetterSetter<Boolean>): GetterSetter<Boolean> {
val matchTag = BooleanInputWithFeedback(this) return GetterSetter.of(
val matchNBT = BooleanInputWithFeedback(this) { getFilter()?.let(mapper)?.get() ?: false },
{ getFilter()?.let(mapper)?.accept(it) }
)
}
val isWhitelist = BooleanInputWithFeedback(this, make { it::isWhitelist.asGetterSetter() }).also { it.filter { drivePresent } }
val matchTag = BooleanInputWithFeedback(this, make { it::matchTag.asGetterSetter() }).also { it.filter { drivePresent } }
val matchNBT = BooleanInputWithFeedback(this, make { it::matchNBT.asGetterSetter() }).also { it.filter { drivePresent } }
override fun broadcastChanges() { override fun broadcastChanges() {
super.broadcastChanges() super.broadcastChanges()
@ -99,37 +115,12 @@ class DriveViewerMenu(
} }
} }
drivePresent = lastDrive != null
if (prev != lastDrive) { if (prev != lastDrive) {
prev?.let(powered!!::remove) prev?.let(powered!!::remove)
this.networkedItemView.clear() this.networkedItemView.clear()
lastDrive?.let(powered!!::add) lastDrive?.let(powered!!::add)
if (lastDrive != null) {
val filter = (itemStack.item as? PortableCondensationDriveItem)?.getFilterSettings(itemStack)
if (filter != null) {
driveFilter.copyFrom(filter)
driveFilter.isLocked = false
isWhitelist.with(driveFilter::isWhitelist)
matchTag.with(driveFilter::matchTag)
matchNBT.with(driveFilter::matchNBT)
} else {
driveFilter.clear()
driveFilter.isLocked = true
isWhitelist.clear()
matchTag.clear()
matchNBT.clear()
}
} else {
driveFilter.clear()
driveFilter.isLocked = true
isWhitelist.clear()
matchTag.clear()
matchNBT.clear()
}
} }
this.networkedItemView.network() this.networkedItemView.network()

View File

@ -3,7 +3,6 @@ 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.StorageBusBlockEntity import ru.dbotthepony.mc.otm.block.entity.storage.StorageBusBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
@ -16,7 +15,7 @@ class StorageBusMenu(
inventory: Inventory, inventory: Inventory,
tile: StorageBusBlockEntity? = null tile: StorageBusBlockEntity? = null
) : MatteryPoweredMenu(MMenus.STORAGE_BUS, containerId, inventory, tile) { ) : MatteryPoweredMenu(MMenus.STORAGE_BUS, containerId, inventory, tile) {
val busFilterSlots: List<ItemFilterNetworkSlot> val busFilterSlots = addFilterSlots(tile?.filter, StorageBusBlockEntity.MAX_FILTERS)
val busFilterState = BooleanInputWithFeedback(this, tile?.let { it.filter::isWhitelist }) val busFilterState = BooleanInputWithFeedback(this, tile?.let { it.filter::isWhitelist })
val insertPriority = IntInputWithFeedback(this, tile?.let { it::insertPriority }) val insertPriority = IntInputWithFeedback(this, tile?.let { it::insertPriority })
val extractPriority = IntInputWithFeedback(this, tile?.let { it::extractPriority }) val extractPriority = IntInputWithFeedback(this, tile?.let { it::extractPriority })
@ -24,12 +23,6 @@ class StorageBusMenu(
val mode = EnumInputWithFeedback(this, tile?.let { it::mode }, FlowDirection.WITHOUT_NONE) val mode = EnumInputWithFeedback(this, tile?.let { it::mode }, FlowDirection.WITHOUT_NONE)
init { init {
if (tile != null) {
busFilterSlots = addFilterSlots(tile.filter)
} else {
busFilterSlots = addFilterSlots(StorageBusBlockEntity.MAX_FILTERS)
}
addStorageSlot(batterySlot) addStorageSlot(batterySlot)
addInventorySlots() addInventorySlots()
} }

View File

@ -1,32 +1,22 @@
package ru.dbotthepony.mc.otm.menu.storage package ru.dbotthepony.mc.otm.menu.storage
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.inventory.Slot
import ru.dbotthepony.mc.otm.block.entity.storage.StorageExporterBlockEntity import ru.dbotthepony.mc.otm.block.entity.storage.StorageExporterBlockEntity
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus
class StorageExporterMenu @JvmOverloads constructor( class StorageExporterMenu(
p_38852_: Int, p_38852_: Int,
inventory: Inventory, inventory: Inventory,
tile: StorageExporterBlockEntity? = null tile: StorageExporterBlockEntity? = null
) : MatteryPoweredMenu( ) : MatteryPoweredMenu(
MMenus.STORAGE_EXPORTER, p_38852_, inventory, tile MMenus.STORAGE_EXPORTER, p_38852_, inventory, tile
) { ) {
val busFilterSlots: List<ItemFilterNetworkSlot> val busFilterSlots = addFilterSlots(tile?.filter, StorageExporterBlockEntity.MAX_FILTERS)
val busFilterState: BooleanInputWithFeedback val busFilterState = BooleanInputWithFeedback(this, tile?.let { it.filter::isWhitelist })
init { init {
if (tile != null) {
busFilterSlots = addFilterSlots(tile.filter)
busFilterState = BooleanInputWithFeedback(this, tile.filter::isWhitelist)
} else {
busFilterSlots = addFilterSlots(StorageExporterBlockEntity.MAX_FILTERS)
busFilterState = BooleanInputWithFeedback(this)
}
addInventorySlots() addInventorySlots()
} }
} }

View File

@ -1,32 +1,18 @@
package ru.dbotthepony.mc.otm.menu.storage package ru.dbotthepony.mc.otm.menu.storage
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.inventory.Slot
import ru.dbotthepony.mc.otm.block.entity.storage.StorageImporterBlockEntity import ru.dbotthepony.mc.otm.block.entity.storage.StorageImporterBlockEntity
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus
class StorageImporterMenu @JvmOverloads constructor( class StorageImporterMenu(
p_38852_: Int, containerId: Int, inventory: Inventory, tile: StorageImporterBlockEntity? = null
inventory: Inventory, ) : MatteryPoweredMenu(MMenus.STORAGE_IMPORTER, containerId, inventory, tile) {
tile: StorageImporterBlockEntity? = null val busFilterSlots = addFilterSlots(tile?.filter, StorageImporterBlockEntity.MAX_FILTERS)
) : MatteryPoweredMenu( val busFilterState = BooleanInputWithFeedback(this, tile?.let { it.filter::isWhitelist })
MMenus.STORAGE_IMPORTER, p_38852_, inventory, tile
) {
val busFilterSlots: List<ItemFilterNetworkSlot>
val busFilterState: BooleanInputWithFeedback
init { init {
if (tile != null) {
busFilterSlots = addFilterSlots(tile.filter)
busFilterState = BooleanInputWithFeedback(this, tile.filter::isWhitelist)
} else {
busFilterSlots = addFilterSlots(StorageImporterBlockEntity.MAX_FILTERS)
busFilterState = BooleanInputWithFeedback(this)
}
addInventorySlots() addInventorySlots()
} }
} }

View File

@ -5,11 +5,9 @@ import net.minecraft.network.FriendlyByteBuf
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraftforge.network.NetworkDirection import net.minecraftforge.network.NetworkDirection
import net.minecraftforge.network.NetworkEvent import net.minecraftforge.network.NetworkEvent
import ru.dbotthepony.mc.otm.block.entity.storage.ItemMonitorPlayerSettings
import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.compat.InventoryScrollPacket import ru.dbotthepony.mc.otm.compat.InventoryScrollPacket
import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket
import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu
import ru.dbotthepony.mc.otm.menu.matter.CancelTaskPacket import ru.dbotthepony.mc.otm.menu.matter.CancelTaskPacket
import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatteryMenu
@ -74,12 +72,11 @@ class SetCarriedPacket(val item: ItemStack) : MatteryPacket {
} }
object MenuNetworkChannel : MatteryNetworkChannel( object MenuNetworkChannel : MatteryNetworkChannel(
version = "3", version = "4",
name = "menu" name = "menu"
) { ) {
fun register() { fun register() {
add(SetCarriedPacket::class.java, SetCarriedPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT) add(SetCarriedPacket::class.java, SetCarriedPacket.Companion::read, NetworkDirection.PLAY_TO_CLIENT)
add(ItemFilterSlotPacket::class.java, ItemFilterSlotPacket.Companion::read)
// networked item view // networked item view
add(ClearItemViewPacket::class.java, { ClearItemViewPacket }, NetworkDirection.PLAY_TO_CLIENT) add(ClearItemViewPacket::class.java, { ClearItemViewPacket }, NetworkDirection.PLAY_TO_CLIENT)