mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
wiresim: signal sinking actors are only getting updated when the sim calls for
This commit is contained in:
@@ -18,7 +18,7 @@ public class XXHash32 {
|
|||||||
|
|
||||||
public static int hashGeoCoord(int x, int y) {
|
public static int hashGeoCoord(int x, int y) {
|
||||||
int p = ((x & 65535) << 16) | (y & 65535);
|
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) {
|
public static int hash(byte[] data, int seed) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
|||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameactors.ActorID
|
import net.torvald.terrarum.gameactors.ActorID
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
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.gameactors.BlockMarkerActor
|
||||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
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 =
|
override fun getMax(axis: Int, t: ActorWithBody): Double =
|
||||||
when (axis) {
|
when (axis) {
|
||||||
0 -> t.hitbox.endX
|
0 -> t.hitbox.endX - PHYS_EPSILON_DIST
|
||||||
1 -> t.hitbox.endY
|
1 -> t.hitbox.endY - PHYS_EPSILON_DIST
|
||||||
else -> throw IllegalArgumentException("nonexistent axis $axis for ${dimensions}-dimensional object")
|
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 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()
|
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<ActorWithBody> {
|
fun getActorsAt(worldX: Double, worldY: Double): List<ActorWithBody> {
|
||||||
val outList = ArrayList<ActorWithBody>()
|
val outList = ArrayList<ActorWithBody>()
|
||||||
try {
|
try {
|
||||||
actorsRTree.find(worldX, worldY, worldX + 1.0, worldY + 1.0, outList)
|
actorsRTree.find(worldX, worldY, worldX, worldY, outList)
|
||||||
}
|
}
|
||||||
catch (e: NullPointerException) {}
|
catch (e: NullPointerException) {}
|
||||||
return outList
|
return outList
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.torvald.terrarum
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import net.torvald.random.XXHash32
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,6 +116,10 @@ class Point2i() {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int = XXHash32.hashGeoCoord(x, y)
|
||||||
|
|
||||||
|
override fun toString() = "Point2i($x, $y)"
|
||||||
|
|
||||||
operator fun component1() = x
|
operator fun component1() = x
|
||||||
operator fun component2() = y
|
operator fun component2() = y
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package net.torvald.terrarum.gameworld
|
|||||||
import com.badlogic.gdx.utils.Queue
|
import com.badlogic.gdx.utils.Queue
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
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.Block
|
||||||
import net.torvald.terrarum.blockproperties.Fluid
|
import net.torvald.terrarum.blockproperties.Fluid
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
@@ -476,6 +477,7 @@ object WorldSimulator {
|
|||||||
private val wireSimMarked = HashSet<Long>()
|
private val wireSimMarked = HashSet<Long>()
|
||||||
private val wireSimPoints = Queue<WireGraphCursor>()
|
private val wireSimPoints = Queue<WireGraphCursor>()
|
||||||
private val oldTraversedNodes = ArrayList<WireGraphCursor>()
|
private val oldTraversedNodes = ArrayList<WireGraphCursor>()
|
||||||
|
private val fixtureCache = HashMap<Point2i, Pair<FixtureBase, WireEmissionType>>() // also instance of Electric
|
||||||
|
|
||||||
private fun simulateWires(delta: Float) {
|
private fun simulateWires(delta: Float) {
|
||||||
// unset old wires before we begin
|
// unset old wires before we begin
|
||||||
@@ -484,11 +486,12 @@ object WorldSimulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oldTraversedNodes.clear()
|
oldTraversedNodes.clear()
|
||||||
|
fixtureCache.clear()
|
||||||
|
|
||||||
wiresimGetSourceBlocks().let { sources ->
|
wiresimGetSourceBlocks().let { sources ->
|
||||||
// signal-emitting fixtures must set emitState of its own tiles via update()
|
// signal-emitting fixtures must set emitState of its own tiles via update()
|
||||||
sources.forEach {
|
sources.forEach {
|
||||||
(it as Electric).wireEmitterTypes.forEach { wireType, bbi ->
|
(it as Electric).wireEmitterTypes.forEach { bbi, wireType ->
|
||||||
|
|
||||||
val startingPoint = it.worldBlockPos!! + it.blockBoxIndexToPoint2i(bbi)
|
val startingPoint = it.worldBlockPos!! + it.blockBoxIndexToPoint2i(bbi)
|
||||||
val signal = (it as Electric).wireEmission[bbi] ?: Vector2(0.0, 0.0)
|
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) {
|
private fun traverseWireGraph(world: GameWorld, wire: ItemID, startingPoint: WireGraphCursor, signal: Vector2) {
|
||||||
|
|
||||||
|
val emissionType = WireCodex[wire].accepts
|
||||||
|
|
||||||
fun getAdjacent(cnx: Int, point: WireGraphCursor): List<WireGraphCursor> {
|
fun getAdjacent(cnx: Int, point: WireGraphCursor): List<WireGraphCursor> {
|
||||||
val r = ArrayList<WireGraphCursor>()
|
val r = ArrayList<WireGraphCursor>()
|
||||||
for (dir in intArrayOf(RIGHT, DOWN, LEFT, UP)) {
|
for (dir in intArrayOf(RIGHT, DOWN, LEFT, UP)) {
|
||||||
@@ -540,6 +545,29 @@ object WorldSimulator {
|
|||||||
enq(x)
|
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<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
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,20 @@ import org.dyn4j.geometry.Vector2
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
typealias BlockBoxIndex = Int
|
typealias BlockBoxIndex = Int
|
||||||
|
typealias WireEmissionType = String
|
||||||
|
|
||||||
interface Electric {
|
interface Electric {
|
||||||
val wireEmitterTypes: HashMap<String, BlockBoxIndex>
|
val wireEmitterTypes: HashMap<BlockBoxIndex, WireEmissionType>
|
||||||
|
val wireSinkTypes: HashMap<BlockBoxIndex, WireEmissionType>
|
||||||
val wireEmission: HashMap<BlockBoxIndex, Vector2>
|
val wireEmission: HashMap<BlockBoxIndex, Vector2>
|
||||||
val wireConsumption: HashMap<BlockBoxIndex, Vector2>
|
val wireConsumption: HashMap<BlockBoxIndex, Vector2>
|
||||||
|
|
||||||
|
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
|
protected set
|
||||||
|
|
||||||
lateinit var blockBox: BlockBox // something like TapestryObject will want to redefine this
|
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 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)
|
var blockBoxProps: BlockBoxProps = BlockBoxProps(0)
|
||||||
@Transient var nameFun: () -> String = { "" }
|
@Transient var nameFun: () -> String = { "" }
|
||||||
@Transient var mainUI: UICanvas? = null
|
@Transient var mainUI: UICanvas? = null
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.gameactors
|
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.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
@@ -13,9 +9,10 @@ import org.dyn4j.geometry.Vector2
|
|||||||
|
|
||||||
class FixtureLogicSignalEmitter : FixtureBase, Electric {
|
class FixtureLogicSignalEmitter : FixtureBase, Electric {
|
||||||
|
|
||||||
override val wireEmitterTypes: HashMap<String, BlockBoxIndex> = HashMap()
|
@Transient override val wireEmitterTypes: java.util.HashMap<BlockBoxIndex, WireEmissionType> = java.util.HashMap()
|
||||||
override val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
@Transient override val wireSinkTypes: java.util.HashMap<BlockBoxIndex, WireEmissionType> = java.util.HashMap()
|
||||||
override val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
@Transient override val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||||
|
@Transient override val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||||
|
|
||||||
|
|
||||||
constructor() : super(
|
constructor() : super(
|
||||||
@@ -34,12 +31,13 @@ class FixtureLogicSignalEmitter : FixtureBase, Electric {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actorValue[AVKey.BASEMASS] = MASS
|
actorValue[AVKey.BASEMASS] = MASS
|
||||||
|
|
||||||
|
setWireEmitterAt(0, 0, "digital_bit")
|
||||||
|
setWireEmissionAt(0, 0, Vector2(1.0, 0.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(delta: Float) {
|
override fun update(delta: Float) {
|
||||||
// the values does not get preserved on save reload??
|
// the values does not get preserved on save reload??
|
||||||
wireEmitterTypes["digital_bit"] = 0
|
|
||||||
wireEmission[0] = Vector2(1.0, 0.0)
|
|
||||||
|
|
||||||
super.update(delta)
|
super.update(delta)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,19 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory.Companion
|
|||||||
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIWorldPortal
|
import net.torvald.terrarum.modulebasegame.ui.UIWorldPortal
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import org.dyn4j.geometry.Vector2
|
||||||
|
import java.util.HashMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-05-28.
|
* Created by minjaesong on 2023-05-28.
|
||||||
*/
|
*/
|
||||||
class FixtureWorldPortal : FixtureBase {
|
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()
|
||||||
|
|
||||||
|
|
||||||
constructor() : super(
|
constructor() : super(
|
||||||
BlockBox(BlockBox.NO_COLLISION, 5, 2),
|
BlockBox(BlockBox.NO_COLLISION, 5, 2),
|
||||||
@@ -36,6 +44,20 @@ class FixtureWorldPortal : FixtureBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actorValue[AVKey.BASEMASS] = FixtureLogicSignalEmitter.MASS
|
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() {
|
override fun reload() {
|
||||||
@@ -43,4 +65,5 @@ class FixtureWorldPortal : FixtureBase {
|
|||||||
|
|
||||||
// TODO do something with (mainUI as UIWorldPortal).***
|
// TODO do something with (mainUI as UIWorldPortal).***
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user