Portable condensation drive now use new item filter
Item filter now supports tag and nbt matching
This commit is contained in:
parent
86c706a178
commit
89581bbb52
@ -50,6 +50,10 @@ public class FlexGridPanel extends EditablePanel {
|
|||||||
// список потомков
|
// список потомков
|
||||||
var children = getUndockedChildren();
|
var children = getUndockedChildren();
|
||||||
|
|
||||||
|
if (children.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// хранит общую ширину всех потомков в ряд
|
// хранит общую ширину всех потомков в ряд
|
||||||
// а так же ограничитель ширины ряда после
|
// а так же ограничитель ширины ряда после
|
||||||
// определения количества рядов
|
// определения количества рядов
|
||||||
|
@ -233,24 +233,6 @@ public class MatteryNetworking {
|
|||||||
Optional.of(NetworkDirection.PLAY_TO_CLIENT)
|
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(
|
CHANNEL.registerMessage(
|
||||||
next_network_id++,
|
next_network_id++,
|
||||||
EnergyCounterPacket.class,
|
EnergyCounterPacket.class,
|
||||||
|
@ -6,11 +6,8 @@ import net.minecraft.world.entity.player.Inventory
|
|||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.*
|
import ru.dbotthepony.mc.otm.client.screen.panels.*
|
||||||
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
|
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
|
||||||
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) :
|
class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Component) :
|
||||||
MatteryScreen<DriveViewerMenu>(menu, inventory, title) {
|
MatteryScreen<DriveViewerMenu>(menu, inventory, title) {
|
||||||
@ -86,134 +83,13 @@ class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Comp
|
|||||||
settings.add(dock_left)
|
settings.add(dock_left)
|
||||||
settings.add(grid_filter)
|
settings.add(grid_filter)
|
||||||
|
|
||||||
for (i in 0 until FilterSettings.MAX_FILTERS) {
|
for (i in 0 until PortableCondensationDriveItem.MAX_FILTERS) {
|
||||||
object : AbstractSlotPanel(this@DriveViewerScreen, grid_filter, 0f, 0f) {
|
FilterSlotPanel(this, grid_filter, menu.driveFilterSlots[i], 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val no = TranslatableComponent("otm.filter.no")
|
CheckBoxLabelInputPanel(this, dock_left, menu.isWhitelist, TranslatableComponent("otm.gui.filter.is_whitelist"), width = 90f, height = 20f).also { it.setDockMargin(0f, 4f, 0f, 0f) }
|
||||||
val yes = TranslatableComponent("otm.filter.yes")
|
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) }
|
||||||
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)
|
|
||||||
|
|
||||||
for (panel in settings) {
|
for (panel in settings) {
|
||||||
panel.visible = false
|
panel.visible = false
|
||||||
|
@ -4,6 +4,8 @@ import net.minecraft.nbt.CompoundTag
|
|||||||
import net.minecraft.nbt.ListTag
|
import net.minecraft.nbt.ListTag
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.server.level.ServerPlayer
|
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.minecraft.world.item.ItemStack
|
||||||
import net.minecraftforge.common.util.INBTSerializable
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
import net.minecraftforge.network.NetworkEvent
|
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.ifHas
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.set
|
import ru.dbotthepony.mc.otm.set
|
||||||
|
import java.util.Arrays
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
|
||||||
@ -42,7 +45,12 @@ data class ItemFilterSlotPacket(val slotID: Int, val newValue: ItemStack) {
|
|||||||
|
|
||||||
fun playServer(player: ServerPlayer) {
|
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")
|
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 {
|
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 get() = filter?.get(slotID) ?: remote
|
||||||
fun set(value: ItemStack) {
|
fun set(value: ItemStack) {
|
||||||
if (filter != null)
|
if (filter != null)
|
||||||
filter[slotID] = value
|
filter!![slotID] = value
|
||||||
else
|
else
|
||||||
remote = value
|
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(
|
class ItemFilter(
|
||||||
val size: Int,
|
val size: Int,
|
||||||
private val modified: (slot: Int?, oldValue: ItemStack?, newValue: ItemStack?) -> Unit
|
private val modified: ItemFilterFullCallback? = 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>()
|
||||||
|
|
||||||
|
var isLocked = false
|
||||||
|
|
||||||
var isWhitelist = false
|
var isWhitelist = false
|
||||||
set(value) {
|
set(value) {
|
||||||
if (value != field) {
|
if (value != field) {
|
||||||
field = value
|
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) {
|
operator fun set(index: Int, value: ItemStack) {
|
||||||
if (value.isEmpty && filter[index].isEmpty) {
|
if (value.isEmpty && filter[index].isEmpty) {
|
||||||
return
|
return
|
||||||
@ -100,14 +172,17 @@ class ItemFilter(
|
|||||||
val old = filter[index]
|
val old = filter[index]
|
||||||
filter[index] = value.let { if (!it.isEmpty) it.copy().also { it.count = 1 } else it }
|
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)
|
if (!old.isEmpty)
|
||||||
linkedFilter.remove(old)
|
linkedFilter.remove(old)
|
||||||
|
|
||||||
if (!filter[index].isEmpty)
|
if (!filter[index].isEmpty)
|
||||||
linkedFilter.add(filter[index])
|
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()
|
operator fun get(index: Int): ItemStack = filter[index].copy()
|
||||||
@ -121,24 +196,48 @@ class ItemFilter(
|
|||||||
return !isWhitelist
|
return !isWhitelist
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWhitelist) {
|
for (item in linkedFilter) {
|
||||||
for (item in linkedFilter) {
|
var matched = item.`is`(value.item)
|
||||||
if (item.`is`(value.item)) {
|
|
||||||
return true
|
if (matched && matchTag) {
|
||||||
|
matched = false
|
||||||
|
|
||||||
|
val thisTags = item.tags
|
||||||
|
val stackTags = HashSet<TagKey<Item>>()
|
||||||
|
|
||||||
|
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 (matched) {
|
||||||
if (item.`is`(value.item)) {
|
return isWhitelist
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return !isWhitelist
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun serializeNBT(): CompoundTag {
|
override fun serializeNBT(): CompoundTag {
|
||||||
@ -150,6 +249,8 @@ class ItemFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
it["is_whitelist"] = isWhitelist
|
it["is_whitelist"] = isWhitelist
|
||||||
|
it["match_tag"] = matchTag
|
||||||
|
it["match_nbt"] = matchNBT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,5 +270,7 @@ class ItemFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
isWhitelist = nbt.getBoolean("is_whitelist")
|
isWhitelist = nbt.getBoolean("is_whitelist")
|
||||||
|
matchTag = nbt.getBoolean("match_tag")
|
||||||
|
matchNBT = nbt.getBoolean("match_nbt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,9 @@ import net.minecraftforge.event.ForgeEventFactory
|
|||||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||||
import net.minecraftforge.event.entity.player.EntityItemPickupEvent
|
import net.minecraftforge.event.entity.player.EntityItemPickupEvent
|
||||||
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.core.ImpreciseFraction
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
|
import ru.dbotthepony.mc.otm.ifHas
|
||||||
import ru.dbotthepony.mc.otm.set
|
import ru.dbotthepony.mc.otm.set
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -92,117 +94,18 @@ class PortableCondensationDriveItem(capacity: Int) :
|
|||||||
return DriveCapability(stack)
|
return DriveCapability(stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
class FilterSettings() {
|
fun getFilterSettings(drive: ItemStack): ItemFilter {
|
||||||
@JvmField
|
val filter = ItemFilter(MAX_FILTERS)
|
||||||
val items = Array<ItemStack>(MAX_FILTERS) { ItemStack.EMPTY }
|
filter.isWhitelist = true
|
||||||
|
drive.tag?.ifHas(FILTER_PATH, CompoundTag::class.java, filter::deserializeNBT)
|
||||||
@JvmField
|
return filter
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
companion object {
|
companion object {
|
||||||
|
const val MAX_FILTERS = 4 * 3
|
||||||
|
const val FILTER_PATH = "filter"
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
fun onPickupEvent(event: EntityItemPickupEvent) {
|
fun onPickupEvent(event: EntityItemPickupEvent) {
|
||||||
if (event.item.owner != null && event.item.owner != event.player.uuid && event.item.age < 200) {
|
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 {
|
stack.getCapability(MatteryCapability.DRIVE).ifPresent {
|
||||||
val filter = drive.getFilterSettings(stack)
|
val filter = drive.getFilterSettings(stack)
|
||||||
|
|
||||||
if (filter.matches(event.item.item)) {
|
if (filter.match(event.item.item)) {
|
||||||
val copy = event.item.item.copy()
|
val copy = event.item.item.copy()
|
||||||
val remaining = (it as ItemMatteryDrive).insertStack(event.item.item, false)
|
val remaining = (it as ItemMatteryDrive).insertStack(event.item.item, false)
|
||||||
|
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
package ru.dbotthepony.mc.otm.menu
|
package ru.dbotthepony.mc.otm.menu
|
||||||
|
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
|
||||||
import net.minecraft.world.SimpleContainer
|
import net.minecraft.world.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraftforge.energy.CapabilityEnergy
|
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.block.entity.DriveViewerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
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.container.ItemFilter
|
||||||
|
import ru.dbotthepony.mc.otm.ifPresentK
|
||||||
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem
|
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.INetworkedItemViewSupplier
|
||||||
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView
|
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.registry.MMenus
|
||||||
|
import ru.dbotthepony.mc.otm.storage.ITEM_STORAGE
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||||
import ru.dbotthepony.mc.otm.storage.PoweredVirtualComponent
|
import ru.dbotthepony.mc.otm.storage.PoweredVirtualComponent
|
||||||
import java.util.function.Supplier
|
|
||||||
|
|
||||||
class DriveViewerMenu @JvmOverloads constructor(
|
class DriveViewerMenu @JvmOverloads constructor(
|
||||||
containerID: Int,
|
containerID: Int,
|
||||||
@ -27,9 +26,10 @@ class DriveViewerMenu @JvmOverloads constructor(
|
|||||||
) : MatteryPoweredMenu(
|
) : MatteryPoweredMenu(
|
||||||
MMenus.DRIVE_VIEWER, containerID, inventory, tile
|
MMenus.DRIVE_VIEWER, containerID, inventory, tile
|
||||||
), INetworkedItemViewSupplier {
|
), INetworkedItemViewSupplier {
|
||||||
val view: NetworkedItemView
|
val view = NetworkedItemView(inventory.player, this, tile == null)
|
||||||
private val powered: PoweredVirtualComponent<ItemStackWrapper>?
|
|
||||||
val driveSlot: MatterySlot
|
val driveSlot: MatterySlot
|
||||||
|
|
||||||
|
private val powered: PoweredVirtualComponent<ItemStackWrapper>?
|
||||||
private var lastDrive: IMatteryDrive<ItemStackWrapper>? = null
|
private var lastDrive: IMatteryDrive<ItemStackWrapper>? = null
|
||||||
|
|
||||||
override fun getNetworkedItemView() = view
|
override fun getNetworkedItemView() = view
|
||||||
@ -43,8 +43,6 @@ class DriveViewerMenu @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view = NetworkedItemView(inventory.player, this, tile == null)
|
|
||||||
|
|
||||||
if (tile != null) {
|
if (tile != null) {
|
||||||
powered = PoweredVirtualComponent(
|
powered = PoweredVirtualComponent(
|
||||||
ItemStackWrapper::class.java,
|
ItemStackWrapper::class.java,
|
||||||
@ -60,6 +58,26 @@ class DriveViewerMenu @JvmOverloads constructor(
|
|||||||
addInventorySlots()
|
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() {
|
override fun broadcastChanges() {
|
||||||
super.broadcastChanges()
|
super.broadcastChanges()
|
||||||
|
|
||||||
@ -70,21 +88,44 @@ class DriveViewerMenu @JvmOverloads constructor(
|
|||||||
lastDrive = null
|
lastDrive = null
|
||||||
|
|
||||||
if (!itemStack.isEmpty) {
|
if (!itemStack.isEmpty) {
|
||||||
itemStack.getCapability(MatteryCapability.DRIVE).ifPresent {
|
itemStack.getCapability(MatteryCapability.DRIVE).ifPresentK {
|
||||||
if (it.storageType === OverdriveThatMatters.INSTANCE.ITEM_STORAGE()) {
|
if (it.storageType === ITEM_STORAGE) {
|
||||||
lastDrive = it as IMatteryDrive<ItemStackWrapper>
|
lastDrive = it as IMatteryDrive<ItemStackWrapper>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev != lastDrive) {
|
if (prev != lastDrive) {
|
||||||
if (prev != null)
|
prev?.let(powered!!::remove)
|
||||||
powered!!.remove(prev)
|
|
||||||
|
|
||||||
view.clear()
|
view.clear()
|
||||||
|
lastDrive?.let(powered!!::add)
|
||||||
|
|
||||||
if (lastDrive != null)
|
if (lastDrive != null) {
|
||||||
powered!!.add(lastDrive!!)
|
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()
|
view.network()
|
||||||
@ -102,10 +143,10 @@ class DriveViewerMenu @JvmOverloads constructor(
|
|||||||
override fun removed(p_38940_: Player) {
|
override fun removed(p_38940_: Player) {
|
||||||
super.removed(p_38940_)
|
super.removed(p_38940_)
|
||||||
|
|
||||||
if (powered != null)
|
if (lastDrive != null)
|
||||||
lastDrive?.removeListener(powered)
|
powered?.remove(lastDrive!!)
|
||||||
|
|
||||||
view.clear()
|
view.removed()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack {
|
override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack {
|
||||||
@ -135,107 +176,4 @@ class DriveViewerMenu @JvmOverloads constructor(
|
|||||||
slot.setChanged()
|
slot.setChanged()
|
||||||
return copy
|
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<NetworkEvent.Context>) {
|
|
||||||
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<NetworkEvent.Context>) {
|
|
||||||
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()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -55,6 +55,18 @@ class BooleanPlayerInputWidget(menu: MatteryMenu) : AbstractWidget(menu) {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun withProperty(state: KMutableProperty0<Boolean>): BooleanPlayerInputWidget {
|
||||||
|
withClicker { state.set(it) }
|
||||||
|
withSupplier { state.get() }
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withoutAnything(): BooleanPlayerInputWidget {
|
||||||
|
supplier = null
|
||||||
|
clicker = null
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
fun asClient(): BooleanPlayerInputWidget {
|
fun asClient(): BooleanPlayerInputWidget {
|
||||||
supplier = null
|
supplier = null
|
||||||
clicker = {
|
clicker = {
|
||||||
|
@ -35,13 +35,13 @@ open class VirtualComponent<T : IStorageStack>(type: StorageStackType<T>) : IVir
|
|||||||
override val storageType: StorageStackType<T> = type
|
override val storageType: StorageStackType<T> = type
|
||||||
|
|
||||||
// удаленный UUID -> Кортеж
|
// удаленный UUID -> Кортеж
|
||||||
protected val remoteByUUID: MutableMap<UUID, RemoteTuple<T>> = HashMap()
|
protected val remoteByUUID = HashMap<UUID, RemoteTuple<T>>()
|
||||||
|
|
||||||
// локальный UUID -> Локальный кортеж
|
// локальный UUID -> Локальный кортеж
|
||||||
protected val localByUUID: MutableMap<UUID, LocalTuple<T>> = HashMap()
|
protected val localByUUID = HashMap<UUID, LocalTuple<T>>()
|
||||||
|
|
||||||
// Стак -> Локальный кортеж стака
|
// Стак -> Локальный кортеж стака
|
||||||
protected val tuples: MutableMap<T, LocalTuple<T>> = HashMap()
|
protected val tuples = HashMap<T, LocalTuple<T>>()
|
||||||
|
|
||||||
// ArrayList для скорости работы
|
// ArrayList для скорости работы
|
||||||
protected val listeners = ArrayList<IStorageListener<T>>()
|
protected val listeners = ArrayList<IStorageListener<T>>()
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
"otm.gui.matter.name": "MtU",
|
"otm.gui.matter.name": "MtU",
|
||||||
|
|
||||||
"otm.gui.filter.is_whitelist": "Is Whitelist",
|
"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",
|
"otm.gui.android_research": "Research Tree",
|
||||||
|
|
||||||
@ -88,10 +90,6 @@
|
|||||||
"otm.filter.yes": "Yes",
|
"otm.filter.yes": "Yes",
|
||||||
"otm.filter.no": "No",
|
"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",
|
"otm.matter_bottler.switch_mode": "Switch work mode",
|
||||||
|
|
||||||
"android_feature.overdrive_that_matters.air_bags": "Air Bags",
|
"android_feature.overdrive_that_matters.air_bags": "Air Bags",
|
||||||
|
Loading…
Reference in New Issue
Block a user