mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-10 05:41:51 +09:00
electric: rising/falling edge and level detection
This commit is contained in:
@@ -151,4 +151,8 @@ class WireCodex {
|
||||
|
||||
printdbg(this, "Setting prop ${prop.id} ->>\t${prop.nameKey}")
|
||||
}
|
||||
|
||||
fun getAllWiresThatAccepts(accept: String): List<Pair<ItemID, WireProp>> {
|
||||
return wireProps.filter { it.value.accepts == accept }.toList()
|
||||
}
|
||||
}
|
||||
@@ -389,14 +389,14 @@ open class GameWorld(
|
||||
return wiringGraph[blockAddr]?.get(itemID)?.emt
|
||||
}
|
||||
|
||||
fun getWireRecvStateOf(x: Int, y: Int, itemID: ItemID): ArrayList<WireRecvState>? {
|
||||
fun getWireReceptionStateOf(x: Int, y: Int, itemID: ItemID): ArrayList<WireReceptionState>? {
|
||||
val (x, y) = coerceXY(x, y)
|
||||
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
||||
return getWireRecvStateUnsafe(blockAddr, itemID)
|
||||
return getWireReceptionStateUnsafe(blockAddr, itemID)
|
||||
}
|
||||
|
||||
fun getWireRecvStateUnsafe(blockAddr: BlockAddress, itemID: ItemID): ArrayList<WireRecvState>? {
|
||||
return wiringGraph[blockAddr]?.get(itemID)?.rcv
|
||||
fun getWireReceptionStateUnsafe(blockAddr: BlockAddress, itemID: ItemID): ArrayList<WireReceptionState>? {
|
||||
return wiringGraph[blockAddr]?.get(itemID)?.rcp
|
||||
}
|
||||
|
||||
fun setWireGraphOf(x: Int, y: Int, itemID: ItemID, cnx: Int) {
|
||||
@@ -429,7 +429,7 @@ open class GameWorld(
|
||||
wiringGraph[blockAddr]!![itemID]!!.emt.set(vector)
|
||||
}
|
||||
|
||||
fun addWireRecvStateOf(x: Int, y: Int, itemID: ItemID, state: WireRecvState) {
|
||||
fun addWireRecvStateOf(x: Int, y: Int, itemID: ItemID, state: WireReceptionState) {
|
||||
val (x, y) = coerceXY(x, y)
|
||||
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
||||
return addWireRecvStateOfUnsafe(blockAddr, itemID, state)
|
||||
@@ -441,13 +441,13 @@ open class GameWorld(
|
||||
return clearAllWireRecvStateUnsafe(blockAddr)
|
||||
}
|
||||
|
||||
fun addWireRecvStateOfUnsafe(blockAddr: BlockAddress, itemID: ItemID, state: WireRecvState) {
|
||||
fun addWireRecvStateOfUnsafe(blockAddr: BlockAddress, itemID: ItemID, state: WireReceptionState) {
|
||||
if (wiringGraph[blockAddr] == null)
|
||||
wiringGraph[blockAddr] = WiringGraphMap()
|
||||
if (wiringGraph[blockAddr]!![itemID] == null)
|
||||
wiringGraph[blockAddr]!![itemID] = WiringSimCell(0)
|
||||
|
||||
wiringGraph[blockAddr]!![itemID]!!.rcv.add(state)
|
||||
wiringGraph[blockAddr]!![itemID]!!.rcp.add(state)
|
||||
}
|
||||
|
||||
fun getAllWiringGraph(x: Int, y: Int): HashMap<ItemID, WiringSimCell>? {
|
||||
@@ -462,7 +462,7 @@ open class GameWorld(
|
||||
|
||||
fun clearAllWireRecvStateUnsafe(blockAddr: BlockAddress) {
|
||||
wiringGraph[blockAddr]?.forEach {
|
||||
it.value.rcv.clear()
|
||||
it.value.rcp.clear()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,7 +654,7 @@ open class GameWorld(
|
||||
val ws: SortedArrayList<ItemID> = SortedArrayList<ItemID>() // what could possibly go wrong bloating up the RAM footprint when it's practically infinite these days?
|
||||
)
|
||||
|
||||
data class WireRecvState(
|
||||
data class WireReceptionState(
|
||||
var dist: Int = -1, // how many tiles it took to traverse
|
||||
var src: Point2i = Point2i(0,0) // xy position
|
||||
// to get the state, use the src to get the state of the source emitter directly, then use dist to apply attenuation
|
||||
@@ -666,7 +666,7 @@ open class GameWorld(
|
||||
data class WiringSimCell(
|
||||
var cnx: Int = 0, // connections. [1, 2, 4, 8] = [RIGHT, DOWN, LEFT, UP]
|
||||
val emt: Vector2 = Vector2(0.0, 0.0), // i'm emitting this much power
|
||||
val rcv: ArrayList<WireRecvState> = ArrayList() // how far away are the power sources
|
||||
val rcp: ArrayList<WireReceptionState> = ArrayList() // how far away are the power sources
|
||||
)
|
||||
|
||||
fun getTemperature(worldTileX: Int, worldTileY: Int): Float? {
|
||||
|
||||
@@ -469,15 +469,15 @@ object WorldSimulator {
|
||||
/**
|
||||
* @return List of FixtureBases, safe to cast into Electric
|
||||
*/
|
||||
private fun wiresimGetSourceBlocks(): List<FixtureBase> =
|
||||
INGAME.actorContainerActive.filterIsInstance<FixtureBase>().filter {
|
||||
it is Electric && it.inUpdateRange(world) && it.wireEmitterTypes.isNotEmpty()
|
||||
private fun wiresimGetSourceBlocks(): List<Electric> =
|
||||
INGAME.actorContainerActive.filterIsInstance<Electric>().filter {
|
||||
it.inUpdateRange(world) && it.wireEmitterTypes.isNotEmpty()
|
||||
}
|
||||
|
||||
private val wireSimMarked = HashSet<Long>()
|
||||
private val wireSimPoints = Queue<WireGraphCursor>()
|
||||
private val oldTraversedNodes = ArrayList<WireGraphCursor>()
|
||||
private val fixtureCache = HashMap<Point2i, Pair<FixtureBase, WireEmissionType>>() // also instance of Electric
|
||||
private val fixtureCache = HashMap<Point2i, Pair<Electric, WireEmissionType>>() // also instance of Electric
|
||||
|
||||
private fun simulateWires(delta: Float) {
|
||||
// unset old wires before we begin
|
||||
@@ -491,10 +491,10 @@ object WorldSimulator {
|
||||
wiresimGetSourceBlocks().let { sources ->
|
||||
// signal-emitting fixtures must set emitState of its own tiles via update()
|
||||
sources.forEach {
|
||||
(it as Electric).wireEmitterTypes.forEach { bbi, wireType ->
|
||||
it.wireEmitterTypes.forEach { bbi, wireType ->
|
||||
|
||||
val startingPoint = it.worldBlockPos!! + it.blockBoxIndexToPoint2i(bbi)
|
||||
val signal = (it as Electric).wireEmission[bbi] ?: Vector2(0.0, 0.0)
|
||||
val signal = it.wireEmission[bbi] ?: Vector2(0.0, 0.0)
|
||||
|
||||
world.getAllWiringGraph(startingPoint.x, startingPoint.y)?.keys?.filter { WireCodex[it].accepts == wireType }?.forEach { wire ->
|
||||
val simStartingPoint = WireGraphCursor(startingPoint, wire)
|
||||
@@ -553,20 +553,19 @@ object WorldSimulator {
|
||||
if (fixture == null) {
|
||||
INGAME.getActorsAt(point.x * TILE_SIZED, point.y * TILE_SIZED).filterIsInstance<Electric>().firstOrNull().let { found ->
|
||||
if (found != null) {
|
||||
val foundFixture = (found as FixtureBase)
|
||||
// get offset from the fixture's origin
|
||||
tileOffsetFromFixture = foundFixture.intTilewiseHitbox.let { Point2i(it.startX.toInt(), it.startY.toInt()) } - tilePoint
|
||||
tileOffsetFromFixture = found.intTilewiseHitbox.let { Point2i(it.startX.toInt(), it.startY.toInt()) } - tilePoint
|
||||
|
||||
// println("$tilePoint; ${found.javaClass.canonicalName}, $tileOffsetFromFixture, ${found.getWireSinkAt(tileOffsetFromFixture!!)}")
|
||||
|
||||
if (found.getWireSinkAt(tileOffsetFromFixture!!) == emissionType) {
|
||||
fixtureCache[tilePoint] = foundFixture to emissionType
|
||||
fixture = foundFixture to emissionType
|
||||
fixtureCache[tilePoint] = found to emissionType
|
||||
fixture = found to emissionType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(fixture?.first as? Electric)?.updateOnWireGraphTraversal(tileOffsetFromFixture!!.x, tileOffsetFromFixture!!.y, fixture!!.second)
|
||||
fixture?.first?.updateOnWireGraphTraversal(tileOffsetFromFixture!!.x, tileOffsetFromFixture!!.y, fixture!!.second)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,18 +16,108 @@ import java.util.*
|
||||
typealias BlockBoxIndex = Int
|
||||
typealias WireEmissionType = String
|
||||
|
||||
interface Electric {
|
||||
val wireEmitterTypes: HashMap<BlockBoxIndex, WireEmissionType>
|
||||
val wireSinkTypes: HashMap<BlockBoxIndex, WireEmissionType>
|
||||
val wireEmission: HashMap<BlockBoxIndex, Vector2>
|
||||
val wireConsumption: HashMap<BlockBoxIndex, Vector2>
|
||||
open class Electric : FixtureBase {
|
||||
|
||||
fun onRisingEdge(readFrom: BlockBoxIndex) {}
|
||||
fun onFallingEdge(readFrom: BlockBoxIndex) {}
|
||||
fun onSignalHigh(readFrom: BlockBoxIndex, highThreshold: Double = 0.9) {}
|
||||
fun onSignalLow(readFrom: BlockBoxIndex, lowThreshold: Double = 0.1) {}
|
||||
protected constructor() : super() {
|
||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
}
|
||||
|
||||
fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {}
|
||||
/**
|
||||
* Making the sprite: do not address the CommonResourcePool directly; just do it like this snippet:
|
||||
*
|
||||
* ```makeNewSprite(FixtureBase.getSpritesheet("basegame", "sprites/fixtures/tiki_torch.tga", 16, 32))```
|
||||
*/
|
||||
constructor(
|
||||
blockBox0: BlockBox,
|
||||
blockBoxProps: BlockBoxProps = BlockBoxProps(0),
|
||||
renderOrder: RenderOrder = RenderOrder.MIDDLE,
|
||||
nameFun: () -> String,
|
||||
mainUI: UICanvas? = null,
|
||||
inventory: FixtureInventory? = null,
|
||||
id: ActorID? = null
|
||||
) : super(renderOrder, PhysProperties.IMMOBILE, id) {
|
||||
blockBox = blockBox0
|
||||
setHitboxDimension(TILE_SIZE * blockBox.width, TILE_SIZE * blockBox.height, 0, 0)
|
||||
this.blockBoxProps = blockBoxProps
|
||||
this.renderOrder = renderOrder
|
||||
this.nameFun = nameFun
|
||||
this.mainUI = mainUI
|
||||
this.inventory = inventory
|
||||
|
||||
if (mainUI != null)
|
||||
App.disposables.add(mainUI)
|
||||
|
||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ELECTIC_THRESHOLD_HIGH = 0.9
|
||||
const val ELECTRIC_THRESHOLD_LOW = 0.1
|
||||
const val ELECTRIC_THRESHOLD_EDGE_DELTA = 0.7
|
||||
}
|
||||
|
||||
fun getWireEmitterAt(point: Point2i) = if (this is Electric) this.wireEmitterTypes[pointToBlockBoxIndex(point)] else throw IllegalStateException("Fixture is not instance of Electric")
|
||||
fun getWireEmitterAt(x: Int, y: Int) = if (this is Electric) this.wireEmitterTypes[pointToBlockBoxIndex(x, y)] else throw IllegalStateException("Fixture is not instance of Electric")
|
||||
fun getWireSinkAt(point: Point2i) = if (this is Electric) this.wireSinkTypes[pointToBlockBoxIndex(point)] else throw IllegalStateException("Fixture is not instance of Electric")
|
||||
fun getWireSinkAt(x: Int, y: Int) = if (this is Electric) this.wireSinkTypes[pointToBlockBoxIndex(x, y)] else throw IllegalStateException("Fixture is not instance of Electric")
|
||||
|
||||
fun setWireEmitterAt(x: Int, y: Int, type: WireEmissionType) { if (this is Electric) wireEmitterTypes[pointToBlockBoxIndex(x, y)] = type else throw IllegalStateException("Fixture is not instance of Electric") }
|
||||
fun setWireSinkAt(x: Int, y: Int, type: WireEmissionType) { if (this is Electric) wireSinkTypes[pointToBlockBoxIndex(x, y)] = type else throw IllegalStateException("Fixture is not instance of Electric") }
|
||||
fun setWireEmissionAt(x: Int, y: Int, emission: Vector2) { if (this is Electric) wireEmission[pointToBlockBoxIndex(x, y)] = emission else throw IllegalStateException("Fixture is not instance of Electric") }
|
||||
fun setWireConsumptionAt(x: Int, y: Int, consumption: Vector2) { if (this is Electric) wireConsumption[pointToBlockBoxIndex(x, y)] = consumption else throw IllegalStateException("Fixture is not instance of Electric") }
|
||||
|
||||
@Transient val wireEmitterTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
||||
@Transient val wireSinkTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
||||
@Transient val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
@Transient val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
|
||||
/** Edge detection only considers the real component (labeled as 'x') of the vector */
|
||||
open fun onRisingEdge(readFrom: BlockBoxIndex) {}
|
||||
/** Edge detection only considers the real component (labeled as 'x') of the vector */
|
||||
open fun onFallingEdge(readFrom: BlockBoxIndex) {}
|
||||
/** Level detection only considers the real component (labeled as 'x') of the vector */
|
||||
open fun onSignalHigh(readFrom: BlockBoxIndex) {}
|
||||
/** Level detection only considers the real component (labeled as 'x') of the vector */
|
||||
open fun onSignalLow(readFrom: BlockBoxIndex) {}
|
||||
|
||||
|
||||
private val oldSinkStatus: Array<Vector2>
|
||||
|
||||
open fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {
|
||||
val index = pointToBlockBoxIndex(offsetX, offsetY)
|
||||
val old = oldSinkStatus[index]
|
||||
val wx = offsetX + intTilewiseHitbox.startX.toInt()
|
||||
val wy = offsetY + intTilewiseHitbox.startY.toInt()
|
||||
val new = WireCodex.getAllWiresThatAccepts("digital_bit").fold(Vector2()) { acc, (id, _) ->
|
||||
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
||||
}
|
||||
}
|
||||
|
||||
if (new.x - old.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x >= ELECTIC_THRESHOLD_HIGH)
|
||||
onRisingEdge(index)
|
||||
else if (old.x - new.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x <= ELECTRIC_THRESHOLD_LOW)
|
||||
onFallingEdge(index)
|
||||
else if (new.x >= ELECTIC_THRESHOLD_HIGH)
|
||||
onSignalHigh(index)
|
||||
else if (new.y <= ELECTRIC_THRESHOLD_LOW)
|
||||
onSignalLow(index)
|
||||
|
||||
}
|
||||
|
||||
override fun update(delta: Float) {
|
||||
super.update(delta)
|
||||
oldSinkStatus.indices.forEach { index ->
|
||||
val wx = (index % blockBox.width) + intTilewiseHitbox.startX.toInt()
|
||||
val wy = (index / blockBox.width) + intTilewiseHitbox.startY.toInt()
|
||||
val new = WireCodex.getAllWiresThatAccepts(getWireSinkAt(index % blockBox.width, index / blockBox.width) ?: "").fold(Vector2()) { acc, (id, _) ->
|
||||
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
||||
}
|
||||
}
|
||||
oldSinkStatus[index].set(new)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,16 +139,6 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
fun pointToBlockBoxIndex(point: Point2i) = point.y * this.blockBox.width + point.x
|
||||
fun pointToBlockBoxIndex(x: Int, y: Int) = y * this.blockBox.width + x
|
||||
|
||||
fun getWireEmitterAt(point: Point2i) = if (this is Electric) this.wireEmitterTypes[pointToBlockBoxIndex(point)] else throw IllegalStateException("Fixture is not instance of Electric")
|
||||
fun getWireEmitterAt(x: Int, y: Int) = if (this is Electric) this.wireEmitterTypes[pointToBlockBoxIndex(x, y)] else throw IllegalStateException("Fixture is not instance of Electric")
|
||||
fun getWireSinkAt(point: Point2i) = if (this is Electric) this.wireSinkTypes[pointToBlockBoxIndex(point)] else throw IllegalStateException("Fixture is not instance of Electric")
|
||||
fun getWireSinkAt(x: Int, y: Int) = if (this is Electric) this.wireSinkTypes[pointToBlockBoxIndex(x, y)] else throw IllegalStateException("Fixture is not instance of Electric")
|
||||
|
||||
fun setWireEmitterAt(x: Int, y: Int, type: WireEmissionType) { if (this is Electric) wireEmitterTypes[pointToBlockBoxIndex(x, y)] = type else throw IllegalStateException("Fixture is not instance of Electric") }
|
||||
fun setWireSinkAt(x: Int, y: Int, type: WireEmissionType) { if (this is Electric) wireSinkTypes[pointToBlockBoxIndex(x, y)] = type else throw IllegalStateException("Fixture is not instance of Electric") }
|
||||
fun setWireEmissionAt(x: Int, y: Int, emission: Vector2) { if (this is Electric) wireEmission[pointToBlockBoxIndex(x, y)] = emission else throw IllegalStateException("Fixture is not instance of Electric") }
|
||||
fun setWireConsumptionAt(x: Int, y: Int, consumption: Vector2) { if (this is Electric) wireConsumption[pointToBlockBoxIndex(x, y)] = consumption else throw IllegalStateException("Fixture is not instance of Electric") }
|
||||
|
||||
var blockBoxProps: BlockBoxProps = BlockBoxProps(0)
|
||||
@Transient var nameFun: () -> String = { "" }
|
||||
@Transient var mainUI: UICanvas? = null
|
||||
@@ -66,7 +146,8 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
||||
|
||||
protected var actorThatInstalledThisFixture: UUID? = null
|
||||
|
||||
private constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null)
|
||||
protected constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null)
|
||||
protected constructor(renderOrder: RenderOrder, physProp: PhysProperties, id: ActorID?) : super(renderOrder, physProp, id)
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,13 +7,7 @@ import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import org.dyn4j.geometry.Vector2
|
||||
|
||||
class FixtureLogicSignalEmitter : FixtureBase, Electric {
|
||||
|
||||
@Transient override val wireEmitterTypes: java.util.HashMap<BlockBoxIndex, WireEmissionType> = java.util.HashMap()
|
||||
@Transient override val wireSinkTypes: java.util.HashMap<BlockBoxIndex, WireEmissionType> = java.util.HashMap()
|
||||
@Transient override val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
@Transient override val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
|
||||
class FixtureLogicSignalEmitter : Electric {
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 1, 1),
|
||||
@@ -31,17 +25,11 @@ class FixtureLogicSignalEmitter : FixtureBase, Electric {
|
||||
}
|
||||
|
||||
actorValue[AVKey.BASEMASS] = MASS
|
||||
|
||||
|
||||
setWireEmitterAt(0, 0, "digital_bit")
|
||||
setWireEmissionAt(0, 0, Vector2(1.0, 0.0))
|
||||
}
|
||||
|
||||
override fun update(delta: Float) {
|
||||
// the values does not get preserved on save reload??
|
||||
|
||||
super.update(delta)
|
||||
}
|
||||
|
||||
override fun dispose() { }
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package net.torvald.terrarum.modulebasegame.gameactors
|
||||
|
||||
import net.torvald.terrarum.INGAME
|
||||
import net.torvald.terrarum.WireCodex
|
||||
import net.torvald.terrarum.gameactors.AVKey
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory.Companion.CAPACITY_MODE_WEIGHT
|
||||
@@ -12,13 +14,7 @@ import java.util.HashMap
|
||||
/**
|
||||
* Created by minjaesong on 2023-05-28.
|
||||
*/
|
||||
class FixtureWorldPortal : FixtureBase, Electric {
|
||||
|
||||
@Transient override val wireEmitterTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
||||
@Transient override val wireSinkTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
||||
@Transient override val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
@Transient override val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||
|
||||
class FixtureWorldPortal : Electric {
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 5, 2),
|
||||
@@ -48,14 +44,6 @@ class FixtureWorldPortal : FixtureBase, Electric {
|
||||
setWireSinkAt(2, 1, "digital_bit")
|
||||
}
|
||||
|
||||
override fun update(delta: Float) {
|
||||
super.update(delta)
|
||||
}
|
||||
|
||||
override fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {
|
||||
println("[FixtureWorldPortal] updateOnWireGraphTraversal! ($offsetX, $offsetY, $sinkType)")
|
||||
}
|
||||
|
||||
override fun onRisingEdge(readFrom: BlockBoxIndex) {
|
||||
println("[FixtureWorldPortal] teleport! ($readFrom)")
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class WireGraphDebugger(originalID: ItemID) : GameItem(originalID) {
|
||||
val wireName = WireCodex[itemID].nameKey
|
||||
|
||||
val emit = simCell.emt
|
||||
val recv = simCell.rcv
|
||||
val recv = simCell.rcp
|
||||
|
||||
sb.append("$connexionIcon $wireName")
|
||||
sb.append("\nE: $emit")
|
||||
|
||||
Reference in New Issue
Block a user