diff --git a/src/net/torvald/random/XXHash32.java b/src/net/torvald/random/XXHash32.java index 668156477..70e989e17 100644 --- a/src/net/torvald/random/XXHash32.java +++ b/src/net/torvald/random/XXHash32.java @@ -18,7 +18,7 @@ public class XXHash32 { public static int hashGeoCoord(int x, int y) { int p = ((x & 65535) << 16) | (y & 65535); - return hash(new byte[]{(byte) p, (byte)(p >>> 8), (byte)(p >>> 16), (byte)(p >>> 24)}, 10000); + return hash(new byte[]{(byte) p, (byte)(p >>> 8), (byte)(p >>> 16), (byte)(p >>> 24)}, x ^ y); } public static int hash(byte[] data, int seed) { diff --git a/src/net/torvald/terrarum/IngameInstance.kt b/src/net/torvald/terrarum/IngameInstance.kt index c3fad8b82..82a069309 100644 --- a/src/net/torvald/terrarum/IngameInstance.kt +++ b/src/net/torvald/terrarum/IngameInstance.kt @@ -7,6 +7,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.ActorID import net.torvald.terrarum.gameactors.ActorWithBody +import net.torvald.terrarum.gameactors.ActorWithBody.Companion.PHYS_EPSILON_DIST import net.torvald.terrarum.gameactors.BlockMarkerActor import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent import net.torvald.terrarum.gameitems.ItemID @@ -49,8 +50,8 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo override fun getMax(axis: Int, t: ActorWithBody): Double = when (axis) { - 0 -> t.hitbox.endX - 1 -> t.hitbox.endY + 0 -> t.hitbox.endX - PHYS_EPSILON_DIST + 1 -> t.hitbox.endY - PHYS_EPSILON_DIST else -> throw IllegalArgumentException("nonexistent axis $axis for ${dimensions}-dimensional object") } } @@ -449,7 +450,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo val dist2 = (p.getOrd(0) - (t.hitbox.centeredX - world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr() val dist3 = (p.getOrd(0) - (t.hitbox.centeredX + world.width * TILE_SIZE)).sqr() + (p.getOrd(1) - t.hitbox.centeredY).sqr() - minOf(dist1, minOf(dist2, dist3)) + minOf(dist1, dist2, dist3) } /** @@ -467,7 +468,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo fun getActorsAt(worldX: Double, worldY: Double): List { val outList = ArrayList() try { - actorsRTree.find(worldX, worldY, worldX + 1.0, worldY + 1.0, outList) + actorsRTree.find(worldX, worldY, worldX, worldY, outList) } catch (e: NullPointerException) {} return outList diff --git a/src/net/torvald/terrarum/Point2d.kt b/src/net/torvald/terrarum/Point2d.kt index 5642e794e..f3274283e 100644 --- a/src/net/torvald/terrarum/Point2d.kt +++ b/src/net/torvald/terrarum/Point2d.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum +import net.torvald.random.XXHash32 import org.dyn4j.geometry.Vector2 /** @@ -115,6 +116,10 @@ class Point2i() { return this } + override fun hashCode(): Int = XXHash32.hashGeoCoord(x, y) + + override fun toString() = "Point2i($x, $y)" + operator fun component1() = x operator fun component2() = y } diff --git a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt index a80174330..5c15c934c 100644 --- a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt +++ b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt @@ -3,6 +3,7 @@ package net.torvald.terrarum.gameworld import com.badlogic.gdx.utils.Queue import net.torvald.terrarum.* import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE +import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Fluid import net.torvald.terrarum.gameactors.ActorWithBody @@ -476,6 +477,7 @@ object WorldSimulator { private val wireSimMarked = HashSet() private val wireSimPoints = Queue() private val oldTraversedNodes = ArrayList() + private val fixtureCache = HashMap>() // also instance of Electric private fun simulateWires(delta: Float) { // unset old wires before we begin @@ -484,11 +486,12 @@ object WorldSimulator { } oldTraversedNodes.clear() + fixtureCache.clear() wiresimGetSourceBlocks().let { sources -> // signal-emitting fixtures must set emitState of its own tiles via update() sources.forEach { - (it as Electric).wireEmitterTypes.forEach { wireType, bbi -> + (it as Electric).wireEmitterTypes.forEach { bbi, wireType -> val startingPoint = it.worldBlockPos!! + it.blockBoxIndexToPoint2i(bbi) val signal = (it as Electric).wireEmission[bbi] ?: Vector2(0.0, 0.0) @@ -506,6 +509,8 @@ object WorldSimulator { private fun traverseWireGraph(world: GameWorld, wire: ItemID, startingPoint: WireGraphCursor, signal: Vector2) { + val emissionType = WireCodex[wire].accepts + fun getAdjacent(cnx: Int, point: WireGraphCursor): List { val r = ArrayList() for (dir in intArrayOf(RIGHT, DOWN, LEFT, UP)) { @@ -540,6 +545,29 @@ object WorldSimulator { enq(x) } } + + // do something with the power receiver + val tilePoint = Point2i(point.x, point.y) + var fixture = fixtureCache[tilePoint] + var tileOffsetFromFixture: Point2i? = null + if (fixture == null) { + INGAME.getActorsAt(point.x * TILE_SIZED, point.y * TILE_SIZED).filterIsInstance().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 + +// println("$tilePoint; ${found.javaClass.canonicalName}, $tileOffsetFromFixture, ${found.getWireSinkAt(tileOffsetFromFixture!!)}") + + if (found.getWireSinkAt(tileOffsetFromFixture!!) == emissionType) { + fixtureCache[tilePoint] = foundFixture to emissionType + fixture = foundFixture to emissionType + } + } + } + } + (fixture?.first as? Electric)?.updateOnWireGraphTraversal(tileOffsetFromFixture!!.x, tileOffsetFromFixture!!.y, fixture!!.second) + } } } diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt index f47081e55..eb045670e 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt @@ -14,11 +14,20 @@ import org.dyn4j.geometry.Vector2 import java.util.* typealias BlockBoxIndex = Int +typealias WireEmissionType = String interface Electric { - val wireEmitterTypes: HashMap + val wireEmitterTypes: HashMap + val wireSinkTypes: HashMap val wireEmission: HashMap val wireConsumption: HashMap + + fun onRisingEdge(readFrom: BlockBoxIndex) {} + fun onFallingEdge(readFrom: BlockBoxIndex) {} + fun onSignalHigh(readFrom: BlockBoxIndex, highThreshold: Double = 0.9) {} + fun onSignalLow(readFrom: BlockBoxIndex, lowThreshold: Double = 0.1) {} + + fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {} } /** @@ -35,7 +44,21 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { protected set lateinit var blockBox: BlockBox // something like TapestryObject will want to redefine this + fun blockBoxIndexToPoint2i(it: BlockBoxIndex): Point2i = this.blockBox.width.let { w -> Point2i(it % w, it / w) } + 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 diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalEmitter.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalEmitter.kt index da7b72dab..c3dc9c3d6 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalEmitter.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalEmitter.kt @@ -1,9 +1,5 @@ package net.torvald.terrarum.modulebasegame.gameactors -import com.badlogic.gdx.graphics.Texture -import com.badlogic.gdx.graphics.g2d.TextureRegion -import net.torvald.terrarum.CommonResourcePool -import net.torvald.terrarum.ModMgr import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.langpack.Lang @@ -13,9 +9,10 @@ import org.dyn4j.geometry.Vector2 class FixtureLogicSignalEmitter : FixtureBase, Electric { - override val wireEmitterTypes: HashMap = HashMap() - override val wireEmission: HashMap = HashMap() - override val wireConsumption: HashMap = HashMap() + @Transient override val wireEmitterTypes: java.util.HashMap = java.util.HashMap() + @Transient override val wireSinkTypes: java.util.HashMap = java.util.HashMap() + @Transient override val wireEmission: HashMap = HashMap() + @Transient override val wireConsumption: HashMap = HashMap() constructor() : super( @@ -34,12 +31,13 @@ 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?? - wireEmitterTypes["digital_bit"] = 0 - wireEmission[0] = Vector2(1.0, 0.0) super.update(delta) } diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureWorldPortal.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureWorldPortal.kt index 9e81f9bb0..b537850dd 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureWorldPortal.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureWorldPortal.kt @@ -6,11 +6,19 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory.Companion import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase import net.torvald.terrarum.modulebasegame.ui.UIWorldPortal import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack +import org.dyn4j.geometry.Vector2 +import java.util.HashMap /** * Created by minjaesong on 2023-05-28. */ -class FixtureWorldPortal : FixtureBase { +class FixtureWorldPortal : FixtureBase, Electric { + + @Transient override val wireEmitterTypes: HashMap = HashMap() + @Transient override val wireSinkTypes: HashMap = HashMap() + @Transient override val wireEmission: HashMap = HashMap() + @Transient override val wireConsumption: HashMap = HashMap() + constructor() : super( BlockBox(BlockBox.NO_COLLISION, 5, 2), @@ -36,6 +44,20 @@ class FixtureWorldPortal : FixtureBase { } actorValue[AVKey.BASEMASS] = FixtureLogicSignalEmitter.MASS + + 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)") } override fun reload() { @@ -43,4 +65,5 @@ class FixtureWorldPortal : FixtureBase { // TODO do something with (mainUI as UIWorldPortal).*** } + } \ No newline at end of file