Cache destination interfaces

This commit is contained in:
Shadowfacts 2023-03-12 22:18:34 -04:00
parent 82482ca9c6
commit d527185888
6 changed files with 43 additions and 3 deletions

@ -1 +1 @@
Subproject commit abe783ae7ce45ccf296ed7b7e5c1b194e7c560fa Subproject commit 1cbaea53d207f1e16c6e5ee2e6bf6e3c1440ac44

View File

@ -16,4 +16,6 @@ public interface Interface {
void send(@NotNull EthernetFrame frame); void send(@NotNull EthernetFrame frame);
default void cableDisconnected() {}
} }

View File

@ -21,6 +21,7 @@ import net.shadowfacts.phycon.frame.ARPResponseFrame
import net.shadowfacts.phycon.frame.BasePacketFrame import net.shadowfacts.phycon.frame.BasePacketFrame
import net.shadowfacts.phycon.packet.* import net.shadowfacts.phycon.packet.*
import net.shadowfacts.phycon.util.NetworkUtil import net.shadowfacts.phycon.util.NetworkUtil
import java.lang.ref.WeakReference
import java.util.* import java.util.*
/** /**
@ -43,6 +44,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
private val arpTable = mutableMapOf<IPAddress, MACAddress>() private val arpTable = mutableMapOf<IPAddress, MACAddress>()
private val packetQueue = LinkedList<PendingPacket>() private val packetQueue = LinkedList<PendingPacket>()
private var cachedDestination: WeakReference<Interface>? = null
var counter: Long = 0 var counter: Long = 0
@ -119,14 +121,27 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
} }
open fun findDestination(): Interface? { open fun findDestination(): Interface? {
val cachedDestination = this.cachedDestination?.get()
if (cachedDestination != null) {
return cachedDestination
}
val sides = (cachedState.block as NetworkComponentBlock).getNetworkConnectedSides(cachedState, world!!, pos) val sides = (cachedState.block as NetworkComponentBlock).getNetworkConnectedSides(cachedState, world!!, pos)
return when (sides.size) { return when (sides.size) {
0 -> null 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") 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() { open fun tick() {
counter++ counter++

View File

@ -23,9 +23,11 @@ import net.shadowfacts.phycon.PhysicalConnectivity
import net.shadowfacts.phycon.api.Interface import net.shadowfacts.phycon.api.Interface
import net.shadowfacts.phycon.api.NetworkCableBlock import net.shadowfacts.phycon.api.NetworkCableBlock
import net.shadowfacts.phycon.api.NetworkComponentBlock import net.shadowfacts.phycon.api.NetworkComponentBlock
import net.shadowfacts.phycon.block.DeviceBlockEntity
import net.shadowfacts.phycon.init.PhyItems import net.shadowfacts.phycon.init.PhyItems
import net.shadowfacts.phycon.item.FaceDeviceBlockItem import net.shadowfacts.phycon.item.FaceDeviceBlockItem
import net.shadowfacts.phycon.util.CableConnection import net.shadowfacts.phycon.util.CableConnection
import net.shadowfacts.phycon.util.NetworkUtil
import net.shadowfacts.phycon.util.containsInclusive import net.shadowfacts.phycon.util.containsInclusive
import java.util.* import java.util.*
@ -195,4 +197,16 @@ class CableBlock(
return getShape(state) 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()
}
}
}
} }

View File

@ -36,6 +36,7 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
val interfaces = Direction.values().map { SwitchInterface(it, WeakReference(this), MACAddress.random()) } val interfaces = Direction.values().map { SwitchInterface(it, WeakReference(this), MACAddress.random()) }
private val macTable = mutableMapOf<MACAddress, Direction>() private val macTable = mutableMapOf<MACAddress, Direction>()
private val destinationCache = Array<WeakReference<Interface>?>(6) { null }
private var packetsHandledThisTick = 0 private var packetsHandledThisTick = 0
private var delayedPackets: Deque<Pair<PacketFrame, SwitchInterface>> = LinkedList() private var delayedPackets: Deque<Pair<PacketFrame, SwitchInterface>> = LinkedList()
@ -79,7 +80,10 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
private fun findDestination(fromItf: Interface): Interface? { private fun findDestination(fromItf: Interface): Interface? {
val side = (fromItf as SwitchInterface).side 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() { fun tick() {
@ -158,6 +162,10 @@ class SwitchBlockEntity(pos: BlockPos, state: BlockState): BlockEntity(PhyBlockE
override fun send(frame: EthernetFrame) { override fun send(frame: EthernetFrame) {
switch.get()?.findDestination(this)?.receive(frame) switch.get()?.findDestination(this)?.receive(frame)
} }
override fun cableDisconnected() {
switch.get()?.destinationCache?.set(side.ordinal, null)
}
} }
} }

View File

@ -1,5 +1,6 @@
package net.shadowfacts.phycon.frame package net.shadowfacts.phycon.frame
import net.shadowfacts.phycon.api.Interface
import net.shadowfacts.phycon.api.util.IPAddress import net.shadowfacts.phycon.api.util.IPAddress
import net.shadowfacts.phycon.api.util.MACAddress import net.shadowfacts.phycon.api.util.MACAddress