diff --git a/src/main/java/net/shadowfacts/phycon/api/PacketSource.java b/src/main/java/net/shadowfacts/phycon/api/PacketSource.java new file mode 100644 index 0000000..7b6eed1 --- /dev/null +++ b/src/main/java/net/shadowfacts/phycon/api/PacketSource.java @@ -0,0 +1,15 @@ +package net.shadowfacts.phycon.api; + +import net.shadowfacts.phycon.api.packet.Packet; + +/** + * @author shadowfacts + */ +public interface PacketSource { + // todo: better name for this + void sendToSingle(Packet packet); + + void sendToAll(Packet packet); + + void sendToAll(Packet packet, Iterable destinations); +} diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/DeviceBlockEntity.kt b/src/main/kotlin/net/shadowfacts/phycon/network/DeviceBlockEntity.kt index d2d0c56..2e61680 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/network/DeviceBlockEntity.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/network/DeviceBlockEntity.kt @@ -4,18 +4,16 @@ import net.minecraft.block.BlockState import net.minecraft.block.entity.BlockEntity import net.minecraft.block.entity.BlockEntityType import net.minecraft.nbt.CompoundTag -import net.minecraft.util.Tickable import net.shadowfacts.phycon.api.PacketSink +import net.shadowfacts.phycon.api.PacketSource import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.api.util.MACAddress import net.shadowfacts.phycon.network.packet.DeviceRemovedPacket -import java.lang.ref.WeakReference -import java.util.* /** * @author shadowfacts */ -abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), PacketSink { +abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), PacketSink, PacketSource { var macAddress = MACAddress.random() protected set @@ -48,8 +46,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), P destination.handle(packet) } - // todo: better name for this - fun sendToSingle(packet: Packet) { + override fun sendToSingle(packet: Packet) { val destinations = NetworkUtil.findDestinations(world!!, pos) if (destinations.size != 1) { // todo: handle this better @@ -59,11 +56,11 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), P send(packet, destinations.first()) } - fun sendToAll(packet: Packet) { + override fun sendToAll(packet: Packet) { sendToAll(packet, NetworkUtil.findDestinations(world!!, pos)) } - fun sendToAll(packet: Packet, destinations: Iterable) { + override fun sendToAll(packet: Packet, destinations: Iterable) { destinations.forEach { it.handle(packet) } diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/block/netinterface/InterfaceBlockEntity.kt b/src/main/kotlin/net/shadowfacts/phycon/network/block/netinterface/InterfaceBlockEntity.kt index 5a60491..1300771 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/network/block/netinterface/InterfaceBlockEntity.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/network/block/netinterface/InterfaceBlockEntity.kt @@ -4,17 +4,19 @@ import alexiil.mc.lib.attributes.SearchOptions import alexiil.mc.lib.attributes.Simulation import alexiil.mc.lib.attributes.item.GroupedItemInv import alexiil.mc.lib.attributes.item.ItemAttributes -import net.minecraft.entity.ItemEntity +import net.minecraft.item.ItemStack import net.minecraft.util.math.Direction import net.shadowfacts.phycon.api.packet.Packet import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.network.DeviceBlockEntity +import net.shadowfacts.phycon.network.component.ItemStackPacketHandler +import net.shadowfacts.phycon.network.component.handleItemStack import net.shadowfacts.phycon.network.packet.* /** * @author shadowfacts */ -class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE) { +class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE), ItemStackPacketHandler { private val facing: Direction get() = world!!.getBlockState(pos)[InterfaceBlock.FACING] @@ -73,21 +75,14 @@ class InterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.INTERFACE) { } } - private fun handleItemStack(packet: ItemStackPacket) { + override fun doHandleItemStack(packet: ItemStackPacket): ItemStack { val inventory = getInventory() if (inventory != null) { val remaining = inventory.insert(packet.stack) - if (!remaining.isEmpty) { - // todo: should this send whatever was left back to the terminal instead of dropping it? - // todo: calculate entity spawn point by finding non-obstructed location - val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), remaining) - world!!.spawnEntity(entity) - } + // whatever could not be inserted will be sent back to the packet's source + return remaining } else { - // todo: should the stack back to the terminal instead of dropping it? - // todo: calculate entity spawn point by finding non-obstructed location - val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack) - world!!.spawnEntity(entity) + return packet.stack } } diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/block/terminal/TerminalBlockEntity.kt b/src/main/kotlin/net/shadowfacts/phycon/network/block/terminal/TerminalBlockEntity.kt index 8c43d35..4aad945 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/network/block/terminal/TerminalBlockEntity.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/network/block/terminal/TerminalBlockEntity.kt @@ -7,7 +7,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory import net.minecraft.block.BlockState -import net.minecraft.entity.ItemEntity import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerInventory import net.minecraft.inventory.Inventory @@ -25,6 +24,8 @@ import net.shadowfacts.phycon.api.util.MACAddress import net.shadowfacts.phycon.init.PhyBlockEntities import net.shadowfacts.phycon.network.DeviceBlockEntity import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity +import net.shadowfacts.phycon.network.component.ItemStackPacketHandler +import net.shadowfacts.phycon.network.component.handleItemStack import net.shadowfacts.phycon.network.packet.* import java.util.* import kotlin.math.min @@ -32,7 +33,7 @@ import kotlin.math.min /** * @author shadowfacts */ -class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), InventoryChangedListener, BlockEntityClientSerializable, Tickable { +class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), InventoryChangedListener, BlockEntityClientSerializable, Tickable, ItemStackPacketHandler { companion object { val LOCATE_REQUEST_TIMEOUT = 40 // ticks @@ -89,18 +90,15 @@ class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL), Invento } } - private fun handleItemStack(packet: ItemStackPacket) { + override fun doHandleItemStack(packet: ItemStackPacket): ItemStack { val remaining = internalBuffer.insertFromNetwork(packet.stack) - if (!remaining.isEmpty) { - // todo: calculate entity spawn point by finding non-obstructed location - val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), remaining) - world!!.spawnEntity(entity) - } // this happens outside the normal update loop because by receiving the item stack packet // we "know" how much the count in the source inventory has changed updateNetItems() sync() + + return remaining } private fun handleCapacity(packet: CapacityPacket) { diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/component/ItemStackPacketHandler.kt b/src/main/kotlin/net/shadowfacts/phycon/network/component/ItemStackPacketHandler.kt new file mode 100644 index 0000000..7ea9fe9 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/component/ItemStackPacketHandler.kt @@ -0,0 +1,31 @@ +package net.shadowfacts.phycon.network.component + +import net.minecraft.block.entity.BlockEntity +import net.minecraft.entity.ItemEntity +import net.minecraft.item.ItemStack +import net.shadowfacts.phycon.api.PacketSink +import net.shadowfacts.phycon.api.PacketSource +import net.shadowfacts.phycon.network.packet.ItemStackPacket + +/** + * @author shadowfacts + */ +interface ItemStackPacketHandler: PacketSink, PacketSource { + fun doHandleItemStack(packet: ItemStackPacket): ItemStack +} + +fun BE.handleItemStack(packet: ItemStackPacket) where BE: BlockEntity, BE: ItemStackPacketHandler { + // todo: is 5 a good number? + // the max bounce count should always be odd, so the item is spawned in-world at the + if (packet.bounceCount == 5) { + // todo: calculate entity spawn point by finding non-obstructed location + val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack) + world!!.spawnEntity(entity) + return + } + val remainder = doHandleItemStack(packet) + // if there are any items remaining, send them back to the source with incremented bounce count + if (!remainder.isEmpty) { + sendToSingle(ItemStackPacket(remainder, packet.bounceCount + 1, macAddress, packet.source)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/packet/ItemStackPacket.kt b/src/main/kotlin/net/shadowfacts/phycon/network/packet/ItemStackPacket.kt index bc41a70..a65ca2c 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/network/packet/ItemStackPacket.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/network/packet/ItemStackPacket.kt @@ -6,5 +6,6 @@ import net.shadowfacts.phycon.api.util.MACAddress /** * @author shadowfacts */ -class ItemStackPacket(val stack: ItemStack, source: MACAddress, destination: MACAddress): BasePacket(source, destination) { +class ItemStackPacket(val stack: ItemStack, val bounceCount: Int, source: MACAddress, destination: MACAddress): BasePacket(source, destination) { + constructor(stack: ItemStack, source: MACAddress, destination: MACAddress): this(stack, 0, source, destination) }