Item Filter and storage bus menu
This commit is contained in:
parent
5b245ec564
commit
aa6f28977b
@ -8,6 +8,7 @@ import net.minecraftforge.network.PacketDistributor;
|
|||||||
import net.minecraftforge.network.simple.SimpleChannel;
|
import net.minecraftforge.network.simple.SimpleChannel;
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
||||||
import ru.dbotthepony.mc.otm.block.entity.EnergyCounterPacket;
|
import ru.dbotthepony.mc.otm.block.entity.EnergyCounterPacket;
|
||||||
|
import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket;
|
||||||
import ru.dbotthepony.mc.otm.item.weapon.WeaponScopePacket;
|
import ru.dbotthepony.mc.otm.item.weapon.WeaponScopePacket;
|
||||||
import ru.dbotthepony.mc.otm.item.weapon.WeaponFireInputPacket;
|
import ru.dbotthepony.mc.otm.item.weapon.WeaponFireInputPacket;
|
||||||
import ru.dbotthepony.mc.otm.matter.RegistryPacketClear;
|
import ru.dbotthepony.mc.otm.matter.RegistryPacketClear;
|
||||||
@ -312,5 +313,14 @@ public class MatteryNetworking {
|
|||||||
WeaponFireInputPacket::play,
|
WeaponFireInputPacket::play,
|
||||||
Optional.of(NetworkDirection.PLAY_TO_SERVER)
|
Optional.of(NetworkDirection.PLAY_TO_SERVER)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CHANNEL.registerMessage(
|
||||||
|
next_network_id++,
|
||||||
|
ItemFilterSlotPacket.class,
|
||||||
|
ItemFilterSlotPacket::write,
|
||||||
|
ItemFilterSlotPacket.Companion::read,
|
||||||
|
ItemFilterSlotPacket::play
|
||||||
|
// Optional.of(NetworkDirection.)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package ru.dbotthepony.mc.otm.block.entity
|
|||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.nbt.ListTag
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.network.chat.TranslatableComponent
|
import net.minecraft.network.chat.TranslatableComponent
|
||||||
import net.minecraft.server.level.ServerLevel
|
import net.minecraft.server.level.ServerLevel
|
||||||
@ -20,10 +22,12 @@ import ru.dbotthepony.mc.otm.*
|
|||||||
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
|
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
|
||||||
|
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.core.plus
|
import ru.dbotthepony.mc.otm.core.plus
|
||||||
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
|
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
|
||||||
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
|
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
|
||||||
|
import ru.dbotthepony.mc.otm.menu.StorageBusMenu
|
||||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||||
import ru.dbotthepony.mc.otm.registry.MNames
|
import ru.dbotthepony.mc.otm.registry.MNames
|
||||||
import ru.dbotthepony.mc.otm.storage.*
|
import ru.dbotthepony.mc.otm.storage.*
|
||||||
@ -53,13 +57,17 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
override val defaultDisplayName: Component
|
override val defaultDisplayName: Component
|
||||||
get() = MACHINE_NAME
|
get() = MACHINE_NAME
|
||||||
|
|
||||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||||
return null
|
return StorageBusMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val energy = WorkerEnergyStorage(this, maxBatteryLevel = MAX_POWER)
|
override val energy = WorkerEnergyStorage(this, maxBatteryLevel = MAX_POWER)
|
||||||
val cell = BasicStorageGraphNode(energy)
|
val cell = BasicStorageGraphNode(energy)
|
||||||
|
|
||||||
|
val filter = ItemFilter(MAX_FILTERS) { _, _, _ ->
|
||||||
|
component?.scan()
|
||||||
|
}
|
||||||
|
|
||||||
override fun setLevel(p_155231_: Level) {
|
override fun setLevel(p_155231_: Level) {
|
||||||
super.setLevel(p_155231_)
|
super.setLevel(p_155231_)
|
||||||
|
|
||||||
@ -105,6 +113,18 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
valid = false
|
valid = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun saveAdditional(nbt: CompoundTag) {
|
||||||
|
super.saveAdditional(nbt)
|
||||||
|
|
||||||
|
nbt["filter"] = filter.serializeNBT()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun load(nbt: CompoundTag) {
|
||||||
|
super.load(nbt)
|
||||||
|
|
||||||
|
nbt.ifHas("filter", ListTag::class.java, filter::deserializeNBT)
|
||||||
|
}
|
||||||
|
|
||||||
fun checkSurroundings() {
|
fun checkSurroundings() {
|
||||||
if (isRemoved)
|
if (isRemoved)
|
||||||
return
|
return
|
||||||
@ -139,6 +159,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
companion object {
|
companion object {
|
||||||
private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_BUS}")
|
private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_BUS}")
|
||||||
private val MAX_POWER = ImpreciseFraction(10_000)
|
private val MAX_POWER = ImpreciseFraction(10_000)
|
||||||
|
const val MAX_FILTERS = 6 * 3
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class ItemHandlerComponent(private val parent: IItemHandler) : IStorageComponent<ItemStackWrapper> {
|
private inner class ItemHandlerComponent(private val parent: IItemHandler) : IStorageComponent<ItemStackWrapper> {
|
||||||
@ -272,7 +293,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun scan(slot: Int) {
|
fun scan(slot: Int) {
|
||||||
val current = parent[slot].let { if (it.isEmpty) null else it }
|
val current = parent[slot].let { if (it.isEmpty || !filter.match(it)) null else it }
|
||||||
val last = scanned[slot]
|
val last = scanned[slot]
|
||||||
|
|
||||||
if (current == null && last != null) {
|
if (current == null && last != null) {
|
||||||
@ -298,7 +319,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun insertStack(stack: ItemStackWrapper, simulate: Boolean): ItemStackWrapper {
|
override fun insertStack(stack: ItemStackWrapper, simulate: Boolean): ItemStackWrapper {
|
||||||
if (energy.batteryLevel.isZero)
|
if (energy.batteryLevel.isZero || !filter.match(stack.item))
|
||||||
return stack
|
return stack
|
||||||
|
|
||||||
val maxPossibleDemand = stack.count * ITEM_STORAGE.energyPerOperation
|
val maxPossibleDemand = stack.count * ITEM_STORAGE.energyPerOperation
|
||||||
|
@ -3,5 +3,5 @@ package ru.dbotthepony.mc.otm.client
|
|||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.client.gui.Font
|
import net.minecraft.client.gui.Font
|
||||||
|
|
||||||
val minecraft: Minecraft get() = Minecraft.getInstance()
|
inline val minecraft: Minecraft get() = Minecraft.getInstance()
|
||||||
val font: Font get() = minecraft.font
|
inline val font: Font get() = minecraft.font
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.client.screen
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.Component
|
||||||
|
import net.minecraft.world.entity.player.Inventory
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.panels.FilterSlotPanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.panels.SlotPanel
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
|
||||||
|
|
||||||
|
import ru.dbotthepony.mc.otm.menu.StorageBusMenu
|
||||||
|
|
||||||
|
class StorageBusScreen(menu: StorageBusMenu, inventory: Inventory, title: Component) :
|
||||||
|
MatteryScreen<StorageBusMenu>(menu, inventory, title) {
|
||||||
|
override fun makeMainFrame(): FramePanel {
|
||||||
|
val frame = super.makeMainFrame()!!
|
||||||
|
|
||||||
|
PowerGaugePanel(this, frame, menu.powerWidget, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT)
|
||||||
|
SlotPanel(this, frame, menu.batterySlot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE)
|
||||||
|
|
||||||
|
for (row in 0 .. 2) {
|
||||||
|
for (column in 0 .. 5) {
|
||||||
|
FilterSlotPanel(this, frame, menu.busFilterSlots[row + column * 3], 55f + 18f * column, 17f + 18f * row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.client.screen.panels
|
||||||
|
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
||||||
|
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
|
||||||
|
import ru.dbotthepony.mc.otm.container.ItemFilterSlotPacket
|
||||||
|
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||||
|
|
||||||
|
open class FilterSlotPanel(
|
||||||
|
screen: MatteryScreen<*>,
|
||||||
|
parent: EditablePanel?,
|
||||||
|
val slot: ItemFilterNetworkSlot,
|
||||||
|
x: Float = 0f,
|
||||||
|
y: Float = 0f,
|
||||||
|
width: Float = REGULAR_DIMENSIONS,
|
||||||
|
height: Float = REGULAR_DIMENSIONS
|
||||||
|
) : AbstractSlotPanel(screen, parent, x, y, width, height) {
|
||||||
|
override fun getItemStack(): ItemStack {
|
||||||
|
return slot.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean {
|
||||||
|
if (screen.menu.carried.isEmpty) {
|
||||||
|
MatteryNetworking.CHANNEL.sendToServer(ItemFilterSlotPacket(slot.networkID, ItemStack.EMPTY))
|
||||||
|
} else {
|
||||||
|
MatteryNetworking.CHANNEL.sendToServer(ItemFilterSlotPacket(slot.networkID, screen.menu.carried))
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
163
src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt
Normal file
163
src/main/kotlin/ru/dbotthepony/mc/otm/container/ItemFilter.kt
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.container
|
||||||
|
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.nbt.ListTag
|
||||||
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
|
import net.minecraft.server.level.ServerPlayer
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
|
import net.minecraftforge.network.NetworkEvent
|
||||||
|
import org.apache.logging.log4j.LogManager
|
||||||
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
|
import java.util.LinkedList
|
||||||
|
import java.util.function.Supplier
|
||||||
|
|
||||||
|
data class ItemFilterSlotPacket(val slotID: Int, val newValue: ItemStack) {
|
||||||
|
fun write(buff: FriendlyByteBuf) {
|
||||||
|
buff.writeInt(slotID)
|
||||||
|
buff.writeItemStack(newValue, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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!")
|
||||||
|
}
|
||||||
|
|
||||||
|
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, val 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemFilter(
|
||||||
|
val size: Int,
|
||||||
|
private val modified: (slot: Int?, oldValue: ItemStack?, newValue: ItemStack?) -> Unit
|
||||||
|
) : INBTSerializable<ListTag> {
|
||||||
|
private val filter = Array<ItemStack>(size) { ItemStack.EMPTY }
|
||||||
|
private val linkedFilter = LinkedList<ItemStack>()
|
||||||
|
|
||||||
|
var isWhitelist = false
|
||||||
|
set(value) {
|
||||||
|
if (value != field) {
|
||||||
|
field = value
|
||||||
|
modified.invoke(null, null, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(index: Int, value: ItemStack) {
|
||||||
|
if (value.isEmpty && filter[index].isEmpty) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val old = filter[index]
|
||||||
|
filter[index] = value.let { if (!it.isEmpty) it.copy().also { it.count = 1 } else it }
|
||||||
|
|
||||||
|
if (!old.isEmpty)
|
||||||
|
linkedFilter.remove(old)
|
||||||
|
|
||||||
|
if (!filter[index].isEmpty)
|
||||||
|
linkedFilter.add(filter[index])
|
||||||
|
|
||||||
|
modified.invoke(index, old, filter[index])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun get(index: Int): ItemStack = filter[index].copy()
|
||||||
|
|
||||||
|
fun match(value: ItemStack): Boolean {
|
||||||
|
if (value.isEmpty) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkedFilter.isEmpty()) {
|
||||||
|
return !isWhitelist
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWhitelist) {
|
||||||
|
for (item in linkedFilter) {
|
||||||
|
if (item.`is`(value.item)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (item in linkedFilter) {
|
||||||
|
if (item.`is`(value.item)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serializeNBT(): ListTag {
|
||||||
|
return ListTag().also {
|
||||||
|
for (value in filter) {
|
||||||
|
it.add(value.serializeNBT())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserializeNBT(nbt: ListTag?) {
|
||||||
|
for (i in filter.indices)
|
||||||
|
filter[i] = ItemStack.EMPTY
|
||||||
|
|
||||||
|
if (nbt == null)
|
||||||
|
return
|
||||||
|
|
||||||
|
for ((i, value) in nbt.withIndex()) {
|
||||||
|
if (value is CompoundTag) {
|
||||||
|
filter[i] = ItemStack.of(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,7 @@ class MatterBottlerMenu @JvmOverloads constructor(
|
|||||||
} else {
|
} else {
|
||||||
progressWidget = ProgressGaugeWidget(this) { tile.getWorkProgress() }
|
progressWidget = ProgressGaugeWidget(this) { tile.getWorkProgress() }
|
||||||
matterWidget = LevelGaugeWidget(this, tile.matter)
|
matterWidget = LevelGaugeWidget(this, tile.matter)
|
||||||
workFlow = BooleanPlayerInputWidget(this).withSupplier { tile.workFlow }.withClicker { tile.workFlow = it }
|
workFlow = BooleanPlayerInputWidget(this, tile::workFlow)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.container = Array(6) { index ->
|
this.container = Array(6) { index ->
|
||||||
|
@ -7,9 +7,12 @@ import net.minecraft.world.inventory.*
|
|||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity
|
import net.minecraft.world.level.block.entity.BlockEntity
|
||||||
import net.minecraftforge.network.PacketDistributor
|
import net.minecraftforge.network.PacketDistributor
|
||||||
|
import ru.dbotthepony.mc.otm.container.ItemFilter
|
||||||
|
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
|
||||||
import ru.dbotthepony.mc.otm.menu.data.MultiByteDataContainer
|
import ru.dbotthepony.mc.otm.menu.data.MultiByteDataContainer
|
||||||
import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget
|
import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget
|
||||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||||
|
import java.util.Collections
|
||||||
|
|
||||||
@JvmRecord
|
@JvmRecord
|
||||||
data class MoveResult(val mergeOccurred: Boolean, val remaining: ItemStack, val changed_slots: Set<Slot>)
|
data class MoveResult(val mergeOccurred: Boolean, val remaining: ItemStack, val changed_slots: Set<Slot>)
|
||||||
@ -37,6 +40,29 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
@JvmField
|
@JvmField
|
||||||
protected var _synchronizer: ContainerSynchronizer? = null
|
protected var _synchronizer: ContainerSynchronizer? = null
|
||||||
|
|
||||||
|
private val _filterSlots = ArrayList<ItemFilterNetworkSlot>()
|
||||||
|
val filterSlots = Collections.unmodifiableList(_filterSlots)
|
||||||
|
|
||||||
|
fun addFilterSlots(slots: ItemFilter): List<ItemFilterNetworkSlot> {
|
||||||
|
val result = ArrayList<ItemFilterNetworkSlot>(slots.size)
|
||||||
|
|
||||||
|
for (i in 0 until slots.size) {
|
||||||
|
_filterSlots.add(ItemFilterNetworkSlot(i, _filterSlots.size, slots).also(result::add))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addFilterSlots(amount: Int): List<ItemFilterNetworkSlot> {
|
||||||
|
val result = ArrayList<ItemFilterNetworkSlot>(amount)
|
||||||
|
|
||||||
|
for (i in 0 until amount) {
|
||||||
|
_filterSlots.add(ItemFilterNetworkSlot(i, _filterSlots.size, null).also(result::add))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
override fun setSynchronizer(p_150417_: ContainerSynchronizer) {
|
override fun setSynchronizer(p_150417_: ContainerSynchronizer) {
|
||||||
_synchronizer = p_150417_
|
_synchronizer = p_150417_
|
||||||
super.setSynchronizer(p_150417_)
|
super.setSynchronizer(p_150417_)
|
||||||
@ -143,6 +169,16 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
super.broadcastChanges()
|
super.broadcastChanges()
|
||||||
|
|
||||||
|
val consumer = PacketDistributor.PLAYER.with { ply as ServerPlayer }
|
||||||
|
|
||||||
|
for (slot in _filterSlots) {
|
||||||
|
val packet = slot.sendChanges()
|
||||||
|
|
||||||
|
if (packet != null) {
|
||||||
|
MatteryNetworking.CHANNEL.send(consumer, packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun broadcastFullState() {
|
override fun broadcastFullState() {
|
||||||
@ -155,6 +191,16 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
super.broadcastFullState()
|
super.broadcastFullState()
|
||||||
|
|
||||||
|
val consumer = PacketDistributor.PLAYER.with { ply as ServerPlayer }
|
||||||
|
|
||||||
|
for (slot in _filterSlots) {
|
||||||
|
val packet = slot.sendChanges(true)
|
||||||
|
|
||||||
|
if (packet != null) {
|
||||||
|
MatteryNetworking.CHANNEL.send(consumer, packet)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stillValid(player: Player): Boolean {
|
override fun stillValid(player: Player): Boolean {
|
||||||
|
@ -9,10 +9,10 @@ import ru.dbotthepony.mc.otm.registry.MMenus
|
|||||||
|
|
||||||
class PatternStorageMenu @JvmOverloads constructor(
|
class PatternStorageMenu @JvmOverloads constructor(
|
||||||
p_38852_: Int,
|
p_38852_: Int,
|
||||||
inventory: Inventory?,
|
inventory: Inventory,
|
||||||
tile: PatternStorageBlockEntity? = null
|
tile: PatternStorageBlockEntity? = null
|
||||||
) : MatteryMenu(
|
) : MatteryMenu(
|
||||||
MMenus.PATTERN_STORAGE, p_38852_, inventory!!, tile
|
MMenus.PATTERN_STORAGE, p_38852_, inventory, tile
|
||||||
) {
|
) {
|
||||||
val patternSlots = arrayOfNulls<PatternSlot>(2 * 4)
|
val patternSlots = arrayOfNulls<PatternSlot>(2 * 4)
|
||||||
val storedThis: LevelGaugeWidget
|
val storedThis: LevelGaugeWidget
|
||||||
|
33
src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageBusMenu.kt
Normal file
33
src/main/kotlin/ru/dbotthepony/mc/otm/menu/StorageBusMenu.kt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.menu
|
||||||
|
|
||||||
|
import net.minecraft.world.entity.player.Inventory
|
||||||
|
import ru.dbotthepony.mc.otm.block.entity.StorageBusBlockEntity
|
||||||
|
import ru.dbotthepony.mc.otm.container.ItemFilterNetworkSlot
|
||||||
|
import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||||
|
|
||||||
|
class StorageBusMenu @JvmOverloads constructor(
|
||||||
|
p_38852_: Int,
|
||||||
|
inventory: Inventory,
|
||||||
|
tile: StorageBusBlockEntity? = null
|
||||||
|
) : MatteryPoweredMenu(
|
||||||
|
MMenus.STORAGE_BUS, p_38852_, inventory, tile
|
||||||
|
) {
|
||||||
|
val busFilterSlots: List<ItemFilterNetworkSlot>
|
||||||
|
val busFilterState: BooleanPlayerInputWidget
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (tile != null) {
|
||||||
|
busFilterSlots = addFilterSlots(tile.filter)
|
||||||
|
busFilterState = BooleanPlayerInputWidget(this, tile.filter::isWhitelist)
|
||||||
|
} else {
|
||||||
|
busFilterSlots = addFilterSlots(StorageBusBlockEntity.MAX_FILTERS)
|
||||||
|
busFilterState = BooleanPlayerInputWidget(this).asClient()
|
||||||
|
}
|
||||||
|
|
||||||
|
addInventorySlots()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getWorkingSlotStart() = 0
|
||||||
|
override fun getWorkingSlotEnd() = 1
|
||||||
|
}
|
@ -6,6 +6,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
|||||||
import ru.dbotthepony.mc.otm.menu.data.BooleanDataContainer
|
import ru.dbotthepony.mc.otm.menu.data.BooleanDataContainer
|
||||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
|
import kotlin.reflect.KMutableProperty0
|
||||||
|
|
||||||
class BooleanPlayerInputPacket(val id: Int, val value: Boolean) {
|
class BooleanPlayerInputPacket(val id: Int, val value: Boolean) {
|
||||||
fun play(context: Supplier<NetworkEvent.Context>) {
|
fun play(context: Supplier<NetworkEvent.Context>) {
|
||||||
@ -35,6 +36,11 @@ class BooleanPlayerInputWidget(menu: MatteryMenu) : AbstractWidget(menu) {
|
|||||||
addDataSlots(container)
|
addDataSlots(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(menu: MatteryMenu, state: KMutableProperty0<Boolean>) : this(menu) {
|
||||||
|
withClicker { state.set(it) }
|
||||||
|
withSupplier { state.get() }
|
||||||
|
}
|
||||||
|
|
||||||
var supplier: (() -> Boolean)? = null
|
var supplier: (() -> Boolean)? = null
|
||||||
var clicker: ((Boolean) -> Unit)? = null
|
var clicker: ((Boolean) -> Unit)? = null
|
||||||
var value by container::value
|
var value by container::value
|
||||||
|
@ -31,11 +31,14 @@ object MMenus {
|
|||||||
val PLATE_PRESS: MenuType<*> by registry.register(MNames.PLATE_PRESS) { MenuType(::PlatePressMenu) }
|
val PLATE_PRESS: MenuType<*> by registry.register(MNames.PLATE_PRESS) { MenuType(::PlatePressMenu) }
|
||||||
val MATTER_RECYCLER: MenuType<*> by registry.register(MNames.MATTER_RECYCLER) { MenuType(::MatterRecyclerMenu) }
|
val MATTER_RECYCLER: MenuType<*> by registry.register(MNames.MATTER_RECYCLER) { MenuType(::MatterRecyclerMenu) }
|
||||||
|
|
||||||
|
val STORAGE_BUS: MenuType<*> by registry.register(MNames.STORAGE_BUS) { MenuType(::StorageBusMenu) }
|
||||||
|
|
||||||
internal fun register() {
|
internal fun register() {
|
||||||
registry.register(FMLJavaModLoadingContext.get().modEventBus)
|
registry.register(FMLJavaModLoadingContext.get().modEventBus)
|
||||||
FMLJavaModLoadingContext.get().modEventBus.addListener(this::registerClient)
|
FMLJavaModLoadingContext.get().modEventBus.addListener(this::registerClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
private fun registerClient(event: FMLClientSetupEvent) {
|
private fun registerClient(event: FMLClientSetupEvent) {
|
||||||
event.enqueueWork {
|
event.enqueueWork {
|
||||||
MenuScreens.register(ANDROID_STATION as MenuType<AndroidStationMenu>, ::AndroidStationScreen)
|
MenuScreens.register(ANDROID_STATION as MenuType<AndroidStationMenu>, ::AndroidStationScreen)
|
||||||
@ -55,6 +58,7 @@ object MMenus {
|
|||||||
MenuScreens.register(CHEMICAL_GENERATOR as MenuType<ChemicalGeneratorMenu>, ::ChemicalGeneratorScreen)
|
MenuScreens.register(CHEMICAL_GENERATOR as MenuType<ChemicalGeneratorMenu>, ::ChemicalGeneratorScreen)
|
||||||
MenuScreens.register(PLATE_PRESS as MenuType<PlatePressMenu>, ::PlatePressScreen)
|
MenuScreens.register(PLATE_PRESS as MenuType<PlatePressMenu>, ::PlatePressScreen)
|
||||||
MenuScreens.register(MATTER_RECYCLER as MenuType<MatterRecyclerMenu>, ::MatterRecyclerScreen)
|
MenuScreens.register(MATTER_RECYCLER as MenuType<MatterRecyclerMenu>, ::MatterRecyclerScreen)
|
||||||
|
MenuScreens.register(STORAGE_BUS as MenuType<StorageBusMenu>, ::StorageBusScreen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user