PhysicalConnectivity/src/main/kotlin/net/shadowfacts/phycon/network/block/netswitch/SwitchBlockEntity.kt

138 lines
3.9 KiB
Kotlin
Raw Normal View History

2019-10-27 03:13:26 +00:00
package net.shadowfacts.phycon.network.block.netswitch
2021-02-13 23:24:36 +00:00
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable
import net.minecraft.block.BlockState
import net.minecraft.block.entity.BlockEntity
import net.minecraft.nbt.CompoundTag
2019-10-30 18:05:53 +00:00
import net.minecraft.util.Tickable
2019-10-27 03:13:26 +00:00
import net.minecraft.util.math.Direction
2021-02-13 23:24:36 +00:00
import net.shadowfacts.phycon.api.Interface
import net.shadowfacts.phycon.api.frame.EthernetFrame
2019-10-27 03:13:26 +00:00
import net.shadowfacts.phycon.api.util.MACAddress
import net.shadowfacts.phycon.init.PhyBlockEntities
import net.shadowfacts.phycon.network.NetworkUtil
import java.lang.ref.WeakReference
2019-10-27 03:13:26 +00:00
/**
* @author shadowfacts
*/
2021-02-13 23:24:36 +00:00
class SwitchBlockEntity: BlockEntity(PhyBlockEntities.SWITCH),
BlockEntityClientSerializable,
Tickable {
2019-10-30 18:05:53 +00:00
companion object {
var SWITCHING_CAPACITY = 256
}
2019-10-27 03:13:26 +00:00
val interfaces = Direction.values().map { SwitchInterface(it, WeakReference(this), MACAddress.random()) }
2021-02-13 23:24:36 +00:00
2019-10-27 03:13:26 +00:00
private val macTable = mutableMapOf<MACAddress, Direction>()
2019-10-30 18:05:53 +00:00
private var packetsHandledThisTick = 0
2021-02-13 23:24:36 +00:00
// override fun handle(packet: Packet, itf: Interface) {
// if (packetsHandledThisTick >= SWITCHING_CAPACITY) {
// if (packet is ItemStackPacket) {
// // todo: calculate entity spawn point by finding non-obstructed location
// val entity = ItemEntity(world!!, pos.x.toDouble(), pos.y + 1.0, pos.z.toDouble(), packet.stack)
// world!!.spawnEntity(entity)
// }
// return
// }
//
// packetsHandledThisTick++
//
// if (packet.destination.isBroadcast) {
//// for (other in interfaces) {
//// if (other == itf) continue
//// sendPacket(packet, other)
//// }
// flood(packet, itf)
// } else {
// val direction = ipTable[packet.destination]
// if (direction != null) {
// sendPacket()
//// val dest = findDestination(direction)
//// if (dest != null && packet.destination == dest.macAddress) {
//// sendPacke(packet, dest)
//// return
//// }
// }
// flood(packet, itf)
// }
// }
2019-10-27 03:13:26 +00:00
2021-02-13 23:24:36 +00:00
fun interfaceForSide(side: Direction): SwitchInterface {
return interfaces.find { it.side == side }!!
}
2019-10-30 18:05:53 +00:00
private fun handle(frame: EthernetFrame, fromItf: Interface) {
2021-02-13 23:24:36 +00:00
val itfSide = (fromItf as SwitchInterface).side
macTable[frame.source] = itfSide
2019-10-27 03:13:26 +00:00
2021-02-13 23:24:36 +00:00
val knownDir = macTable[frame.destination]
if (knownDir != null) {
println("$this ($itfSide, ${fromItf.macAddress}) forwarding $frame to side $knownDir")
interfaceForSide(knownDir).send(frame)
2019-10-27 03:13:26 +00:00
} else {
2021-02-13 23:24:36 +00:00
println("$this ($itfSide, ${fromItf.macAddress}) flooding $frame")
flood(frame, fromItf)
2019-10-27 03:13:26 +00:00
}
}
2021-02-13 23:24:36 +00:00
private fun flood(frame: EthernetFrame, source: Interface) {
for (itf in interfaces) {
if (source == itf) continue
itf.send(frame)
2019-10-27 03:13:26 +00:00
}
}
private fun findDestination(fromItf: Interface): Interface? {
2021-02-13 23:24:36 +00:00
val side = (fromItf as SwitchInterface).side
return NetworkUtil.findConnectedInterface(world!!, pos, side)
2019-10-27 03:13:26 +00:00
}
2019-10-30 18:05:53 +00:00
override fun tick() {
packetsHandledThisTick = 0
}
2021-02-13 23:24:36 +00:00
override fun toTag(tag: CompoundTag): CompoundTag {
tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address })
return super.toTag(tag)
}
override fun fromTag(state: BlockState, tag: CompoundTag) {
super.fromTag(state, tag)
tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l ->
interfaces[i].macAddress = MACAddress(l)
}
}
override fun toClientTag(tag: CompoundTag): CompoundTag {
tag.putLongArray("InterfaceAddresses", interfaces.map { it.macAddress.address })
return tag
}
override fun fromClientTag(tag: CompoundTag) {
tag.getLongArray("InterfaceAddresses")?.forEachIndexed { i, l ->
interfaces[i].macAddress = MACAddress(l)
}
}
class SwitchInterface(
val side: Direction,
val switch: WeakReference<SwitchBlockEntity>,
@JvmField var macAddress: MACAddress,
): Interface {
override fun getMACAddress() = macAddress
2021-02-13 23:24:36 +00:00
override fun receive(frame: EthernetFrame) {
switch.get()?.handle(frame, this)
}
override fun send(frame: EthernetFrame) {
switch.get()?.findDestination(this)?.receive(frame)
}
2021-02-13 23:24:36 +00:00
}
2019-10-27 03:13:26 +00:00
}