Begin conversion to fabric transfer API
This commit is contained in:
parent
4e32bfb510
commit
dbf450e487
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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>()
|
||||||
|
}
|
Loading…
Reference in New Issue