diff --git a/src/main/java/ru/dbotthepony/mc/otm/client/screen/panels/FlexGridPanel.java b/src/main/java/ru/dbotthepony/mc/otm/client/screen/panels/FlexGridPanel.java index a21c71345..8655ea2c4 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/client/screen/panels/FlexGridPanel.java +++ b/src/main/java/ru/dbotthepony/mc/otm/client/screen/panels/FlexGridPanel.java @@ -50,6 +50,10 @@ public class FlexGridPanel extends EditablePanel { // список потомков var children = getUndockedChildren(); + if (children.size() == 0) { + return; + } + // хранит общую ширину всех потомков в ряд // а так же ограничитель ширины ряда после // определения количества рядов diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java index 255f14a95..f22b49d29 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java @@ -233,24 +233,6 @@ public class MatteryNetworking { Optional.of(NetworkDirection.PLAY_TO_CLIENT) ); - CHANNEL.registerMessage( - next_network_id++, - DriveViewerMenu.FilterSwitchPacket.class, - DriveViewerMenu.FilterSwitchPacket::write, - DriveViewerMenu.FilterSwitchPacket::read, - DriveViewerMenu.FilterSwitchPacket::play, - Optional.of(NetworkDirection.PLAY_TO_SERVER) - ); - - CHANNEL.registerMessage( - next_network_id++, - DriveViewerMenu.FilterSetPacket.class, - DriveViewerMenu.FilterSetPacket::write, - DriveViewerMenu.FilterSetPacket::read, - DriveViewerMenu.FilterSetPacket::play, - Optional.of(NetworkDirection.PLAY_TO_SERVER) - ); - CHANNEL.registerMessage( next_network_id++, EnergyCounterPacket.class, diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt index 1a6fde5c5..e99e50b9d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveViewerScreen.kt @@ -6,11 +6,8 @@ import net.minecraft.world.entity.player.Inventory import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel -import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem.FilterSettings +import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem import ru.dbotthepony.mc.otm.menu.DriveViewerMenu -import ru.dbotthepony.mc.otm.menu.DriveViewerMenu.FilterSetPacket -import ru.dbotthepony.mc.otm.menu.DriveViewerMenu.FilterSwitchPacket -import ru.dbotthepony.mc.otm.network.MatteryNetworking class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Component) : MatteryScreen(menu, inventory, title) { @@ -86,134 +83,13 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp settings.add(dock_left) settings.add(grid_filter) - for (i in 0 until FilterSettings.MAX_FILTERS) { - object : AbstractSlotPanel(this@DriveViewerScreen, grid_filter, 0f, 0f) { - override fun getItemStack(): ItemStack { - val filter = menu.getFilter() ?: return ItemStack.EMPTY - return filter.items[i] - } - - private var clicking = false - - override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean { - clicking = true - return true - } - - override fun mouseReleasedInner(mouse_x: Double, mouse_y: Double, flag: Int): Boolean { - if (clicking) - MatteryNetworking.send(null, FilterSetPacket(menu.containerId, i, menu.carried)) - - clicking = false - return true - } - } + for (i in 0 until PortableCondensationDriveItem.MAX_FILTERS) { + FilterSlotPanel(this, grid_filter, menu.driveFilterSlots[i], 0f, 0f) } - val no = TranslatableComponent("otm.filter.no") - val yes = TranslatableComponent("otm.filter.yes") - - val matchNbt = - object : ButtonPanel(this@DriveViewerScreen, dock_left, 0f, 0f, 90f, 20f, TranslatableComponent("otm.filter.match_nbt", no)) { - override fun tick() { - super.tick() - - val filter = menu.getFilter() - if (filter != null) { - widget?.message = TranslatableComponent("otm.filter.match_nbt", if (filter.matchNbt) yes else no) - widget?.active = !isWidgetDisabled - } else { - widget?.active = false - } - } - - override fun onPress() { - super.onPress() - - val filter = menu.getFilter() - if (filter != null) { - MatteryNetworking.send( - null, - FilterSwitchPacket( - menu.containerId, - DriveViewerMenu.FilterSwitch.MATCH_NBT, - !filter.matchNbt - ) - ) - - disableTicks = 20 - } - } - } - - val matchTag = - object : ButtonPanel(this@DriveViewerScreen, dock_left, 0f, 0f, 90f, 20f, TranslatableComponent("otm.filter.match_tag", no)) { - override fun tick() { - super.tick() - - val filter = menu.getFilter() - if (filter != null) { - widget?.message = TranslatableComponent("otm.filter.match_tag", if (filter.matchTag) yes else no) - widget?.active = !isWidgetDisabled - } else { - widget?.active = false - } - } - - override fun onPress() { - super.onPress() - - val filter = menu.getFilter() - if (filter != null) { - MatteryNetworking.send( - null, - FilterSwitchPacket( - menu.containerId, - DriveViewerMenu.FilterSwitch.MATCH_TAG, - !filter.matchTag - ) - ) - - disableTicks = 20 - } - } - } - - val blacklist = - object : ButtonPanel(this@DriveViewerScreen, dock_left, 0f, 0f, 90f, 20f, TranslatableComponent("otm.filter.blacklist", no)) { - override fun tick() { - super.tick() - - val filter = menu.getFilter() - if (filter != null) { - widget?.message = TranslatableComponent("otm.filter.blacklist", if (filter.isBlacklist) yes else no) - widget?.active = !isWidgetDisabled - } else { - widget?.active = false - } - } - - override fun onPress() { - super.onPress() - val filter = menu.getFilter() - if (filter != null) { - MatteryNetworking.send( - null, - FilterSwitchPacket( - menu.containerId, - DriveViewerMenu.FilterSwitch.BLACKLIST, - !filter.isBlacklist - ) - ) - - disableTicks = 20 - } - } - } - - matchNbt.setDockMargin(0f, 4f, 0f, 0f) - matchTag.setDockMargin(0f, 4f, 0f, 0f) - blacklist.setDockMargin(0f, 4f, 0f, 0f) + CheckBoxLabelInputPanel(this, dock_left, menu.isWhitelist, TranslatableComponent("otm.gui.filter.is_whitelist"), width = 90f, height = 20f).also { it.setDockMargin(0f, 4f, 0f, 0f) } + CheckBoxLabelInputPanel(this, dock_left, menu.matchTag, TranslatableComponent("otm.gui.filter.match_tag"), width = 90f, height = 20f).also { it.setDockMargin(0f, 4f, 0f, 0f) } + CheckBoxLabelInputPanel(this, dock_left, menu.matchNBT, TranslatableComponent("otm.gui.filter.match_nbt"), width = 90f, height = 20f).also { it.setDockMargin(0f, 4f, 0f, 0f) } for (panel in settings) { panel.visible = false diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt index 15b58b1a4..9ed07180b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt @@ -4,6 +4,8 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.ListTag import net.minecraft.network.FriendlyByteBuf import net.minecraft.server.level.ServerPlayer +import net.minecraft.tags.TagKey +import net.minecraft.world.item.Item import net.minecraft.world.item.ItemStack import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.network.NetworkEvent @@ -12,6 +14,7 @@ import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.set +import java.util.Arrays import java.util.LinkedList import java.util.function.Supplier @@ -42,7 +45,12 @@ data class ItemFilterSlotPacket(val slotID: Int, val newValue: ItemStack) { fun playServer(player: ServerPlayer) { val menu = player.containerMenu as? MatteryMenu ?: return LOGGER.error("No MatteryMenu is open right now, can't handle ItemFilterSlotReplicaPacket from $player") - menu.filterSlots.getOrNull(slotID)?.set(newValue) //?: LOGGER.error("ItemFilterSlotReplicaPacket: unknown slot $slotID from $player in $menu!") + 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 { @@ -54,11 +62,11 @@ data class ItemFilterSlotPacket(val slotID: Int, val newValue: ItemStack) { } } -data class ItemFilterNetworkSlot(val slotID: Int, val networkID: Int, val filter: ItemFilter?) { +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 + filter!![slotID] = value else remote = value } @@ -77,21 +85,85 @@ data class ItemFilterNetworkSlot(val slotID: Int, val networkID: Int, val filter } } +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( val size: Int, - private val modified: (slot: Int?, oldValue: ItemStack?, newValue: ItemStack?) -> Unit + private val modified: ItemFilterFullCallback? = null ) : INBTSerializable { + 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(size) { ItemStack.EMPTY } private val linkedFilter = LinkedList() + var isLocked = false + var isWhitelist = false set(value) { if (value != field) { field = value - modified.invoke(null, null, null) + modified?.invoke(this, null, null, null) } } + var matchTag = false + set(value) { + if (value != field) { + field = value + modified?.invoke(this, null, null, null) + } + } + + var matchNBT = false + set(value) { + if (value != field) { + field = value + modified?.invoke(this, null, null, null) + } + } + + fun clear() { + isWhitelist = false + matchTag = false + matchNBT = false + + Arrays.fill(filter, ItemStack.EMPTY) + linkedFilter.clear() + + modified?.invoke(this, null, null, null) + } + + 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) { if (value.isEmpty && filter[index].isEmpty) { return @@ -100,14 +172,17 @@ class ItemFilter( val old = filter[index] filter[index] = value.let { if (!it.isEmpty) it.copy().also { it.count = 1 } else it } + if (!filter[index].isEmpty && filter[index].tag != null && filter[index].tag!!.isEmpty) { + filter[index].tag = null + } + if (!old.isEmpty) linkedFilter.remove(old) if (!filter[index].isEmpty) linkedFilter.add(filter[index]) - modified.invoke(index, old, filter[index]) - + modified?.invoke(this, index, old, filter[index]) } operator fun get(index: Int): ItemStack = filter[index].copy() @@ -121,24 +196,48 @@ class ItemFilter( return !isWhitelist } - if (isWhitelist) { - for (item in linkedFilter) { - if (item.`is`(value.item)) { - return true + for (item in linkedFilter) { + var matched = item.`is`(value.item) + + if (matched && matchTag) { + matched = false + + val thisTags = item.tags + val stackTags = HashSet>() + + for (tag in value.tags) { + stackTags.add(tag) + } + + for (tag1 in thisTags) { + if (stackTags.contains(tag1)) { + matched = true + break + } } } - return false - } + if (matched && matchNBT) { + val a = item.tag + val b = value.tag + if (a == null && b == null) { + // nothing + } else if (a != null && b != null) { + matched = a == b + } else if (a != null) { + matched = a.isEmpty + } else { + matched = false + } + } - for (item in linkedFilter) { - if (item.`is`(value.item)) { - return false + if (matched) { + return isWhitelist } } - return true + return !isWhitelist } override fun serializeNBT(): CompoundTag { @@ -150,6 +249,8 @@ class ItemFilter( } it["is_whitelist"] = isWhitelist + it["match_tag"] = matchTag + it["match_nbt"] = matchNBT } } @@ -169,5 +270,7 @@ class ItemFilter( } isWhitelist = nbt.getBoolean("is_whitelist") + matchTag = nbt.getBoolean("match_tag") + matchNBT = nbt.getBoolean("match_nbt") } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/PortableCondensationDriveItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/PortableCondensationDriveItem.kt index 83170eaa0..a9c04884b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/PortableCondensationDriveItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/PortableCondensationDriveItem.kt @@ -24,7 +24,9 @@ import net.minecraftforge.event.ForgeEventFactory import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.event.entity.player.EntityItemPickupEvent import ru.dbotthepony.mc.otm.capability.drive.DrivePool +import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.ifHas import ru.dbotthepony.mc.otm.set import java.util.* @@ -92,117 +94,18 @@ class PortableCondensationDriveItem(capacity: Int) : return DriveCapability(stack) } - class FilterSettings() { - @JvmField - val items = Array(MAX_FILTERS) { ItemStack.EMPTY } - - @JvmField - var matchNbt = false - - @JvmField - var matchTag = false - - @JvmField - var isBlacklist = false - - constructor(tag: CompoundTag) : this() { - val list = tag.getList("filter", Tag.TAG_COMPOUND.toInt()) - var i = 0 - - for (tag in list) { - if (tag is CompoundTag) { - items[i++] = ItemStack.of(tag) - } - } - - matchNbt = tag.getBoolean("match_nbt") - matchTag = tag.getBoolean("match_tag") - isBlacklist = tag.getBoolean("blacklist") - } - - fun serializeNBT(compound: CompoundTag) { - val list = ListTag() - - for (i in 0 until MAX_FILTERS) { - list.add(items[i].serializeNBT()) - } - - compound["filter"] = list - compound["match_nbt"] = matchNbt - compound["match_tag"] = matchTag - compound["blacklist"] = isBlacklist - } - - fun serializeNBT(drive: ItemStack) { - serializeNBT(drive.orCreateTag) - } - - fun matches(stack: ItemStack): Boolean { - if (isBlacklist) { - for (item in items) { - if (!matchNbt && ItemStack.isSame(item, stack)) { - return false - } - - if (matchTag) { - val thisTags = item.tags - val stackTatgs = stack.tags.toArray() - - for (tag1 in thisTags) { - if (stackTatgs.contains(tag1)) { - return false - } - } - } - - if (matchNbt && ItemStack.isSameItemSameTags(item, stack)) { - return false - } - } - - return true - } else { - for (item in items) { - var same = ItemStack.isSame(item, stack) - - if (!same && matchTag) { - val thisTags = item.tags - val stackTatgs = stack.tags.toArray() - - for (tag1 in thisTags) { - if (stackTatgs.contains(tag1)) { - same = true - break - } - } - } - - if (matchNbt) { - if (same && ItemStack.tagMatches(item, stack)) { - return true - } - } else { - if (same) { - return true - } - } - } - - return false - } - } - - companion object { - const val MAX_FILTERS = 12 - } - } - - fun getFilterSettings(drive: ItemStack): FilterSettings { - return FilterSettings(drive.orCreateTag) + fun getFilterSettings(drive: ItemStack): ItemFilter { + val filter = ItemFilter(MAX_FILTERS) + filter.isWhitelist = true + drive.tag?.ifHas(FILTER_PATH, CompoundTag::class.java, filter::deserializeNBT) + return filter } @Suppress("unused") companion object { + const val MAX_FILTERS = 4 * 3 + const val FILTER_PATH = "filter" + @SubscribeEvent fun onPickupEvent(event: EntityItemPickupEvent) { if (event.item.owner != null && event.item.owner != event.player.uuid && event.item.age < 200) { @@ -221,7 +124,7 @@ class PortableCondensationDriveItem(capacity: Int) : stack.getCapability(MatteryCapability.DRIVE).ifPresent { val filter = drive.getFilterSettings(stack) - if (filter.matches(event.item.item)) { + if (filter.match(event.item.item)) { val copy = event.item.item.copy() val remaining = (it as ItemMatteryDrive).insertStack(event.item.item, false) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt index eeadbf6e2..1724d5423 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt @@ -1,24 +1,23 @@ package ru.dbotthepony.mc.otm.menu -import net.minecraft.network.FriendlyByteBuf import net.minecraft.world.SimpleContainer import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.item.ItemStack import net.minecraftforge.energy.CapabilityEnergy -import net.minecraftforge.network.NetworkEvent -import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.block.entity.DriveViewerBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive +import ru.dbotthepony.mc.otm.container.ItemFilter +import ru.dbotthepony.mc.otm.ifPresentK import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem -import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem.FilterSettings import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView +import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget import ru.dbotthepony.mc.otm.registry.MMenus +import ru.dbotthepony.mc.otm.storage.ITEM_STORAGE import ru.dbotthepony.mc.otm.storage.ItemStackWrapper import ru.dbotthepony.mc.otm.storage.PoweredVirtualComponent -import java.util.function.Supplier class DriveViewerMenu @JvmOverloads constructor( containerID: Int, @@ -27,9 +26,10 @@ class DriveViewerMenu @JvmOverloads constructor( ) : MatteryPoweredMenu( MMenus.DRIVE_VIEWER, containerID, inventory, tile ), INetworkedItemViewSupplier { - val view: NetworkedItemView - private val powered: PoweredVirtualComponent? + val view = NetworkedItemView(inventory.player, this, tile == null) val driveSlot: MatterySlot + + private val powered: PoweredVirtualComponent? private var lastDrive: IMatteryDrive? = null override fun getNetworkedItemView() = view @@ -43,8 +43,6 @@ class DriveViewerMenu @JvmOverloads constructor( } } - view = NetworkedItemView(inventory.player, this, tile == null) - if (tile != null) { powered = PoweredVirtualComponent( ItemStackWrapper::class.java, @@ -60,6 +58,26 @@ class DriveViewerMenu @JvmOverloads constructor( addInventorySlots() } + val driveFilter = ItemFilter(PortableCondensationDriveItem.MAX_FILTERS) { self, _, _, _ -> + if (tile?.container?.get(0)?.item is PortableCondensationDriveItem) { + tile.container[0].getOrCreateTag().put(PortableCondensationDriveItem.FILTER_PATH, self.serializeNBT()) + } + } + + val driveFilterSlots = addFilterSlots(driveFilter) + + val isWhitelist = BooleanPlayerInputWidget(this) + val matchTag = BooleanPlayerInputWidget(this) + val matchNBT = BooleanPlayerInputWidget(this) + + init { + if (tile == null) { + isWhitelist.asClient() + matchTag.asClient() + matchNBT.asClient() + } + } + override fun broadcastChanges() { super.broadcastChanges() @@ -70,21 +88,44 @@ class DriveViewerMenu @JvmOverloads constructor( lastDrive = null if (!itemStack.isEmpty) { - itemStack.getCapability(MatteryCapability.DRIVE).ifPresent { - if (it.storageType === OverdriveThatMatters.INSTANCE.ITEM_STORAGE()) { + itemStack.getCapability(MatteryCapability.DRIVE).ifPresentK { + if (it.storageType === ITEM_STORAGE) { lastDrive = it as IMatteryDrive } } } if (prev != lastDrive) { - if (prev != null) - powered!!.remove(prev) - + prev?.let(powered!!::remove) view.clear() + lastDrive?.let(powered!!::add) - if (lastDrive != null) - powered!!.add(lastDrive!!) + if (lastDrive != null) { + val filter = (itemStack.item as? PortableCondensationDriveItem)?.getFilterSettings(itemStack) + + if (filter != null) { + driveFilter.copyFrom(filter) + driveFilter.isLocked = false + + isWhitelist.withProperty(driveFilter::isWhitelist) + matchTag.withProperty(driveFilter::matchTag) + matchNBT.withProperty(driveFilter::matchNBT) + } else { + driveFilter.clear() + driveFilter.isLocked = true + + isWhitelist.withoutAnything() + matchTag.withoutAnything() + matchNBT.withoutAnything() + } + } else { + driveFilter.clear() + driveFilter.isLocked = true + + isWhitelist.withoutAnything() + matchTag.withoutAnything() + matchNBT.withoutAnything() + } } view.network() @@ -102,10 +143,10 @@ class DriveViewerMenu @JvmOverloads constructor( override fun removed(p_38940_: Player) { super.removed(p_38940_) - if (powered != null) - lastDrive?.removeListener(powered) + if (lastDrive != null) + powered?.remove(lastDrive!!) - view.clear() + view.removed() } override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack { @@ -135,107 +176,4 @@ class DriveViewerMenu @JvmOverloads constructor( slot.setChanged() return copy } - - enum class FilterSwitch { - MATCH_NBT, MATCH_TAG, BLACKLIST - } - - fun getFilter(): FilterSettings? { - if (driveSlot.item.isEmpty) - return null - - val item = driveSlot.item.item - return if (item is PortableCondensationDriveItem) item.getFilterSettings(driveSlot.item) else null - } - - class FilterSetPacket(val id: Int, val slot: Int, val value: ItemStack) { - fun write(buffer: FriendlyByteBuf) { - buffer.writeInt(id) - buffer.writeInt(slot) - buffer.writeItem(value) - } - - fun play(context: Supplier) { - context.get().packetHandled = true - - if (slot < 0 || slot >= FilterSettings.MAX_FILTERS) - return - - if (value.count > 1) - value.count = 1 - - context.get().enqueueWork { - val ply = context.get().sender!! - val menu = ply.containerMenu - - if (menu is DriveViewerMenu && menu.containerId == id) { - if (menu.driveSlot.item.isEmpty) - return@enqueueWork - - val itemStack = menu.driveSlot.item - val item = itemStack.item - - if (item is PortableCondensationDriveItem) { - val filter = item.getFilterSettings(itemStack) - filter.items[slot] = value - filter.serializeNBT(itemStack) - } - } - } - } - - companion object { - @JvmStatic - fun read(buffer: FriendlyByteBuf): FilterSetPacket { - return FilterSetPacket(buffer.readInt(), buffer.readInt(), buffer.readItem()) - } - } - } - - class FilterSwitchPacket(val id: Int, val type: FilterSwitch, val value: Boolean) { - fun write(buffer: FriendlyByteBuf) { - buffer.writeInt(id) - buffer.writeEnum(type) - buffer.writeBoolean(value) - } - - fun play(context: Supplier) { - context.get().packetHandled = true - context.get().enqueueWork { - val ply = context.get().sender!! - val menu = ply.containerMenu - - if (menu is DriveViewerMenu && menu.containerId == id) { - val settings = menu.getFilter() ?: return@enqueueWork - - when (type) { - FilterSwitch.MATCH_NBT -> { - settings.matchNbt = value - } - - FilterSwitch.MATCH_TAG -> { - settings.matchTag = value - } - - FilterSwitch.BLACKLIST -> { - settings.isBlacklist = value - } - } - - settings.serializeNBT(menu.driveSlot.item) - } - } - } - - companion object { - @JvmStatic - fun read(buffer: FriendlyByteBuf): FilterSwitchPacket { - return FilterSwitchPacket( - buffer.readInt(), - buffer.readEnum(FilterSwitch::class.java), - buffer.readBoolean() - ) - } - } - } } \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/BooleanPlayerInputWidget.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/BooleanPlayerInputWidget.kt index 8afd2c9e7..6f5be01ac 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/BooleanPlayerInputWidget.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/widget/BooleanPlayerInputWidget.kt @@ -55,6 +55,18 @@ class BooleanPlayerInputWidget(menu: MatteryMenu) : AbstractWidget(menu) { return this } + fun withProperty(state: KMutableProperty0): BooleanPlayerInputWidget { + withClicker { state.set(it) } + withSupplier { state.get() } + return this + } + + fun withoutAnything(): BooleanPlayerInputWidget { + supplier = null + clicker = null + return this + } + fun asClient(): BooleanPlayerInputWidget { supplier = null clicker = { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/VirtualComponent.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/VirtualComponent.kt index 652d4a26b..0fafaf82c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/VirtualComponent.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/VirtualComponent.kt @@ -35,13 +35,13 @@ open class VirtualComponent(type: StorageStackType) : IVir override val storageType: StorageStackType = type // удаленный UUID -> Кортеж - protected val remoteByUUID: MutableMap> = HashMap() + protected val remoteByUUID = HashMap>() // локальный UUID -> Локальный кортеж - protected val localByUUID: MutableMap> = HashMap() + protected val localByUUID = HashMap>() // Стак -> Локальный кортеж стака - protected val tuples: MutableMap> = HashMap() + protected val tuples = HashMap>() // ArrayList для скорости работы protected val listeners = ArrayList>() diff --git a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json index cce063935..c676c6341 100644 --- a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json +++ b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json @@ -36,6 +36,8 @@ "otm.gui.matter.name": "MtU", "otm.gui.filter.is_whitelist": "Is Whitelist", + "otm.gui.filter.match_nbt": "Match NBT", + "otm.gui.filter.match_tag": "Match Tag", "otm.gui.android_research": "Research Tree", @@ -88,10 +90,6 @@ "otm.filter.yes": "Yes", "otm.filter.no": "No", - "otm.filter.match_nbt": "Match NBT: %s", - "otm.filter.match_tag": "Match Tag: %s", - "otm.filter.blacklist": "Blacklist: %s", - "otm.matter_bottler.switch_mode": "Switch work mode", "android_feature.overdrive_that_matters.air_bags": "Air Bags",