diff --git a/src/main/java/net/shadowfacts/phycon/api/NetworkCable.java b/src/main/java/net/shadowfacts/phycon/api/NetworkCable.java new file mode 100644 index 0000000..b90666f --- /dev/null +++ b/src/main/java/net/shadowfacts/phycon/api/NetworkCable.java @@ -0,0 +1,7 @@ +package net.shadowfacts.phycon.api; + +/** + * @author shadowfacts + */ +public interface NetworkCable { +} diff --git a/src/main/java/net/shadowfacts/phycon/api/NetworkInterface.java b/src/main/java/net/shadowfacts/phycon/api/NetworkInterface.java new file mode 100644 index 0000000..a5c0529 --- /dev/null +++ b/src/main/java/net/shadowfacts/phycon/api/NetworkInterface.java @@ -0,0 +1,14 @@ +package net.shadowfacts.phycon.api; + +import net.minecraft.item.ItemStack; + +import java.util.Map; + +/** + * @author shadowfacts + */ +public interface NetworkInterface extends PacketSink { + + Map readAll(); + +} diff --git a/src/main/java/net/shadowfacts/phycon/api/PacketSink.java b/src/main/java/net/shadowfacts/phycon/api/PacketSink.java new file mode 100644 index 0000000..2aacc3c --- /dev/null +++ b/src/main/java/net/shadowfacts/phycon/api/PacketSink.java @@ -0,0 +1,13 @@ +package net.shadowfacts.phycon.api; + +import net.shadowfacts.phycon.api.packet.Packet; +import org.jetbrains.annotations.NotNull; + +/** + * @author shadowfacts + */ +public interface PacketSink { + + void handle(@NotNull Packet packet); + +} diff --git a/src/main/java/net/shadowfacts/phycon/api/PhyAttributes.java b/src/main/java/net/shadowfacts/phycon/api/PhyAttributes.java new file mode 100644 index 0000000..5cd009a --- /dev/null +++ b/src/main/java/net/shadowfacts/phycon/api/PhyAttributes.java @@ -0,0 +1,14 @@ +package net.shadowfacts.phycon.api; + +import alexiil.mc.lib.attributes.Attribute; +import alexiil.mc.lib.attributes.Attributes; + +/** + * @author shadowfacts + */ +public class PhyAttributes { + + public static final Attribute PACKET_SINK = Attributes.create(PacketSink.class); + public static final Attribute NETWORK_INTERFACE = Attributes.create(NetworkInterface.class); + +} diff --git a/src/main/java/net/shadowfacts/phycon/api/packet/Packet.java b/src/main/java/net/shadowfacts/phycon/api/packet/Packet.java new file mode 100644 index 0000000..fb89376 --- /dev/null +++ b/src/main/java/net/shadowfacts/phycon/api/packet/Packet.java @@ -0,0 +1,17 @@ +package net.shadowfacts.phycon.api.packet; + +import net.shadowfacts.phycon.api.util.MACAddress; +import org.jetbrains.annotations.NotNull; + +/** + * @author shadowfacts + */ +public interface Packet { + + @NotNull + MACAddress getSource(); + + @NotNull + MACAddress getDestination(); + +} diff --git a/src/main/java/net/shadowfacts/phycon/api/util/MACAddress.java b/src/main/java/net/shadowfacts/phycon/api/util/MACAddress.java new file mode 100644 index 0000000..3a3cec0 --- /dev/null +++ b/src/main/java/net/shadowfacts/phycon/api/util/MACAddress.java @@ -0,0 +1,84 @@ +package net.shadowfacts.phycon.api.util; + +import org.jetbrains.annotations.NotNull; + +import java.util.Random; + +/** + * @author shadowfacts + */ +public final class MACAddress { + + public enum Type { + BROADCAST, UNICAST, MULTICAST; + } + + public static final MACAddress BROADCAST = new MACAddress(0xffffffffffffL); + + public static MACAddress random(Random random) { + long value = random.nextLong() & 0xfeffffffffffL; + return new MACAddress(value); + } + + private static final Random macAddressRandom = new Random(); + public static MACAddress random() { + return random(macAddressRandom); + } + + public final long address; + + public MACAddress(long address) { + if (address != (address & 0xffffffffffffL)) { + throw new RuntimeException("Invalid MAC address, must be 48 bits."); + } + this.address = address; + } + + @NotNull + public MACAddress toUnicast() { + return new MACAddress(address & 0xfeffffffffffL); + } + + @NotNull + public MACAddress toMulticast() { + return new MACAddress(address | 0x010000000000L); + } + + @NotNull + public Type getType() { + if (this == BROADCAST) { + return Type.BROADCAST; + } else if (((address >> 46) & 1) == 1) { + return Type.MULTICAST; + } else { + return Type.UNICAST; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MACAddress that = (MACAddress)o; + return address == that.address; + } + + @Override + public int hashCode() { + return Long.hashCode(address); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(17); + for (int i = 5; i >= 0; i--) { + if (i < 5) { + builder.append(':'); + } + long octet = (address >> (i * 8)) & 0xff; + builder.append(Long.toHexString(octet)); + } + return builder.toString(); + } + +} diff --git a/src/main/kotlin/net/shadowfacts/phycon/PhysicalConnectivity.kt b/src/main/kotlin/net/shadowfacts/phycon/PhysicalConnectivity.kt new file mode 100644 index 0000000..889b255 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/PhysicalConnectivity.kt @@ -0,0 +1,20 @@ +package net.shadowfacts.phycon + +import net.fabricmc.api.ModInitializer +import net.shadowfacts.phycon.init.PhyBlockEntities +import net.shadowfacts.phycon.init.PhyBlocks +import net.shadowfacts.phycon.init.PhyItems + +/** + * @author shadowfacts + */ +object PhysicalConnectivity: ModInitializer { + + val MODID = "phycon" + + override fun onInitialize() { + PhyBlocks.init() + PhyBlockEntities.init() + PhyItems.init() + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/phycon/block/BlockWithEntity.kt b/src/main/kotlin/net/shadowfacts/phycon/block/BlockWithEntity.kt new file mode 100644 index 0000000..e426b60 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/block/BlockWithEntity.kt @@ -0,0 +1,22 @@ +package net.shadowfacts.phycon.block + +import net.minecraft.block.Block +import net.minecraft.block.BlockEntityProvider +import net.minecraft.block.entity.BlockEntity +import net.minecraft.util.math.BlockPos +import net.minecraft.world.BlockView + +/** + * @author shadowfacts + */ +abstract class BlockWithEntity(settings: Settings): Block(settings), BlockEntityProvider { + abstract override fun createBlockEntity(world: BlockView): T? + fun getBlockEntity(world: BlockView, pos: BlockPos): T? { + val entity = world.getBlockEntity(pos) + return if (entity != null) { + entity as? T + } else { + null + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/phycon/init/PhyBlockEntities.kt b/src/main/kotlin/net/shadowfacts/phycon/init/PhyBlockEntities.kt new file mode 100644 index 0000000..cb898bd --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/init/PhyBlockEntities.kt @@ -0,0 +1,34 @@ +package net.shadowfacts.phycon.init + +import net.minecraft.block.Block +import net.minecraft.block.entity.BlockEntity +import net.minecraft.block.entity.BlockEntityType +import net.minecraft.util.Identifier +import net.minecraft.util.registry.Registry +import net.shadowfacts.phycon.network.block.networkinterface.NetworkInterfaceBlock +import net.shadowfacts.phycon.network.block.networkinterface.NetworkInterfaceBlockEntity +import net.shadowfacts.phycon.network.block.terminal.TerminalBlock +import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity + +/** + * @author shadowfacts + */ +object PhyBlockEntities { + + val NETWORK_INTERFACE = create(::NetworkInterfaceBlockEntity, PhyBlocks.NETWORK_INTERFACE) + val TERMINAL = create(::TerminalBlockEntity, PhyBlocks.TERMINAL) + + private fun create(builder: () -> T, block: Block): BlockEntityType { + return BlockEntityType.Builder.create(builder, arrayOf(block)).build(null) + } + + fun init() { + register(NetworkInterfaceBlock.ID, NETWORK_INTERFACE) + register(TerminalBlock.ID, TERMINAL) + } + + private fun register(id: Identifier, type: BlockEntityType<*>) { + Registry.register(Registry.BLOCK_ENTITY, id, type) + } + +} diff --git a/src/main/kotlin/net/shadowfacts/phycon/init/PhyBlocks.kt b/src/main/kotlin/net/shadowfacts/phycon/init/PhyBlocks.kt new file mode 100644 index 0000000..9def846 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/init/PhyBlocks.kt @@ -0,0 +1,26 @@ +package net.shadowfacts.phycon.init + +import net.minecraft.block.Block +import net.minecraft.util.Identifier +import net.minecraft.util.registry.Registry +import net.shadowfacts.phycon.network.block.networkinterface.NetworkInterfaceBlock +import net.shadowfacts.phycon.network.block.terminal.TerminalBlock + +/** + * @author shadowfacts + */ +object PhyBlocks { + + val NETWORK_INTERFACE = NetworkInterfaceBlock() + val TERMINAL = TerminalBlock() + + fun init() { + register(NetworkInterfaceBlock.ID, NETWORK_INTERFACE) + register(TerminalBlock.ID, TERMINAL) + } + + private fun register(id: Identifier, block: Block) { + Registry.register(Registry.BLOCK, id, block) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/phycon/init/PhyItems.kt b/src/main/kotlin/net/shadowfacts/phycon/init/PhyItems.kt new file mode 100644 index 0000000..e9172eb --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/init/PhyItems.kt @@ -0,0 +1,27 @@ +package net.shadowfacts.phycon.init + +import net.minecraft.item.BlockItem +import net.minecraft.item.Item +import net.minecraft.util.Identifier +import net.minecraft.util.registry.Registry +import net.shadowfacts.phycon.network.block.networkinterface.NetworkInterfaceBlock +import net.shadowfacts.phycon.network.block.terminal.TerminalBlock + +/** + * @author shadowfacts + */ +object PhyItems { + + val NETWORK_INTERFACE = BlockItem(PhyBlocks.NETWORK_INTERFACE, Item.Settings()) + val TERMINAL = BlockItem(PhyBlocks.TERMINAL, Item.Settings()) + + fun init() { + register(NetworkInterfaceBlock.ID, NETWORK_INTERFACE) + register(TerminalBlock.ID, TERMINAL) + } + + private fun register(id: Identifier, item: Item) { + Registry.register(Registry.ITEM, id, item) + } + +} diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/DeviceBlockEntity.kt b/src/main/kotlin/net/shadowfacts/phycon/network/DeviceBlockEntity.kt new file mode 100644 index 0000000..567626d --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/DeviceBlockEntity.kt @@ -0,0 +1,66 @@ +package net.shadowfacts.phycon.network + +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.packet.Packet +import net.shadowfacts.phycon.api.util.MACAddress +import java.util.* + +/** + * @author shadowfacts + */ +abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), Tickable, PacketSink { + + var macAddress = MACAddress.random() + protected set + + private val sendQueue = LinkedList() + + override fun handle(packet: Packet) { + if (acceptsPacket(packet)) { + handlePacket(packet) + } + } + + abstract fun handlePacket(packet: Packet) + + fun acceptsPacket(packet: Packet): Boolean { + return when (packet.destination.type) { + MACAddress.Type.BROADCAST -> true + MACAddress.Type.UNICAST -> macAddress == packet.destination + MACAddress.Type.MULTICAST -> acceptsMulticastPacket(packet) + } + } + + fun acceptsMulticastPacket(packet: Packet): Boolean { + return false + } + + fun enqueue(packet: Packet) { + sendQueue.add(packet) + } + + override fun tick() { + if (sendQueue.isNotEmpty()) { + val packet = sendQueue.pop() + val destinations = NetworkUtil.findDestinations(world!!, pos) + destinations.forEach { + it.handle(packet) + } + } + } + + override fun toTag(tag: CompoundTag): CompoundTag { + tag.putLong("MACAddress", macAddress.address) + return super.toTag(tag) + } + + override fun fromTag(tag: CompoundTag) { + super.fromTag(tag) + macAddress = MACAddress(tag.getLong("MACAddress")) + } + +} diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/NetworkUtil.kt b/src/main/kotlin/net/shadowfacts/phycon/network/NetworkUtil.kt new file mode 100644 index 0000000..7f0f7d9 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/NetworkUtil.kt @@ -0,0 +1,44 @@ +package net.shadowfacts.phycon.network + +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Direction +import net.minecraft.world.World +import net.shadowfacts.phycon.api.NetworkCable +import net.shadowfacts.phycon.api.PacketSink +import net.shadowfacts.phycon.api.PhyAttributes +import java.util.* + +/** + * @author shadowfacts + */ +object NetworkUtil { + + fun findDestinations(world: World, startPos: BlockPos): List { + val results = mutableListOf() + val visited = hashSetOf(startPos) + val queue = LinkedList() + addAdjacent(queue, visited, startPos) + while (queue.isNotEmpty()) { + val pos = queue.pop() + val sink = PhyAttributes.PACKET_SINK.getFirstOrNull(world, pos) + if (sink != null) { + results.add(sink) + } + if (pos === startPos || world.getBlockState(pos).block is NetworkCable) { + addAdjacent(queue, visited, pos) + } + visited.add(pos) + } + return results + } + + fun addAdjacent(queue: MutableList, visited: Set, pos: BlockPos) { + for (dir in Direction.values()) { + val newPos = pos.offset(dir) + if (newPos !in visited) { + queue.add(newPos) + } + } + } + +} diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/block/networkinterface/NetworkInterfaceBlock.kt b/src/main/kotlin/net/shadowfacts/phycon/network/block/networkinterface/NetworkInterfaceBlock.kt new file mode 100644 index 0000000..95df2d0 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/block/networkinterface/NetworkInterfaceBlock.kt @@ -0,0 +1,67 @@ +package net.shadowfacts.phycon.network.block.networkinterface + +import alexiil.mc.lib.attributes.AttributeList +import alexiil.mc.lib.attributes.AttributeProvider +import net.minecraft.block.Block +import net.minecraft.block.BlockState +import net.minecraft.block.Material +import net.minecraft.entity.LivingEntity +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.item.ItemPlacementContext +import net.minecraft.item.ItemStack +import net.minecraft.state.StateFactory +import net.minecraft.state.property.Properties +import net.minecraft.util.Hand +import net.minecraft.util.Identifier +import net.minecraft.util.hit.BlockHitResult +import net.minecraft.util.math.BlockPos +import net.minecraft.world.BlockView +import net.minecraft.world.World +import net.shadowfacts.phycon.PhysicalConnectivity +import net.shadowfacts.phycon.block.BlockWithEntity + +/** + * @author shadowfacts + */ +class NetworkInterfaceBlock: BlockWithEntity(Settings.of(Material.METAL)), AttributeProvider { + companion object { + val ID = Identifier(PhysicalConnectivity.MODID, "network_interface") + val FACING = Properties.FACING + } + + override fun appendProperties(builder: StateFactory.Builder) { + super.appendProperties(builder) + builder.add(FACING) + } + + override fun createBlockEntity(world: BlockView) = NetworkInterfaceBlockEntity() + + override fun getPlacementState(context: ItemPlacementContext): BlockState { + val facing = if (context.player?.isSneaking == true) context.playerFacing else context.playerFacing.opposite + return defaultState.with(FACING, facing) + } + + 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() + } + } + + override fun activate(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, result: BlockHitResult): Boolean { + if (!world.isClient) { + getBlockEntity(world, pos)!!.printContents() + } + return true + } + + override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) { + to.offer(getBlockEntity(world, pos)) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/block/networkinterface/NetworkInterfaceBlockEntity.kt b/src/main/kotlin/net/shadowfacts/phycon/network/block/networkinterface/NetworkInterfaceBlockEntity.kt new file mode 100644 index 0000000..9a8a221 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/block/networkinterface/NetworkInterfaceBlockEntity.kt @@ -0,0 +1,54 @@ +package net.shadowfacts.phycon.network.block.networkinterface + +import alexiil.mc.lib.attributes.SearchOptions +import alexiil.mc.lib.attributes.item.GroupedItemInv +import alexiil.mc.lib.attributes.item.ItemAttributes +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.packet.ReadAllPacket +import net.shadowfacts.phycon.network.packet.RequestReadAllPacket + +/** + * @author shadowfacts + */ +class NetworkInterfaceBlockEntity: DeviceBlockEntity(PhyBlockEntities.NETWORK_INTERFACE) { + + private val facing: Direction + get() = world!!.getBlockState(pos)[NetworkInterfaceBlock.FACING] + + private var inventory: GroupedItemInv? = null + + fun updateInventory() { + val offsetPos = pos.offset(facing) + val option = SearchOptions.inDirection(facing) + inventory = ItemAttributes.GROUPED_INV.getFirstOrNull(world, offsetPos, option) + } + + fun printContents() { + inventory?.also { inv -> + inv.storedStacks.forEach { + println(it) + } + } + } + + override fun handlePacket(packet: Packet) { + when (packet) { + is RequestReadAllPacket -> handleReadAll(packet) + } + } + + fun handleReadAll(packet: RequestReadAllPacket) { + enqueue(ReadAllPacket(readAll(), macAddress, packet.source)) + } + + fun readAll(): Map { + return inventory?.let { + it.storedStacks.associateWith(it::getAmount) + } ?: mapOf() + } + +} diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/block/terminal/TerminalBlock.kt b/src/main/kotlin/net/shadowfacts/phycon/network/block/terminal/TerminalBlock.kt new file mode 100644 index 0000000..e9d61d8 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/block/terminal/TerminalBlock.kt @@ -0,0 +1,35 @@ +package net.shadowfacts.phycon.network.block.terminal + +import alexiil.mc.lib.attributes.AttributeList +import alexiil.mc.lib.attributes.AttributeProvider +import net.minecraft.block.BlockState +import net.minecraft.block.Material +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.util.Hand +import net.minecraft.util.Identifier +import net.minecraft.util.hit.BlockHitResult +import net.minecraft.util.math.BlockPos +import net.minecraft.world.BlockView +import net.minecraft.world.World +import net.shadowfacts.phycon.PhysicalConnectivity +import net.shadowfacts.phycon.block.BlockWithEntity + +/** + * @author shadowfacts + */ +class TerminalBlock: BlockWithEntity(Settings.of(Material.METAL)), AttributeProvider { + companion object { + val ID = Identifier(PhysicalConnectivity.MODID, "terminal") + } + + override fun createBlockEntity(world: BlockView) = TerminalBlockEntity() + + override fun activate(blockState_1: BlockState?, world_1: World?, blockPos_1: BlockPos?, playerEntity_1: PlayerEntity?, hand_1: Hand?, blockHitResult_1: BlockHitResult?): Boolean { + getBlockEntity(world_1!!, blockPos_1!!)!!.onActivate() + return true + } + + override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) { + to.offer(getBlockEntity(world, pos)) + } +} 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 new file mode 100644 index 0000000..5c7c2f4 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/block/terminal/TerminalBlockEntity.kt @@ -0,0 +1,37 @@ +package net.shadowfacts.phycon.network.block.terminal + +import net.minecraft.item.ItemStack +import net.shadowfacts.phycon.api.packet.Packet +import net.shadowfacts.phycon.init.PhyBlockEntities +import net.shadowfacts.phycon.network.DeviceBlockEntity +import net.shadowfacts.phycon.network.packet.ReadAllPacket +import net.shadowfacts.phycon.network.packet.RequestReadAllPacket + +/** + * @author shadowfacts + */ +class TerminalBlockEntity: DeviceBlockEntity(PhyBlockEntities.TERMINAL) { + + private var cachedItems = mutableMapOf() + + override fun handlePacket(packet: Packet) { + when (packet) { + is ReadAllPacket -> handleReadAll(packet) + } + } + + fun handleReadAll(packet: ReadAllPacket) { + packet.items.forEach { (stack, amount) -> + cachedItems.merge(stack, amount) { a, b -> a + b } + } + println("new cached items: $cachedItems") + } + + fun onActivate() { + if (!world!!.isClient) { + cachedItems.clear() + enqueue(RequestReadAllPacket(macAddress)) + } + } + +} diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/packet/BasePacket.kt b/src/main/kotlin/net/shadowfacts/phycon/network/packet/BasePacket.kt new file mode 100644 index 0000000..d0a0715 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/packet/BasePacket.kt @@ -0,0 +1,17 @@ +package net.shadowfacts.phycon.network.packet + +import net.shadowfacts.phycon.api.packet.Packet +import net.shadowfacts.phycon.api.util.MACAddress + +/** + * @author shadowfacts + */ +abstract class BasePacket( + @JvmField private val source: MACAddress, + @JvmField private val destination: MACAddress +): Packet { + + override fun getSource() = source + override fun getDestination() = destination + +} \ No newline at end of file diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/packet/ReadAllPacket.kt b/src/main/kotlin/net/shadowfacts/phycon/network/packet/ReadAllPacket.kt new file mode 100644 index 0000000..9587f98 --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/packet/ReadAllPacket.kt @@ -0,0 +1,13 @@ +package net.shadowfacts.phycon.network.packet + +import net.minecraft.item.ItemStack +import net.shadowfacts.phycon.api.util.MACAddress + +/** + * @author shadowfacts + */ +class ReadAllPacket( + val items: Map, + source: MACAddress, + destination: MACAddress +): BasePacket(source, destination) diff --git a/src/main/kotlin/net/shadowfacts/phycon/network/packet/RequestReadAllPacket.kt b/src/main/kotlin/net/shadowfacts/phycon/network/packet/RequestReadAllPacket.kt new file mode 100644 index 0000000..a4ac63d --- /dev/null +++ b/src/main/kotlin/net/shadowfacts/phycon/network/packet/RequestReadAllPacket.kt @@ -0,0 +1,8 @@ +package net.shadowfacts.phycon.network.packet + +import net.shadowfacts.phycon.api.util.MACAddress + +/** + * @author shadowfacts + */ +class RequestReadAllPacket(source: MACAddress, destination: MACAddress = MACAddress.BROADCAST): BasePacket(source, destination)