Convert Miner to fabric transfer API
This commit is contained in:
parent
dbf450e487
commit
0ba1033518
|
@ -1,7 +1,10 @@
|
|||
package net.shadowfacts.phycon.block.miner
|
||||
|
||||
import alexiil.mc.lib.attributes.item.GroupedItemInvView
|
||||
import alexiil.mc.lib.attributes.item.filter.ItemFilter
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.base.ExtractionOnlyStorage
|
||||
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext
|
||||
import net.fabricmc.fabric.api.transfer.v1.transaction.base.SnapshotParticipant
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.item.ItemStack
|
||||
|
@ -36,7 +39,7 @@ class MinerBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(Phy
|
|||
private val facing: Direction
|
||||
get() = cachedState[MinerBlock.FACING]
|
||||
|
||||
private val invProxy = MinerInvProxy(this)
|
||||
private val invProxy = MinerStorageProxy(this)
|
||||
|
||||
override val pendingInsertions = mutableListOf<PendingInsertion>()
|
||||
override val dispatchStackTimeout = AbstractTerminalBlockEntity.INSERTION_TIMEOUT
|
||||
|
@ -60,16 +63,16 @@ class MinerBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(Phy
|
|||
if (minerMode != MinerMode.ON_DEMAND || packet.kind != RequestInventoryPacket.Kind.GROUPED) {
|
||||
return
|
||||
}
|
||||
sendPacket(ReadGroupedInventoryPacket(invProxy, ipAddress, packet.source))
|
||||
sendPacket(ReadItemStoragePacket(invProxy, ipAddress, packet.source))
|
||||
}
|
||||
|
||||
private fun handleLocateStack(packet: LocateStackPacket) {
|
||||
if (minerMode != MinerMode.ON_DEMAND) {
|
||||
return
|
||||
}
|
||||
val amount = invProxy.getAmount(packet.stack)
|
||||
val amount = invProxy.simulateExtract(ItemVariant.of(packet.stack), Long.MAX_VALUE, null)
|
||||
if (amount > 0) {
|
||||
sendPacket(StackLocationPacket(packet.stack, amount, this, ipAddress, packet.source))
|
||||
sendPacket(StackLocationPacket(packet.stack, amount.toInt(), this, ipAddress, packet.source))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +83,8 @@ class MinerBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(Phy
|
|||
|
||||
// always recalculate immediately before breaking
|
||||
val drops = invProxy.getDrops(recalculate = true)
|
||||
if (invProxy.getAmount(packet.stack) > 0) {
|
||||
val amount = invProxy.simulateExtract(ItemVariant.of(packet.stack), packet.amount.toLong(), null)
|
||||
if (amount > 0) {
|
||||
world!!.breakBlock(pos.offset(facing), false)
|
||||
|
||||
// send the requested amount back to the requester
|
||||
|
@ -184,13 +188,15 @@ class MinerBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(Phy
|
|||
val friendlyName = TranslatableText("gui.phycon.miner_mode.${name.lowercase()}")
|
||||
}
|
||||
|
||||
class MinerInvProxy(val miner: MinerBlockEntity) : GroupedItemInvView {
|
||||
class MinerStorageProxy(val miner: MinerBlockEntity) :
|
||||
SnapshotParticipant<Pair<BlockState, List<ItemStack>>?>(),
|
||||
ExtractionOnlyStorage<ItemVariant>
|
||||
{
|
||||
companion object {
|
||||
val TOOL = ItemStack(Items.DIAMOND_PICKAXE)
|
||||
}
|
||||
|
||||
private var cachedState: BlockState? = null
|
||||
private var cachedDrops: List<ItemStack>? = null
|
||||
private var cache: Pair<BlockState, List<ItemStack>>? = null
|
||||
|
||||
private val world: World
|
||||
get() = miner.world!!
|
||||
|
@ -202,35 +208,73 @@ class MinerBlockEntity(pos: BlockPos, state: BlockState) : DeviceBlockEntity(Phy
|
|||
fun getDrops(recalculate: Boolean = false): List<ItemStack> {
|
||||
val targetPos = pos.offset(facing)
|
||||
val realState = world.getBlockState(targetPos)
|
||||
val cache = this.cache
|
||||
// todo: does BlockState.equals actually work or is reference equality fine for BlockStates?
|
||||
if (cachedDrops == null || realState != cachedState || recalculate) {
|
||||
cachedState = realState
|
||||
|
||||
if (cache == null || realState != cache.first || recalculate) {
|
||||
val be = if (realState.hasBlockEntity()) world.getBlockEntity(targetPos) else null
|
||||
cachedDrops = Block.getDroppedStacks(realState, world as ServerWorld, targetPos, be, null, TOOL)
|
||||
val drops = Block.getDroppedStacks(realState, world as ServerWorld, targetPos, be, null, TOOL)
|
||||
this.cache = Pair(realState, drops)
|
||||
return drops
|
||||
}
|
||||
return cachedDrops!!
|
||||
return cache.second
|
||||
}
|
||||
|
||||
override fun getStoredStacks(): Set<ItemStack> {
|
||||
if (miner.minerMode != MinerMode.ON_DEMAND) {
|
||||
return setOf()
|
||||
override fun createSnapshot(): Pair<BlockState, List<ItemStack>>? {
|
||||
return cache
|
||||
}
|
||||
|
||||
override fun readSnapshot(snapshot: Pair<BlockState, List<ItemStack>>?) {
|
||||
cache = snapshot
|
||||
}
|
||||
|
||||
override fun extract(resource: ItemVariant, maxAmount: Long, transaction: TransactionContext): Long {
|
||||
val drops = getDrops()
|
||||
val (matched, unmatched) = drops.partition { resource.matches(it) }
|
||||
if (matched.isEmpty()) {
|
||||
return 0
|
||||
}
|
||||
return getDrops().toSet()
|
||||
}
|
||||
|
||||
override fun getTotalCapacity(): Int {
|
||||
return Int.MAX_VALUE
|
||||
}
|
||||
|
||||
override fun getStatistics(filter: ItemFilter): GroupedItemInvView.ItemInvStatistic {
|
||||
var totalCount = 0
|
||||
for (s in storedStacks) {
|
||||
if (filter.matches(s)) {
|
||||
totalCount += s.count
|
||||
val matchedCount = matched.sumOf { it.count }.toLong()
|
||||
val extracted = min(maxAmount, matchedCount)
|
||||
transaction.addCloseCallback { context, result ->
|
||||
if (result.wasCommitted()) {
|
||||
world.breakBlock(pos.offset(facing), false)
|
||||
// send any un-extracted drops to the network
|
||||
if (matchedCount > extracted) {
|
||||
miner.dispatchItemStack(resource.toStack().copyWithCount((matchedCount - extracted).toInt()))
|
||||
}
|
||||
for (stack in unmatched) {
|
||||
miner.dispatchItemStack(stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
return GroupedItemInvView.ItemInvStatistic(filter, totalCount, 0, Int.MAX_VALUE)
|
||||
return extracted
|
||||
}
|
||||
|
||||
override fun iterator(transaction: TransactionContext): Iterator<StorageView<ItemVariant>> {
|
||||
return getDrops().map { View(it, this) }.iterator()
|
||||
}
|
||||
|
||||
class View(val stack: ItemStack, val proxy: MinerStorageProxy) : StorageView<ItemVariant> {
|
||||
override fun extract(resource: ItemVariant, maxAmount: Long, transaction: TransactionContext): Long {
|
||||
return proxy.extract(resource, maxAmount, transaction)
|
||||
}
|
||||
|
||||
override fun isResourceBlank(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getResource(): ItemVariant {
|
||||
return ItemVariant.of(stack)
|
||||
}
|
||||
|
||||
override fun getAmount(): Long {
|
||||
return stack.count.toLong()
|
||||
}
|
||||
|
||||
override fun getCapacity(): Long {
|
||||
// TODO: ehh? we have stuff stored, but nothing can be inserted, so...
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue