Compare commits
2 Commits
d743f8f2b2
...
8d1c2854f6
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 8d1c2854f6 | |
Shadowfacts | bae2a32cb0 |
|
@ -14,7 +14,11 @@ import net.shadowfacts.phycon.api.packet.Packet
|
||||||
import net.shadowfacts.phycon.api.util.IPAddress
|
import net.shadowfacts.phycon.api.util.IPAddress
|
||||||
import net.shadowfacts.phycon.init.PhyBlockEntities
|
import net.shadowfacts.phycon.init.PhyBlockEntities
|
||||||
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
import net.shadowfacts.phycon.network.DeviceBlockEntity
|
||||||
|
import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity
|
||||||
|
import net.shadowfacts.phycon.network.component.NetworkStackDispatcher
|
||||||
import net.shadowfacts.phycon.network.component.NetworkStackProvider
|
import net.shadowfacts.phycon.network.component.NetworkStackProvider
|
||||||
|
import net.shadowfacts.phycon.network.component.handleItemStack
|
||||||
|
import net.shadowfacts.phycon.network.component.spawnItemStack
|
||||||
import net.shadowfacts.phycon.network.packet.*
|
import net.shadowfacts.phycon.network.packet.*
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
@ -22,18 +26,24 @@ import kotlin.math.min
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
||||||
NetworkStackProvider {
|
NetworkStackProvider,
|
||||||
|
NetworkStackDispatcher<MinerBlockEntity.PendingInsertion> {
|
||||||
|
|
||||||
private val facing: Direction
|
private val facing: Direction
|
||||||
get() = cachedState[MinerBlock.FACING]
|
get() = cachedState[MinerBlock.FACING]
|
||||||
|
|
||||||
private val invProxy = MinerInvProxy(this)
|
private val invProxy = MinerInvProxy(this)
|
||||||
|
|
||||||
|
override val pendingInsertions = mutableListOf<PendingInsertion>()
|
||||||
|
override val dispatchStackTimeout = TerminalBlockEntity.INSERTION_TIMEOUT
|
||||||
|
|
||||||
override fun handle(packet: Packet) {
|
override fun handle(packet: Packet) {
|
||||||
when (packet) {
|
when (packet) {
|
||||||
is RequestInventoryPacket -> handleRequestInventory(packet)
|
is RequestInventoryPacket -> handleRequestInventory(packet)
|
||||||
is LocateStackPacket -> handleLocateStack(packet)
|
is LocateStackPacket -> handleLocateStack(packet)
|
||||||
is ExtractStackPacket -> handleExtractStack(packet)
|
is ExtractStackPacket -> handleExtractStack(packet)
|
||||||
|
is CapacityPacket -> handleCapacity(packet)
|
||||||
|
is ItemStackPacket -> handleItemStack(packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +60,7 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
||||||
|
|
||||||
private fun handleExtractStack(packet: ExtractStackPacket) {
|
private fun handleExtractStack(packet: ExtractStackPacket) {
|
||||||
// always recalculate immediately before breaking
|
// always recalculate immediately before breaking
|
||||||
val drops = invProxy.getDrops(true)
|
val drops = invProxy.getDrops(recalculate = true)
|
||||||
if (invProxy.getAmount(packet.stack) > 0) {
|
if (invProxy.getAmount(packet.stack) > 0) {
|
||||||
world!!.breakBlock(pos.offset(facing), false)
|
world!!.breakBlock(pos.offset(facing), false)
|
||||||
|
|
||||||
|
@ -77,11 +87,18 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
||||||
// dump any remaining drops into the network
|
// dump any remaining drops into the network
|
||||||
for (droppedStack in drops) {
|
for (droppedStack in drops) {
|
||||||
if (droppedStack.isEmpty) continue
|
if (droppedStack.isEmpty) continue
|
||||||
sendPacket(ItemStackPacket(droppedStack, ipAddress, IPAddress.BROADCAST))
|
dispatchItemStack(droppedStack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun doHandleItemStack(packet: ItemStackPacket): ItemStack {
|
||||||
|
// miner can't receive stacks, so remaining is the entire packet stack
|
||||||
|
return packet.stack
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createPendingInsertion(stack: ItemStack) = PendingInsertion(stack, counter)
|
||||||
|
|
||||||
class MinerInvProxy(val miner: MinerBlockEntity): GroupedItemInvView {
|
class MinerInvProxy(val miner: MinerBlockEntity): GroupedItemInvView {
|
||||||
private var cachedState: BlockState? = null
|
private var cachedState: BlockState? = null
|
||||||
private var cachedDrops: List<ItemStack>? = null
|
private var cachedDrops: List<ItemStack>? = null
|
||||||
|
@ -96,7 +113,7 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
||||||
fun getDrops(recalculate: Boolean = false): List<ItemStack> {
|
fun getDrops(recalculate: Boolean = false): List<ItemStack> {
|
||||||
val targetPos = pos.offset(facing)
|
val targetPos = pos.offset(facing)
|
||||||
val realState = world.getBlockState(targetPos)
|
val realState = world.getBlockState(targetPos)
|
||||||
// todo: does BlockState.equals actually work?
|
// todo: does BlockState.equals actually work or is reference equality fine for BlockStates?
|
||||||
if (cachedDrops == null || realState != cachedState || recalculate) {
|
if (cachedDrops == null || realState != cachedState || recalculate) {
|
||||||
cachedState = realState
|
cachedState = realState
|
||||||
val be = if (realState.block.hasBlockEntity()) world.getBlockEntity(targetPos) else null
|
val be = if (realState.block.hasBlockEntity()) world.getBlockEntity(targetPos) else null
|
||||||
|
@ -124,4 +141,7 @@ class MinerBlockEntity: DeviceBlockEntity(PhyBlockEntities.MINER),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PendingInsertion(stack: ItemStack, timestamp: Long): NetworkStackDispatcher.PendingInsertion<PendingInsertion>(stack, timestamp) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,13 +14,11 @@ interface ItemStackPacketHandler: PacketSink, PacketSource {
|
||||||
fun doHandleItemStack(packet: ItemStackPacket): ItemStack
|
fun doHandleItemStack(packet: ItemStackPacket): ItemStack
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <BE> BE.handleItemStack(packet: ItemStackPacket) where BE: BlockEntity, BE: ItemStackPacketHandler {
|
fun <Self> Self.handleItemStack(packet: ItemStackPacket) where Self: BlockEntity, Self: ItemStackPacketHandler {
|
||||||
// todo: is 5 a good number?
|
// todo: is 5 a good number?
|
||||||
// the max bounce count should always be odd, so the item is spawned in-world at the
|
// the max bounce count should always be odd, so the item is spawned in-world at the
|
||||||
if (packet.bounceCount == 5) {
|
if (packet.bounceCount == 5) {
|
||||||
// todo: calculate entity spawn point by finding non-obstructed location
|
spawnItemStack(packet.stack)
|
||||||
val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack)
|
|
||||||
world!!.spawnEntity(entity)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val remainder = doHandleItemStack(packet)
|
val remainder = doHandleItemStack(packet)
|
||||||
|
@ -28,4 +26,10 @@ fun <BE> BE.handleItemStack(packet: ItemStackPacket) where BE: BlockEntity, BE:
|
||||||
if (!remainder.isEmpty) {
|
if (!remainder.isEmpty) {
|
||||||
sendPacket(ItemStackPacket(remainder, packet.bounceCount + 1, ipAddress, packet.source))
|
sendPacket(ItemStackPacket(remainder, packet.bounceCount + 1, ipAddress, packet.source))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Self> Self.spawnItemStack(stack: ItemStack) where Self: BlockEntity, Self: ItemStackPacketHandler {
|
||||||
|
// todo: calculate entity spawn point by finding non-obstructed location
|
||||||
|
val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), stack)
|
||||||
|
world!!.spawnEntity(entity)
|
||||||
}
|
}
|
|
@ -73,8 +73,8 @@ interface NetworkStackDispatcher<Insertion: NetworkStackDispatcher.PendingInsert
|
||||||
fun <Self, Insertion: NetworkStackDispatcher.PendingInsertion<Insertion>> Self.finishTimedOutPendingInsertions() where Self: BlockEntity, Self: NetworkStackDispatcher<Insertion> {
|
fun <Self, Insertion: NetworkStackDispatcher.PendingInsertion<Insertion>> Self.finishTimedOutPendingInsertions() where Self: BlockEntity, Self: NetworkStackDispatcher<Insertion> {
|
||||||
if (world!!.isClient) return
|
if (world!!.isClient) return
|
||||||
|
|
||||||
for (insertion in pendingInsertions) {
|
pendingInsertions
|
||||||
if (!insertion.isFinishable(this)) continue
|
.filter { it.isFinishable(this) }
|
||||||
finishInsertion(insertion)
|
.forEach(::finishInsertion)
|
||||||
}
|
// todo: if a timed-out insertion can't be finished, we should probably retry after some time (exponential backoff?)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue