Add switches

This commit is contained in:
Shadowfacts 2019-10-26 23:13:26 -04:00
parent 0908ccbb3a
commit a95621e3f1
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
8 changed files with 119 additions and 4 deletions

View File

@ -1,6 +1,7 @@
package net.shadowfacts.phycon.api;
import net.shadowfacts.phycon.api.packet.Packet;
import net.shadowfacts.phycon.api.util.MACAddress;
import org.jetbrains.annotations.NotNull;
/**
@ -8,6 +9,9 @@ import org.jetbrains.annotations.NotNull;
*/
public interface PacketSink {
@NotNull
MACAddress getMACAddress();
void handle(@NotNull Packet packet);
}

View File

@ -7,6 +7,8 @@ import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlock
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlockEntity
import net.shadowfacts.phycon.network.block.netswitch.SwitchBlock
import net.shadowfacts.phycon.network.block.netswitch.SwitchBlockEntity
import net.shadowfacts.phycon.network.block.terminal.TerminalBlock
import net.shadowfacts.phycon.network.block.terminal.TerminalBlockEntity
@ -17,6 +19,7 @@ object PhyBlockEntities {
val INTERFACE = create(::InterfaceBlockEntity, PhyBlocks.INTERFACE)
val TERMINAL = create(::TerminalBlockEntity, PhyBlocks.TERMINAL)
val SWITCH = create(::SwitchBlockEntity, PhyBlocks.SWITCH)
private fun <T: BlockEntity> create(builder: () -> T, block: Block): BlockEntityType<T> {
return BlockEntityType.Builder.create(builder, arrayOf(block)).build(null)
@ -25,6 +28,7 @@ object PhyBlockEntities {
fun init() {
register(InterfaceBlock.ID, INTERFACE)
register(TerminalBlock.ID, TERMINAL)
register(SwitchBlock.ID, SWITCH)
}
private fun register(id: Identifier, type: BlockEntityType<*>) {

View File

@ -4,6 +4,7 @@ import net.minecraft.block.Block
import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlock
import net.shadowfacts.phycon.network.block.netswitch.SwitchBlock
import net.shadowfacts.phycon.network.block.terminal.TerminalBlock
/**
@ -13,10 +14,12 @@ object PhyBlocks {
val INTERFACE = InterfaceBlock()
val TERMINAL = TerminalBlock()
val SWITCH = SwitchBlock()
fun init() {
register(InterfaceBlock.ID, INTERFACE)
register(TerminalBlock.ID, TERMINAL)
register(SwitchBlock.ID, SWITCH)
}
private fun register(id: Identifier, block: Block) {

View File

@ -5,6 +5,7 @@ import net.minecraft.item.Item
import net.minecraft.util.Identifier
import net.minecraft.util.registry.Registry
import net.shadowfacts.phycon.network.block.netinterface.InterfaceBlock
import net.shadowfacts.phycon.network.block.netswitch.SwitchBlock
import net.shadowfacts.phycon.network.block.terminal.TerminalBlock
/**
@ -14,10 +15,12 @@ object PhyItems {
val INTERFACE = BlockItem(PhyBlocks.INTERFACE, Item.Settings())
val TERMINAL = BlockItem(PhyBlocks.TERMINAL, Item.Settings())
val SWITCH = BlockItem(PhyBlocks.SWITCH, Item.Settings())
fun init() {
register(InterfaceBlock.ID, INTERFACE)
register(TerminalBlock.ID, TERMINAL)
register(SwitchBlock.ID, SWITCH)
}
private fun register(id: Identifier, item: Item) {

View File

@ -20,13 +20,17 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), T
private val sendQueue = LinkedList<Pair<Packet, WeakReference<PacketSink>>>()
override fun getMACAddress(): MACAddress {
return macAddress
}
override fun handle(packet: Packet) {
if (acceptsPacket(packet)) {
handlePacket(packet)
}
}
abstract fun handlePacket(packet: Packet)
protected abstract fun handlePacket(packet: Packet)
fun acceptsPacket(packet: Packet): Boolean {
return when (packet.destination.type) {
@ -56,7 +60,11 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>): BlockEntity(type), T
}
fun enqueueToAll(packet: Packet) {
sendQueue.addAll(NetworkUtil.findDestinations(world!!, pos).map { packet to WeakReference(it) })
enqueueToAll(packet, NetworkUtil.findDestinations(world!!, pos))
}
fun enqueueToAll(packet: Packet, destinations: Iterable<PacketSink>) {
sendQueue.addAll(destinations.map { packet to WeakReference(it) })
}
override fun tick() {

View File

@ -13,11 +13,15 @@ import java.util.*
*/
object NetworkUtil {
fun findDestinations(world: World, startPos: BlockPos): List<PacketSink> {
fun findDestinations(world: World, startPos: BlockPos, direction: Direction? = null): List<PacketSink> {
val results = LinkedList<PacketSink>()
val visited = hashSetOf(startPos)
val queue = LinkedList<BlockPos>()
if (direction != null) {
queue.add(startPos.offset(direction))
} else {
addAdjacent(queue, visited, startPos)
}
while (queue.isNotEmpty()) {
val pos = queue.pop()

View File

@ -0,0 +1,27 @@
package net.shadowfacts.phycon.network.block.netswitch
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.util.Identifier
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 SwitchBlock: BlockWithEntity<SwitchBlockEntity>(Settings.of(Material.METAL)), AttributeProvider {
companion object {
val ID = Identifier(PhysicalConnectivity.MODID, "switch")
}
override fun createBlockEntity(world: BlockView) = SwitchBlockEntity()
override fun addAllAttributes(world: World, pos: BlockPos, state: BlockState, to: AttributeList<*>) {
to.offer(getBlockEntity(world, pos))
}
}

View File

@ -0,0 +1,62 @@
package net.shadowfacts.phycon.network.block.netswitch
import net.minecraft.util.math.Direction
import net.shadowfacts.phycon.api.PacketSink
import net.shadowfacts.phycon.api.packet.Packet
import net.shadowfacts.phycon.api.util.MACAddress
import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.network.DeviceBlockEntity
import net.shadowfacts.phycon.network.NetworkUtil
import java.lang.RuntimeException
import javax.print.attribute.standard.Destination
/**
* @author shadowfacts
*/
class SwitchBlockEntity: DeviceBlockEntity(PhyBlockEntities.SWITCH) {
private val macTable = mutableMapOf<MACAddress, Direction>()
override fun handlePacket(packet: Packet) {
throw RuntimeException("Unreachable")
}
override fun handle(packet: Packet) {
if (packet.destination == MACAddress.BROADCAST) {
val allDestinations = NetworkUtil.findDestinations(world!!, pos).filter { it.macAddress != packet.source }
enqueueToAll(packet, allDestinations)
} else {
val direction = macTable[packet.destination]
if (direction != null) {
val dest = findDestination(direction)
if (dest != null && packet.destination == dest.macAddress) {
enqueue(packet, dest)
return
}
}
flood(packet)
}
}
private fun findDestination(direction: Direction): PacketSink? {
val allDestinations = NetworkUtil.findDestinations(world!!, pos, direction)
if (allDestinations.size > 1) {
// todo: do this better
println("Can't send packet, multiple destinations: $allDestinations")
return null
}
return allDestinations.firstOrNull()
}
private fun flood(packet: Packet) {
for (dir in Direction.values()) {
val dest = findDestination(dir)
if (dest != null && packet.destination == dest.macAddress) {
macTable[packet.destination] = dir
enqueue(packet, dest)
break
}
}
}
}