From d5271858887a8d0ab2beff698eaf1fa597961029 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 12 Mar 2023 22:18:34 -0400 Subject: [PATCH] Cache destination interfaces --- kiwi-java | 2 +- .../net/shadowfacts/phycon/api/Interface.java | 2 ++ .../phycon/block/DeviceBlockEntity.kt | 17 ++++++++++++++++- .../phycon/block/cable/CableBlock.kt | 14 ++++++++++++++ .../phycon/block/netswitch/SwitchBlockEntity.kt | 10 +++++++++- .../net/shadowfacts/phycon/frame/ARPFrame.kt | 1 + 6 files changed, 43 insertions(+), 3 deletions(-) diff --git a/kiwi-java b/kiwi-java index abe783a..1cbaea5 160000 --- a/kiwi-java +++ b/kiwi-java @@ -1 +1 @@ -Subproject commit abe783ae7ce45ccf296ed7b7e5c1b194e7c560fa +Subproject commit 1cbaea53d207f1e16c6e5ee2e6bf6e3c1440ac44 diff --git a/src/main/java/net/shadowfacts/phycon/api/Interface.java b/src/main/java/net/shadowfacts/phycon/api/Interface.java index 6f5ce31..528596f 100644 --- a/src/main/java/net/shadowfacts/phycon/api/Interface.java +++ b/src/main/java/net/shadowfacts/phycon/api/Interface.java @@ -16,4 +16,6 @@ public interface Interface { void send(@NotNull EthernetFrame frame); + default void cableDisconnected() {} + } diff --git a/src/main/kotlin/net/shadowfacts/phycon/block/DeviceBlockEntity.kt b/src/main/kotlin/net/shadowfacts/phycon/block/DeviceBlockEntity.kt index 326df3a..ba00c76 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/block/DeviceBlockEntity.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/block/DeviceBlockEntity.kt @@ -21,6 +21,7 @@ import net.shadowfacts.phycon.frame.ARPResponseFrame import net.shadowfacts.phycon.frame.BasePacketFrame import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.util.NetworkUtil +import java.lang.ref.WeakReference import java.util.* /** @@ -43,6 +44,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: private val arpTable = mutableMapOf() private val packetQueue = LinkedList() + private var cachedDestination: WeakReference? = null var counter: Long = 0 @@ -119,14 +121,27 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: } open fun findDestination(): Interface? { + val cachedDestination = this.cachedDestination?.get() + if (cachedDestination != null) { + return cachedDestination + } + val sides = (cachedState.block as NetworkComponentBlock).getNetworkConnectedSides(cachedState, world!!, pos) return when (sides.size) { 0 -> null - 1 -> NetworkUtil.findConnectedInterface(world!!, pos, sides.first()) + 1 -> { + NetworkUtil.findConnectedInterface(world!!, pos, sides.first())?.also { + this.cachedDestination = WeakReference(it) + } + } else -> throw RuntimeException("DeviceBlockEntity.findDestination must be overridden by devices which have more than 1 network connected side") } } + override fun cableDisconnected() { + cachedDestination = null + } + open fun tick() { counter++ diff --git a/src/main/kotlin/net/shadowfacts/phycon/block/cable/CableBlock.kt b/src/main/kotlin/net/shadowfacts/phycon/block/cable/CableBlock.kt index 89e1c92..6a70116 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/block/cable/CableBlock.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/block/cable/CableBlock.kt @@ -23,9 +23,11 @@ import net.shadowfacts.phycon.PhysicalConnectivity import net.shadowfacts.phycon.api.Interface import net.shadowfacts.phycon.api.NetworkCableBlock import net.shadowfacts.phycon.api.NetworkComponentBlock +import net.shadowfacts.phycon.block.DeviceBlockEntity import net.shadowfacts.phycon.init.PhyItems import net.shadowfacts.phycon.item.FaceDeviceBlockItem import net.shadowfacts.phycon.util.CableConnection +import net.shadowfacts.phycon.util.NetworkUtil import net.shadowfacts.phycon.util.containsInclusive import java.util.* @@ -195,4 +197,16 @@ class CableBlock( return getShape(state) } + override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) { + super.onBreak(world, pos, state, player) + if (!world.isClient) { + // notify devices on either end that the connection was broken (i.e., unset the cached receivers) + val connectedSides = getNetworkConnectedSides(state, world, pos) + for (side in connectedSides) { + val dest = NetworkUtil.findConnectedInterface(world, pos, side) + dest?.cableDisconnected() + } + } + } + } diff --git a/src/main/kotlin/net/shadowfacts/phycon/block/netswitch/SwitchBlockEntity.kt b/src/main/kotlin/net/shadowfacts/phycon/block/netswitch/SwitchBlockEntity.kt index 7bc00ed..a08c5fe 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/block/netswitch/SwitchBlockEntity.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/block/netswitch/SwitchBlockEntity.kt @@ -36,6 +36,7 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE val interfaces = Direction.values().map { SwitchInterface(it, WeakReference(this), MACAddress.random()) } private val macTable = mutableMapOf() + private val destinationCache = Array?>(6) { null } private var packetsHandledThisTick = 0 private var delayedPackets: Deque> = LinkedList() @@ -79,7 +80,10 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE private fun findDestination(fromItf: Interface): Interface? { val side = (fromItf as SwitchInterface).side - return NetworkUtil.findConnectedInterface(world!!, pos, side) + return destinationCache[side.ordinal]?.get() + ?: NetworkUtil.findConnectedInterface(world!!, pos, side)?.also { + destinationCache[side.ordinal] = WeakReference(it) + } } fun tick() { @@ -158,6 +162,10 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE override fun send(frame: EthernetFrame) { switch.get()?.findDestination(this)?.receive(frame) } + + override fun cableDisconnected() { + switch.get()?.destinationCache?.set(side.ordinal, null) + } } } diff --git a/src/main/kotlin/net/shadowfacts/phycon/frame/ARPFrame.kt b/src/main/kotlin/net/shadowfacts/phycon/frame/ARPFrame.kt index ea39718..e3e2ceb 100644 --- a/src/main/kotlin/net/shadowfacts/phycon/frame/ARPFrame.kt +++ b/src/main/kotlin/net/shadowfacts/phycon/frame/ARPFrame.kt @@ -1,5 +1,6 @@ package net.shadowfacts.phycon.frame +import net.shadowfacts.phycon.api.Interface import net.shadowfacts.phycon.api.util.IPAddress import net.shadowfacts.phycon.api.util.MACAddress