From 6891d6b840c492b074a618c3063c68acf95181d3 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Tue, 3 Aug 2021 16:27:36 +0900 Subject: [PATCH] building wire graph PER TILE --- .../torvald/terrarum/gameactors/WireActor.kt | 12 ++--- .../torvald/terrarum/gameworld/GameWorld.kt | 54 +++++++++++++++++-- .../terrarum/modulebasegame/TerrarumIngame.kt | 8 +-- 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/net/torvald/terrarum/gameactors/WireActor.kt b/src/net/torvald/terrarum/gameactors/WireActor.kt index 82f6b6ed8..4033d7d22 100644 --- a/src/net/torvald/terrarum/gameactors/WireActor.kt +++ b/src/net/torvald/terrarum/gameactors/WireActor.kt @@ -16,10 +16,10 @@ import net.torvald.terrarum.gameworld.GameWorld class WireActor(id: ActorID) : ActorWithBody(RenderOrder.WIRES, PhysProperties.IMMOBILE) { companion object { - private val nearbyArr = arrayOf( - (-1 to 0), // tileL - (0 to +1), // tileB + val WIRE_NEARBY = arrayOf( (+1 to 0), // tileR + (0 to +1), // tileB + (-1 to 0), // tileL (0 to -1) // tileT ) } @@ -60,9 +60,9 @@ class WireActor(id: ActorID) : ActorWithBody(RenderOrder.WIRES, PhysProperties.I val nearbyTiles = getNearbyTilesPos(worldX, worldY).map { world.getAllWiresFrom(it.x, it.y) } var ret = 0 - for (i in nearbyTiles.indices) { + for (i in 0..3) { if (nearbyTiles[i]?.contains(itemID) == true) { - ret += (1 shl i) // add 1, 2, 4, 8 for i = 0, 1, 2, 3 + ret = ret or (1 shl i) // add 1, 2, 4, 8 for i = 0, 1, 2, 3 } } sprite!!.currentFrame = ret @@ -73,7 +73,7 @@ class WireActor(id: ActorID) : ActorWithBody(RenderOrder.WIRES, PhysProperties.I Point2i(x + 1, y), Point2i(x, y - 1), Point2i(x - 1, y), - Point2i(x, y + 1) + Point2i(x, y + 1) // don't know why but it doesn't work if I don't flip Y ) } diff --git a/src/net/torvald/terrarum/gameworld/GameWorld.kt b/src/net/torvald/terrarum/gameworld/GameWorld.kt index 5f674aad9..5f9bb4b06 100644 --- a/src/net/torvald/terrarum/gameworld/GameWorld.kt +++ b/src/net/torvald/terrarum/gameworld/GameWorld.kt @@ -3,21 +3,21 @@ package net.torvald.terrarum.gameworld import com.badlogic.gdx.utils.Disposable import net.torvald.gdx.graphics.Cvec -import net.torvald.terrarum.AppLoader +import net.torvald.terrarum.* import net.torvald.terrarum.AppLoader.printdbg -import net.torvald.terrarum.ReferencingRanges -import net.torvald.terrarum.Terrarum import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.Fluid +import net.torvald.terrarum.gameactors.WireActor import net.torvald.terrarum.gameitem.ItemID import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator -import net.torvald.terrarum.printStackTrace import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.serialise.ReadLayerDataZip import net.torvald.terrarum.worlddrawer.CreateTileAtlas import net.torvald.util.SortedArrayList import org.dyn4j.geometry.Vector2 +import kotlin.experimental.and +import kotlin.experimental.or import kotlin.math.absoluteValue import kotlin.math.sign @@ -79,6 +79,9 @@ open class GameWorld : Disposable { @TEMzPayload("WiNt", TEMzPayload.EXTERNAL_JSON) private val wirings: HashMap + private val wiringGraph = HashMap>() + private val WIRE_POS_MAP = byteArrayOf(1,2,4,8) + /** * Used by the renderer. When wirings are updated, `wirings` and this properties must be synchronised. */ @@ -325,11 +328,54 @@ open class GameWorld : Disposable { if (!bypassEvent) Terrarum.ingame?.queueWireChangedEvent(tile, false, LandUtil.getBlockAddr(this, x, y)) + + + // figure out wiring graphs + val matchingNeighbours = WireActor.WIRE_NEARBY.mapIndexed { index, (tx, ty) -> + (getAllWiresFrom(x + tx, y + ty)?.contains(tile) == true).toInt() shl index + }.sum().toByte() + // setup graph of mine + setWireGraphOfUnsafe(blockAddr, tile, matchingNeighbours) + // setup graph for neighbours + for (i in 0.toByte() .. 3.toByte()) { + if (matchingNeighbours and WIRE_POS_MAP[i] > 0) { + val (tx, ty) = WireActor.WIRE_NEARBY[i] + val old = getWireGraphOf(x + tx, y + ty, tile) ?: 0 + setWireGraphOf(x + tx, y + ty, tile, old or WIRE_POS_MAP[i]) + } + } + } + + fun getWireGraphOf(x: Int, y: Int, itemID: ItemID): Byte? { + val (x, y) = coerceXY(x, y) + val blockAddr = LandUtil.getBlockAddr(this, x, y) + return getWireGraphUnsafe(blockAddr, itemID) + } + + fun getWireGraphUnsafe(blockAddr: BlockAddress, itemID: ItemID): Byte? { + return wiringGraph[blockAddr]?.get(itemID) + } + + fun setWireGraphOf(x: Int, y: Int, itemID: ItemID, byte: Byte) { + val (x, y) = coerceXY(x, y) + val blockAddr = LandUtil.getBlockAddr(this, x, y) + return setWireGraphOfUnsafe(blockAddr, itemID, byte) + } + + fun setWireGraphOfUnsafe(blockAddr: BlockAddress, itemID: ItemID, byte: Byte) { + if (wiringGraph[blockAddr] == null) + wiringGraph[blockAddr] = HashMap() + + wiringGraph[blockAddr]!![itemID] = byte } fun getAllWiresFrom(x: Int, y: Int): SortedArrayList? { val (x, y) = coerceXY(x, y) val blockAddr = LandUtil.getBlockAddr(this, x, y) + return getAllWiresFrom(blockAddr) + } + + fun getAllWiresFrom(blockAddr: BlockAddress): SortedArrayList? { return wirings[blockAddr]?.wires } diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index ce4f92be8..98023115d 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -910,7 +910,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { if (actor.referenceID == theRealGamer.referenceID || actor.referenceID == 0x51621D) // do not delete this magic throw RuntimeException("Attempted to remove player.") - val indexToDelete = actorContainerActive.searchForIndex(actor.referenceID) { it.referenceID!! } + val indexToDelete = actorContainerActive.searchForIndex(actor.referenceID) { it.referenceID } if (indexToDelete != null) { printdbg(this, "Removing actor $actor") printStackTrace(this) @@ -978,8 +978,10 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { throw Error("The actor $actor already exists in the game") } else { - printdbg(this, "Adding actor $actor") - printStackTrace(this) + if (actor.referenceID < ReferencingRanges.ACTORS_WIRES.first) { + printdbg(this, "Adding actor $actor") + printStackTrace(this) + } actorContainerActive.add(actor)