Rudimentary network implementation
This commit is contained in:
parent
7b1a82d02b
commit
0eabbf9ec1
|
@ -0,0 +1,7 @@
|
||||||
|
package net.shadowfacts.phycon.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
public interface NetworkCable {
|
||||||
|
}
|
|
@ -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<ItemStack, Integer> readAll();
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -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<PacketSink> PACKET_SINK = Attributes.create(PacketSink.class);
|
||||||
|
public static final Attribute<NetworkInterface> NETWORK_INTERFACE = Attributes.create(NetworkInterface.class);
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<T: BlockEntity>(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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <T: BlockEntity> create(builder: () -> T, block: Block): BlockEntityType<T> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<Packet>()
|
||||||
|
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<PacketSink> {
|
||||||
|
val results = mutableListOf<PacketSink>()
|
||||||
|
val visited = hashSetOf(startPos)
|
||||||
|
val queue = LinkedList<BlockPos>()
|
||||||
|
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<BlockPos>, visited: Set<BlockPos>, pos: BlockPos) {
|
||||||
|
for (dir in Direction.values()) {
|
||||||
|
val newPos = pos.offset(dir)
|
||||||
|
if (newPos !in visited) {
|
||||||
|
queue.add(newPos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<NetworkInterfaceBlockEntity>(Settings.of(Material.METAL)), AttributeProvider {
|
||||||
|
companion object {
|
||||||
|
val ID = Identifier(PhysicalConnectivity.MODID, "network_interface")
|
||||||
|
val FACING = Properties.FACING
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun appendProperties(builder: StateFactory.Builder<Block, BlockState>) {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<ItemStack, Int> {
|
||||||
|
return inventory?.let {
|
||||||
|
it.storedStacks.associateWith(it::getAmount)
|
||||||
|
} ?: mapOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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<TerminalBlockEntity>(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))
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<ItemStack, Int>()
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
}
|
|
@ -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<ItemStack, Int>,
|
||||||
|
source: MACAddress,
|
||||||
|
destination: MACAddress
|
||||||
|
): BasePacket(source, destination)
|
|
@ -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)
|
Loading…
Reference in New Issue