Begin conversion to fabric transfer API

This commit is contained in:
Shadowfacts 2024-07-14 14:28:09 -07:00
parent 4e32bfb510
commit dbf450e487
10 changed files with 140 additions and 159 deletions

View File

@ -78,23 +78,4 @@ class ExtractorBlock : FaceDeviceBlock<ExtractorBlockEntity>(
override fun createBlockEntity(pos: BlockPos, state: BlockState) = ExtractorBlockEntity(pos, state) override fun createBlockEntity(pos: BlockPos, state: BlockState) = ExtractorBlockEntity(pos, state)
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) {
if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory()
}
}
override fun neighborUpdate(
state: BlockState,
world: World,
pos: BlockPos,
neighbor: Block,
neighborPos: BlockPos,
bl: Boolean
) {
if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory()
}
}
} }

View File

@ -1,13 +1,14 @@
package net.shadowfacts.phycon.block.extractor package net.shadowfacts.phycon.block.extractor
import alexiil.mc.lib.attributes.SearchOptions import net.fabricmc.fabric.api.lookup.v1.block.BlockApiCache
import alexiil.mc.lib.attributes.Simulation import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage
import alexiil.mc.lib.attributes.item.FixedItemInv import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant
import alexiil.mc.lib.attributes.item.ItemAttributes import net.fabricmc.fabric.api.transfer.v1.storage.Storage
import alexiil.mc.lib.attributes.item.filter.ExactItemStackFilter import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
@ -23,6 +24,8 @@ import net.shadowfacts.phycon.packet.ItemStackPacket
import net.shadowfacts.phycon.packet.RemoteActivationPacket import net.shadowfacts.phycon.packet.RemoteActivationPacket
import net.shadowfacts.phycon.util.ActivationMode import net.shadowfacts.phycon.util.ActivationMode
import net.shadowfacts.phycon.util.ClientConfigurableDevice import net.shadowfacts.phycon.util.ClientConfigurableDevice
import net.shadowfacts.phycon.util.copyWithCount
import kotlin.math.min
import kotlin.properties.Delegates import kotlin.properties.Delegates
/** /**
@ -41,20 +44,19 @@ class ExtractorBlockEntity(pos: BlockPos, state: BlockState) :
private val facing: Direction private val facing: Direction
get() = cachedState[FaceDeviceBlock.FACING] get() = cachedState[FaceDeviceBlock.FACING]
private var inventory: FixedItemInv? = null private var inventory: Pair<BlockState, BlockApiCache<Storage<ItemVariant>, Direction>>? = null
override val pendingInsertions = mutableListOf<PendingInsertion>() override val pendingInsertions = mutableListOf<PendingInsertion>()
override val dispatchStackTimeout = 1L override val dispatchStackTimeout = 1L
override val controller = ActivationController(SLEEP_TIME, this) override val controller = ActivationController(SLEEP_TIME, this)
fun updateInventory() { private fun getInventory(): Storage<ItemVariant>? {
val offsetPos = pos.offset(facing) if (inventory == null) {
val option = SearchOptions.inDirection(facing) val offsetPos = pos.offset(facing)
inventory = ItemAttributes.FIXED_INV.getFirstOrNull(world, offsetPos, option) val cachedFacedBlock = world!!.getBlockState(offsetPos)
} val inventory = BlockApiCache.create(ItemStorage.SIDED, world!! as ServerWorld, offsetPos)
this.inventory = Pair(cachedFacedBlock, inventory)
private fun getInventory(): FixedItemInv? { }
if (inventory == null) updateInventory() return inventory!!.second.find(inventory!!.first, facing.opposite)
return inventory
} }
override fun handle(packet: Packet) { override fun handle(packet: Packet) {
@ -76,16 +78,15 @@ class ExtractorBlockEntity(pos: BlockPos, state: BlockState) :
val inventory = getInventory() ?: return insertion.stack val inventory = getInventory() ?: return insertion.stack
// if the inventory has changed, the old slot index is meaningless // if the inventory has changed, the old slot index is meaningless
if (inventory !== insertion.inventory) return insertion.stack if (inventory !== insertion.inventory) return insertion.stack
val extracted = inventory.extractStack( val transaction = Transaction.openOuter()
insertion.inventorySlot, val extractedAmount = inventory.extract(ItemVariant.of(insertion.stack), insertion.stack.count.toLong(), transaction).toInt()
ExactItemStackFilter(insertion.stack), transaction.commit()
ItemStack.EMPTY, if (extractedAmount == 0) {
insertion.totalCapacity, return insertion.stack
Simulation.ACTION } else if (extractedAmount != insertion.stack.count) {
) // if we extracted less than expected, make sure super.finishInsertion doesn't send more than we actually have
if (extracted.isEmpty) return insertion.stack insertion.stack = insertion.stack.copyWithCount(extractedAmount)
// if we extracted less than expected, make sure super.finishInsertion doesn't send more than we actually have }
insertion.stack = extracted
return super.finishInsertion(insertion) return super.finishInsertion(insertion)
} }
@ -101,20 +102,15 @@ class ExtractorBlockEntity(pos: BlockPos, state: BlockState) :
override fun activate(): Boolean { override fun activate(): Boolean {
val inventory = getInventory() ?: return false val inventory = getInventory() ?: return false
for (slot in 0 until inventory.slotCount) { for (view in inventory.iterator(null)) {
val slotStack = inventory.getInvStack(slot) if (view.amount <= 0) continue
if (slotStack.isEmpty) continue val transaction = Transaction.openOuter()
val extractable = inventory.extractStack( var extractableAmount = inventory.simulateExtract(view.resource, view.amount, transaction).toInt()
slot, transaction.close()
ExactItemStackFilter(slotStack), if (extractableAmount <= 0) continue
ItemStack.EMPTY, extractableAmount = min(extractableAmount, view.resource.item.maxCount)
slotStack.count, dispatchItemStack(view.resource.toStack(extractableAmount)) { insertion ->
Simulation.SIMULATE
)
if (extractable.isEmpty) continue
dispatchItemStack(extractable) { insertion ->
insertion.inventory = inventory insertion.inventory = inventory
insertion.inventorySlot = slot
} }
return true return true
} }
@ -141,7 +137,7 @@ class ExtractorBlockEntity(pos: BlockPos, state: BlockState) :
class PendingInsertion(stack: ItemStack, timestamp: Long) : class PendingInsertion(stack: ItemStack, timestamp: Long) :
NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) { NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) {
lateinit var inventory: FixedItemInv lateinit var inventory: Storage<ItemVariant>
var inventorySlot by Delegates.notNull<Int>() var inventorySlot by Delegates.notNull<Int>()
} }
} }

View File

@ -87,25 +87,6 @@ class InserterBlock : FaceDeviceBlock<InserterBlockEntity>(
override fun createBlockEntity(pos: BlockPos, state: BlockState) = InserterBlockEntity(pos, state) override fun createBlockEntity(pos: BlockPos, state: BlockState) = InserterBlockEntity(pos, state)
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, entity: LivingEntity?, stack: ItemStack) {
if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory()
}
}
override fun neighborUpdate(
state: BlockState,
world: World,
pos: BlockPos,
neighborBlock: Block,
neighborPos: BlockPos,
bl: Boolean
) {
if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory()
}
}
override fun onUse( override fun onUse(
state: BlockState, state: BlockState,
world: World, world: World,

View File

@ -1,12 +1,14 @@
package net.shadowfacts.phycon.block.inserter package net.shadowfacts.phycon.block.inserter
import alexiil.mc.lib.attributes.SearchOptions import net.fabricmc.fabric.api.lookup.v1.block.BlockApiCache
import alexiil.mc.lib.attributes.Simulation import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage
import alexiil.mc.lib.attributes.item.ItemAttributes import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant
import alexiil.mc.lib.attributes.item.ItemInsertable import net.fabricmc.fabric.api.transfer.v1.storage.Storage
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
@ -18,10 +20,7 @@ import net.shadowfacts.phycon.component.NetworkStackProvider
import net.shadowfacts.phycon.component.handleItemStack import net.shadowfacts.phycon.component.handleItemStack
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.ActivationMode import net.shadowfacts.phycon.util.*
import net.shadowfacts.phycon.util.ClientConfigurableDevice
import net.shadowfacts.phycon.util.GhostInv
import net.shadowfacts.phycon.util.equalsIgnoringAmount
import kotlin.math.min import kotlin.math.min
/** /**
@ -41,7 +40,7 @@ class InserterBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(
private val facing: Direction private val facing: Direction
get() = cachedState[FaceDeviceBlock.FACING] get() = cachedState[FaceDeviceBlock.FACING]
private var inventory: ItemInsertable? = null private var inventory: Pair<BlockState, BlockApiCache<Storage<ItemVariant>, Direction>>? = null
private var currentRequest: PendingExtractRequest? = null private var currentRequest: PendingExtractRequest? = null
var stackToExtract: ItemStack = ItemStack.EMPTY var stackToExtract: ItemStack = ItemStack.EMPTY
override var ghostSlotStack: ItemStack override var ghostSlotStack: ItemStack
@ -52,15 +51,14 @@ class InserterBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(
var amountToExtract = 1 var amountToExtract = 1
override val controller = ActivationController(SLEEP_TIME, this) override val controller = ActivationController(SLEEP_TIME, this)
fun updateInventory() { private fun getInventory(): Storage<ItemVariant>? {
val offsetPos = pos.offset(facing) if (inventory == null) {
val option = SearchOptions.inDirection(facing) val offsetPos = pos.offset(facing)
inventory = ItemAttributes.INSERTABLE.getFirstOrNull(world, offsetPos, option) val cachedFacedBlock = world!!.getBlockState(offsetPos)
} val inventory = BlockApiCache.create(ItemStorage.SIDED, world!! as ServerWorld, offsetPos)
this.inventory = Pair(cachedFacedBlock, inventory)
private fun getInventory(): ItemInsertable? { }
if (inventory == null) updateInventory() return inventory!!.second.find(inventory!!.first, facing.opposite)
return inventory
} }
override fun handle(packet: Packet) { override fun handle(packet: Packet) {
@ -73,11 +71,20 @@ class InserterBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack { override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
val inventory = getInventory() val inventory = getInventory()
return if (inventory != null) { if (inventory != null) {
inventory.attemptInsertion(packet.stack, Simulation.ACTION) val transaction = Transaction.openOuter()
val inserted = inventory.insert(ItemVariant.of(packet.stack), packet.stack.count.toLong(), transaction).toInt()
transaction.commit()
return if (inserted == 0) {
packet.stack
} else if (inserted == packet.stack.count) {
ItemStack.EMPTY
} else {
packet.stack.copyWithCount(packet.stack.count - inserted)
}
} else { } else {
// no inventory, entire stack remains // no inventory, entire stack remains
packet.stack return packet.stack
} }
} }

View File

@ -39,23 +39,4 @@ class InterfaceBlock : FaceDeviceBlock<InterfaceBlockEntity>(
override fun createBlockEntity(pos: BlockPos, state: BlockState) = InterfaceBlockEntity(pos, state) override fun createBlockEntity(pos: BlockPos, state: BlockState) = InterfaceBlockEntity(pos, state)
override fun onPlaced(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {
if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory()
}
}
override fun neighborUpdate(
state: BlockState,
world: World,
pos: BlockPos,
neighborBlock: Block,
neighborPos: BlockPos,
boolean_1: Boolean
) {
if (!world.isClient) {
getBlockEntity(world, pos)!!.updateInventory()
}
}
} }

View File

@ -1,12 +1,14 @@
package net.shadowfacts.phycon.block.netinterface package net.shadowfacts.phycon.block.netinterface
import alexiil.mc.lib.attributes.SearchOptions import net.fabricmc.fabric.api.lookup.v1.block.BlockApiCache
import alexiil.mc.lib.attributes.Simulation import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage
import alexiil.mc.lib.attributes.item.GroupedItemInv import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant
import alexiil.mc.lib.attributes.item.ItemAttributes import net.fabricmc.fabric.api.transfer.v1.storage.Storage
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import net.minecraft.server.world.ServerWorld
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.packet.Packet
@ -19,7 +21,7 @@ import net.shadowfacts.phycon.component.NetworkStackReceiver
import net.shadowfacts.phycon.component.handleItemStack import net.shadowfacts.phycon.component.handleItemStack
import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.ClientConfigurableDevice import net.shadowfacts.phycon.util.ClientConfigurableDevice
import java.lang.ref.WeakReference import net.shadowfacts.phycon.util.copyWithCount
import kotlin.math.min import kotlin.math.min
/** /**
@ -39,21 +41,17 @@ class InterfaceBlockEntity(pos: BlockPos, state: BlockState) :
override var receiverPriority = 0 override var receiverPriority = 0
var syncPriorities = true var syncPriorities = true
private var inventory: WeakReference<GroupedItemInv>? = null private var cachedFacedBlock: BlockState? = null
private var inventoryCache: BlockApiCache<Storage<ItemVariant>, Direction>? = null
fun updateInventory() { private fun getInventory(): Storage<ItemVariant>? {
val offsetPos = pos.offset(facing) if (cachedFacedBlock == null) {
val option = SearchOptions.inDirection(facing) cachedFacedBlock = world!!.getBlockState(pos.offset(facing))
inventory = ItemAttributes.GROUPED_INV.getFirstOrNull(world, offsetPos, option).let {
WeakReference(it)
} }
} if (inventoryCache == null) {
inventoryCache = BlockApiCache.create(ItemStorage.SIDED, world!! as ServerWorld, pos.offset(facing))
private fun getInventory(): GroupedItemInv? { }
// if we don't have an inventory, try to get one return inventoryCache!!.find(cachedFacedBlock!!, facing.opposite)
// this happens when readAll is called before a neighbor state changes, such as immediately after world load
if (inventory?.get() == null) updateInventory()
return inventory?.get()
} }
override fun handle(packet: Packet) { override fun handle(packet: Packet) {
@ -71,46 +69,50 @@ class InterfaceBlockEntity(pos: BlockPos, state: BlockState) :
return return
} }
getInventory()?.also { inv -> getInventory()?.also { inv ->
sendPacket(ReadGroupedInventoryPacket(inv, ipAddress, packet.source)) sendPacket(ReadItemStoragePacket(inv, ipAddress, packet.source))
} }
} }
private fun handleLocateStack(packet: LocateStackPacket) { private fun handleLocateStack(packet: LocateStackPacket) {
getInventory()?.also { inv -> getInventory()?.also { inv ->
val amount = inv.getAmount(packet.stack) val transaction = Transaction.openOuter()
sendPacket(StackLocationPacket(packet.stack, amount, this, ipAddress, packet.source)) val amount = inv.simulateExtract(ItemVariant.of(packet.stack), Long.MAX_VALUE, transaction);
transaction.close()
sendPacket(StackLocationPacket(packet.stack, amount.toInt(), this, ipAddress, packet.source))
} }
} }
private fun handleExtractStack(packet: ExtractStackPacket) { private fun handleExtractStack(packet: ExtractStackPacket) {
getInventory()?.also { inv -> getInventory()?.also { inv ->
var amount = packet.amount var remaining = packet.amount
while (amount > 0) { while (remaining > 0) {
val extracted = inv.extract(packet.stack, min(amount, packet.stack.maxCount)) val toExtract = min(remaining, packet.stack.maxCount)
if (extracted.isEmpty) { val transaction = Transaction.openOuter()
break val extracted = inv.extract(ItemVariant.of(packet.stack), toExtract.toLong(), transaction)
} else { transaction.commit()
amount -= extracted.count remaining -= extracted.toInt()
sendPacket(ItemStackPacket(extracted, ipAddress, packet.source)) sendPacket(ItemStackPacket(packet.stack.copyWithCount(extracted.toInt()), ipAddress, packet.source))
}
} }
} }
} }
private fun handleCheckCapacity(packet: CheckCapacityPacket) { private fun handleCheckCapacity(packet: CheckCapacityPacket) {
getInventory()?.also { inv -> getInventory()?.also { inv ->
val remaining = inv.attemptInsertion(packet.stack, Simulation.SIMULATE) val transaction = Transaction.openOuter()
val couldAccept = packet.stack.count - remaining.count val inserted = inv.simulateInsert(ItemVariant.of(packet.stack), packet.stack.count.toLong(), transaction)
sendPacket(CapacityPacket(packet.stack, couldAccept, this, ipAddress, packet.source)) transaction.close()
sendPacket(CapacityPacket(packet.stack, inserted.toInt(), this, ipAddress, packet.source))
} }
} }
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack { override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
val inventory = getInventory() val inventory = getInventory()
if (inventory != null) { if (inventory != null) {
val remaining = inventory.insert(packet.stack) val transaction = Transaction.openOuter()
// whatever could not be inserted will be sent back to the packet's source val inserted = inventory.insert(ItemVariant.of(packet.stack), packet.stack.count.toLong(), transaction)
return remaining transaction.commit()
val remaining = packet.stack.count - inserted.toInt()
return packet.stack.copyWithCount(remaining)
} else { } else {
return packet.stack return packet.stack
} }

View File

@ -2,6 +2,9 @@ package net.shadowfacts.phycon.block.terminal
import alexiil.mc.lib.attributes.item.GroupedItemInvView import alexiil.mc.lib.attributes.item.GroupedItemInvView
import alexiil.mc.lib.attributes.item.ItemStackCollections import alexiil.mc.lib.attributes.item.ItemStackCollections
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant
import net.fabricmc.fabric.api.transfer.v1.storage.Storage
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntityType import net.minecraft.block.entity.BlockEntityType
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
@ -18,6 +21,7 @@ import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.block.DeviceBlockEntity import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.component.* import net.shadowfacts.phycon.component.*
import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.Either
import net.shadowfacts.phycon.util.NetworkUtil import net.shadowfacts.phycon.util.NetworkUtil
import net.shadowfacts.phycon.util.equalsIgnoringAmount import net.shadowfacts.phycon.util.equalsIgnoringAmount
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ -43,13 +47,14 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockP
val REQUEST_INVENTORY_TIMEOUT: Long = 1 // ticks val REQUEST_INVENTORY_TIMEOUT: Long = 1 // ticks
} }
protected val inventoryCache = mutableMapOf<IPAddress, GroupedItemInvView>() protected val inventoryCache = mutableMapOf<IPAddress, Either<Storage<ItemVariant>, GroupedItemInvView>>()
val internalBuffer = TerminalBufferInventory(18) val internalBuffer = TerminalBufferInventory(18)
protected val pendingRequests = LinkedList<StackLocateRequest>() protected val pendingRequests = LinkedList<StackLocateRequest>()
override val pendingInsertions = mutableListOf<PendingInsertion>() override val pendingInsertions = mutableListOf<PendingInsertion>()
override val dispatchStackTimeout = INSERTION_TIMEOUT override val dispatchStackTimeout = INSERTION_TIMEOUT
// TODO: need a ItemVariant -> Int/Long map
val cachedNetItems = ItemStackCollections.intMap() val cachedNetItems = ItemStackCollections.intMap()
private var requestInventoryTimestamp: Long? = null private var requestInventoryTimestamp: Long? = null
@ -78,6 +83,7 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockP
override fun handle(packet: Packet) { override fun handle(packet: Packet) {
when (packet) { when (packet) {
is ReadGroupedInventoryPacket -> handleReadInventory(packet) is ReadGroupedInventoryPacket -> handleReadInventory(packet)
is ReadItemStoragePacket -> handleReadItemStorage(packet)
is DeviceRemovedPacket -> handleDeviceRemoved(packet) is DeviceRemovedPacket -> handleDeviceRemoved(packet)
is StackLocationPacket -> handleStackLocation(packet) is StackLocationPacket -> handleStackLocation(packet)
is ItemStackPacket -> handleItemStack(packet) is ItemStackPacket -> handleItemStack(packet)
@ -86,7 +92,12 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockP
} }
private fun handleReadInventory(packet: ReadGroupedInventoryPacket) { private fun handleReadInventory(packet: ReadGroupedInventoryPacket) {
inventoryCache[packet.source] = packet.inventory inventoryCache[packet.source] = Either.Right(packet.inventory)
updateAndSync()
}
private fun handleReadItemStorage(packet: ReadItemStoragePacket) {
inventoryCache[packet.source] = Either.Left(packet.inventory)
updateAndSync() updateAndSync()
} }
@ -136,9 +147,21 @@ abstract class AbstractTerminalBlockEntity(type: BlockEntityType<*>, pos: BlockP
private fun updateNetItems() { private fun updateNetItems() {
cachedNetItems.clear() cachedNetItems.clear()
for (inventory in inventoryCache.values) { for (inventory in inventoryCache.values) {
for (stack in inventory.storedStacks) { when (inventory) {
val amount = inventory.getAmount(stack) is Either.Left -> {
cachedNetItems.mergeInt(stack, amount, IntBinaryOperator { a, b -> a + b }) val transaction = Transaction.openOuter()
for (view in inventory.left.iterator(transaction)) {
val amount = view.amount.toInt()
cachedNetItems.mergeInt(view.resource.toStack(), amount, IntBinaryOperator { a, b -> a + b })
}
transaction.close()
}
is Either.Right -> {
for (stack in inventory.right.storedStacks) {
val amount = inventory.right.getAmount(stack)
cachedNetItems.mergeInt(stack, amount, IntBinaryOperator { a, b -> a + b })
}
}
} }
} }
} }

View File

@ -10,7 +10,6 @@ import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.TranslatableText import net.minecraft.text.TranslatableText
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.packet.RequestInventoryPacket
/** /**
* @author shadowfacts * @author shadowfacts

View File

@ -13,6 +13,7 @@ import kotlin.math.min
/** /**
* @author shadowfacts * @author shadowfacts
*/ */
// TODO: use Transfer API transactions for this
interface NetworkStackDispatcher<Insertion : NetworkStackDispatcher.PendingInsertion<Insertion>> : interface NetworkStackDispatcher<Insertion : NetworkStackDispatcher.PendingInsertion<Insertion>> :
ItemStackPacketHandler { ItemStackPacketHandler {

View File

@ -0,0 +1,10 @@
package net.shadowfacts.phycon.util
/**
* @author shadowfacts
*/
sealed class Either<Left, Right> {
class Left<Left, Right>(val left: Left) : Either<Left, Right>()
class Right<Left, Right>(val right: Right) : Either<Left, Right>()
}