mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 19:14:05 +09:00
wire branching traversal itself works, but fetches wrong signal status
This commit is contained in:
@@ -71,9 +71,9 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
val actorContainerInactive = SortedArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
val actorContainerInactive = SortedArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
|
||||||
|
|
||||||
// FIXME queues will not work; input processing (blocks will queue) and queue consuming cannot be synchronised
|
// FIXME queues will not work; input processing (blocks will queue) and queue consuming cannot be synchronised
|
||||||
protected val terrainChangeQueue = ArrayList<BlockChangeQueueItem>()
|
//protected val terrainChangeQueue = ArrayList<BlockChangeQueueItem>()
|
||||||
protected val wallChangeQueue = ArrayList<BlockChangeQueueItem>()
|
//protected val wallChangeQueue = ArrayList<BlockChangeQueueItem>()
|
||||||
protected val wireChangeQueue = ArrayList<BlockChangeQueueItem>() // if 'old' is set and 'new' is blank, it's a wire cutter
|
//protected val wireChangeQueue = ArrayList<BlockChangeQueueItem>() // if 'old' is set and 'new' is blank, it's a wire cutter
|
||||||
|
|
||||||
override fun hide() {
|
override fun hide() {
|
||||||
}
|
}
|
||||||
@@ -153,15 +153,14 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
* Queueing schema is used to make sure things are synchronised.
|
* Queueing schema is used to make sure things are synchronised.
|
||||||
*/
|
*/
|
||||||
open fun queueTerrainChangedEvent(old: ItemID, new: ItemID, x: Int, y: Int) {
|
open fun queueTerrainChangedEvent(old: ItemID, new: ItemID, x: Int, y: Int) {
|
||||||
printdbg(this, "Terrain change enqueued: ${BlockChangeQueueItem(old, new, x, y)}")
|
//printdbg(this, terrainChangeQueue)
|
||||||
printdbg(this, terrainChangeQueue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wall version of terrainChanged() event
|
* Wall version of terrainChanged() event
|
||||||
*/
|
*/
|
||||||
open fun queueWallChangedEvent(old: ItemID, new: ItemID, x: Int, y: Int) {
|
open fun queueWallChangedEvent(old: ItemID, new: ItemID, x: Int, y: Int) {
|
||||||
wallChangeQueue.add(BlockChangeQueueItem(old, new, x, y))
|
//wallChangeQueue.add(BlockChangeQueueItem(old, new, x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,7 +170,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
* @param new current settings of conduits in bit set format.
|
* @param new current settings of conduits in bit set format.
|
||||||
*/
|
*/
|
||||||
open fun queueWireChangedEvent(wire: ItemID, isRemoval: Boolean, x: Int, y: Int) {
|
open fun queueWireChangedEvent(wire: ItemID, isRemoval: Boolean, x: Int, y: Int) {
|
||||||
wireChangeQueue.add(BlockChangeQueueItem(if (isRemoval) wire else "", if (isRemoval) "" else wire, x, y))
|
//wireChangeQueue.add(BlockChangeQueueItem(if (isRemoval) wire else "", if (isRemoval) "" else wire, x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
|||||||
import net.torvald.terrarum.modulebasegame.gameactors.BlockBoxIndex
|
import net.torvald.terrarum.modulebasegame.gameactors.BlockBoxIndex
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.Electric
|
import net.torvald.terrarum.modulebasegame.gameactors.Electric
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||||
|
import net.torvald.util.IntArrayStack
|
||||||
|
import org.dyn4j.geometry.Vector2
|
||||||
import org.khelekore.prtree.*
|
import org.khelekore.prtree.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
@@ -200,44 +202,38 @@ object WorldSimulator {
|
|||||||
// displace fallables (TODO implement blocks with fallable supports e.g. scaffolding)
|
// displace fallables (TODO implement blocks with fallable supports e.g. scaffolding)
|
||||||
// only displace SINGLE BOTTOMMOST block on single X-coord (this doesn't mean they must fall only one block)
|
// only displace SINGLE BOTTOMMOST block on single X-coord (this doesn't mean they must fall only one block)
|
||||||
// so that the "falling" should be visible to the end user
|
// so that the "falling" should be visible to the end user
|
||||||
if (!DEBUG_STEPPING_MODE || DEBUG_STEPPING_MODE && KeyToggler.isOn (Input.Keys.PERIOD)) {
|
for (x in updateXFrom..updateXTo) {
|
||||||
for (x in updateXFrom..updateXTo) {
|
var fallDownCounter = 0
|
||||||
var fallDownCounter = 0
|
var fallableStackProcessed = false
|
||||||
var fallableStackProcessed = false
|
// one "stack" is a contiguous fallable blocks, regardless of the actual block number
|
||||||
// one "stack" is a contiguous fallable blocks, regardless of the actual block number
|
// when you are simulating the gradual falling, it is natural to process all the "stacks" at the same run,
|
||||||
// when you are simulating the gradual falling, it is natural to process all the "stacks" at the same run,
|
// otherwise you'll get an artefact.
|
||||||
// otherwise you'll get an artefact.
|
for (y in updateYTo downTo updateYFrom) {
|
||||||
for (y in updateYTo downTo updateYFrom) {
|
val currentTile = world.getTileFromTerrain(x, y)
|
||||||
val currentTile = world.getTileFromTerrain(x, y)
|
val prop = BlockCodex[currentTile]
|
||||||
val prop = BlockCodex[currentTile]
|
val isAir = currentTile == Block.AIR
|
||||||
val isAir = currentTile == Block.AIR
|
val support = prop.maxSupport
|
||||||
val support = prop.maxSupport
|
val isFallable = support != -1
|
||||||
val isFallable = support != -1
|
|
||||||
|
|
||||||
// mark the beginnig of the new "stack"
|
// mark the beginnig of the new "stack"
|
||||||
if (fallableStackProcessed && !isFallable) {
|
if (fallableStackProcessed && !isFallable) {
|
||||||
fallableStackProcessed = false
|
fallableStackProcessed = false
|
||||||
} // do not chain with "else if"
|
} // do not chain with "else if"
|
||||||
|
|
||||||
// process the gradual falling of the selected "stack"
|
// process the gradual falling of the selected "stack"
|
||||||
if (!fallableStackProcessed && fallDownCounter != 0 && isFallable) {
|
if (!fallableStackProcessed && fallDownCounter != 0 && isFallable) {
|
||||||
// replace blocks
|
// replace blocks
|
||||||
world.setTileTerrain(x, y, Block.AIR, true)
|
world.setTileTerrain(x, y, Block.AIR, true)
|
||||||
world.setTileTerrain(x, y + fallDownCounter, currentTile, true)
|
world.setTileTerrain(x, y + fallDownCounter, currentTile, true)
|
||||||
|
|
||||||
fallableStackProcessed = true
|
fallableStackProcessed = true
|
||||||
}
|
}
|
||||||
else if (!isAir) {
|
else if (!isAir) {
|
||||||
fallDownCounter = 0
|
fallDownCounter = 0
|
||||||
}
|
}
|
||||||
else if (!isFallable && fallDownCounter < FALLABLE_MAX_FALL_SPEED) {
|
else if (!isFallable && fallDownCounter < FALLABLE_MAX_FALL_SPEED) {
|
||||||
fallDownCounter += 1
|
fallDownCounter += 1
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG_STEPPING_MODE) {
|
|
||||||
KeyToggler.forceSet(Input.Keys.PERIOD, false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,9 +487,14 @@ object WorldSimulator {
|
|||||||
var terminate = false
|
var terminate = false
|
||||||
|
|
||||||
fun dequeue() {
|
fun dequeue() {
|
||||||
|
//printdbg(this, "points before deq: $points")
|
||||||
points.removeAt(0)
|
points.removeAt(0)
|
||||||
|
//printdbg(this, "points after deq: $points")
|
||||||
if (points.size == 0) terminate = true
|
if (points.size == 0) terminate = true
|
||||||
else point = points[0]
|
else {
|
||||||
|
point = points[0]
|
||||||
|
//printdbg(this, "new point: $point")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
points.add(point.copy())
|
points.add(point.copy())
|
||||||
@@ -510,7 +511,7 @@ object WorldSimulator {
|
|||||||
|
|
||||||
world.getAllWiringGraph(point.x, point.y)?.get(wire)?.let { node ->
|
world.getAllWiringGraph(point.x, point.y)?.get(wire)?.let { node ->
|
||||||
|
|
||||||
val signal = node.emitState
|
val signal = Vector2(1.0, 0.0)//node.emitState // FIXME branching wires somehow fetches wrong signal value
|
||||||
val cnx = node.connections.toInt() // 1-15
|
val cnx = node.connections.toInt() // 1-15
|
||||||
val nextDirBit = cnx and (15 - point.fromWhere) // cnx minus where the old cursur was; also 1-15
|
val nextDirBit = cnx and (15 - point.fromWhere) // cnx minus where the old cursur was; also 1-15
|
||||||
//printdbg(this, "(${point.x}, ${point.y}) from ${point.fromWhere} to $nextDirBit")
|
//printdbg(this, "(${point.x}, ${point.y}) from ${point.fromWhere} to $nextDirBit")
|
||||||
@@ -526,7 +527,7 @@ object WorldSimulator {
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
when (nextDirBit.bitCount()) {
|
when (nextDirBit.bitCount()) {
|
||||||
in 4..64 -> { throw IllegalArgumentException("Bad nextDirBit: $nextDirBit") }
|
in 5..64 -> { throw IllegalArgumentException("Bad nextDirBit: $nextDirBit") }
|
||||||
// nowhere to go
|
// nowhere to go
|
||||||
0 -> {
|
0 -> {
|
||||||
dequeue()
|
dequeue()
|
||||||
@@ -539,17 +540,35 @@ object WorldSimulator {
|
|||||||
// propagate the signal to next position
|
// propagate the signal to next position
|
||||||
world.setWireEmitStateOf(point.x, point.y, wire, signal)
|
world.setWireEmitStateOf(point.x, point.y, wire, signal)
|
||||||
}
|
}
|
||||||
// two or three directions to go
|
// two, three or four (starting point only) directions to go
|
||||||
else -> {
|
else -> {
|
||||||
return
|
|
||||||
|
|
||||||
// propagate the signal
|
|
||||||
|
|
||||||
// mark this branch
|
// mark this branch
|
||||||
points.add(point.copy())
|
//branchesVisited.add(point.copy())
|
||||||
|
|
||||||
// move the "cursor" by try right, down, left then up
|
// spawn and move the "cursor" by try right, down, left then up
|
||||||
|
val movableDirs = IntArrayStack(4)
|
||||||
|
for (s in 3 downTo 0) { // so that top of the stack holds lowest of the direction-number
|
||||||
|
(nextDirBit and (1 shl s)).let {
|
||||||
|
if (it != 0) movableDirs.push(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printdbg(this, movableDirs.depth) // stack size is correct..?
|
||||||
|
// take top of the stack as mine
|
||||||
|
val mine = movableDirs.pop()
|
||||||
|
|
||||||
|
while (movableDirs.isNotEmpty()) {
|
||||||
|
// obviously 'point' must not me altered beforehand
|
||||||
|
movableDirs.pop().let { dir ->
|
||||||
|
points.add(point.copy().moveOneCell(dir))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printdbg(this, points) // and points are also correct...
|
||||||
|
|
||||||
|
// finally move the cursor of mine
|
||||||
|
point.moveOneCell(mine)
|
||||||
|
|
||||||
|
// propagate the signal to next position
|
||||||
|
world.setWireEmitStateOf(point.x, point.y, wire, signal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -563,6 +582,11 @@ object WorldSimulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val RIGHT = 1
|
||||||
|
private const val DOWN = 2
|
||||||
|
private const val LEFT = 4
|
||||||
|
private const val UP = 8
|
||||||
|
|
||||||
private fun getNearbyTilesPos(x: Int, y: Int): Array<Point2i> {
|
private fun getNearbyTilesPos(x: Int, y: Int): Array<Point2i> {
|
||||||
return arrayOf(
|
return arrayOf(
|
||||||
Point2i(x + 1, y),
|
Point2i(x + 1, y),
|
||||||
@@ -580,15 +604,17 @@ object WorldSimulator {
|
|||||||
) {
|
) {
|
||||||
constructor(point2i: Point2i): this(point2i.x, point2i.y, 0, 0)
|
constructor(point2i: Point2i): this(point2i.x, point2i.y, 0, 0)
|
||||||
|
|
||||||
fun moveOneCell(dir: Int) {
|
fun moveOneCell(dir: Int): WireGraphCursor {
|
||||||
when (dir) {
|
when (dir) {
|
||||||
1 -> { x += 1; fromWhere = 4 }
|
1 -> { x += 1; fromWhere = LEFT }
|
||||||
2 -> { y += 1; fromWhere = 8 }
|
2 -> { y += 1; fromWhere = UP }
|
||||||
4 -> { x -= 1; fromWhere = 1 }
|
4 -> { x -= 1; fromWhere = RIGHT }
|
||||||
8 -> { y -= 1; fromWhere = 2 }
|
8 -> { y -= 1; fromWhere = DOWN }
|
||||||
else -> throw IllegalArgumentException("Unacceptable direction: $dir")
|
else -> throw IllegalArgumentException("Unacceptable direction: $dir")
|
||||||
}
|
}
|
||||||
len += 1
|
len += 1
|
||||||
|
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -589,6 +589,8 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
|
|
||||||
|
//hypothetical_input_capturing_function_if_you_finally_decided_to_forgo_gdx_input_processor_and_implement_your_own_to_synchronise_everything()
|
||||||
|
|
||||||
WorldSimulator.resetForThisFrame()
|
WorldSimulator.resetForThisFrame()
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
@@ -635,13 +637,12 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
// world click events (e.g. opening the UI that a fixture has) must go here
|
// world click events (e.g. opening the UI that a fixture has) must go here
|
||||||
ingameController.update(delta)
|
ingameController.update(delta)
|
||||||
|
|
||||||
if (!paused) {
|
/*if (!paused) {
|
||||||
printdbg(this, "Clear tile change queues")
|
|
||||||
// completely consume block change queues because why not
|
// completely consume block change queues because why not
|
||||||
terrainChangeQueue.clear()
|
terrainChangeQueue.clear()
|
||||||
wallChangeQueue.clear()
|
wallChangeQueue.clear()
|
||||||
wireChangeQueue.clear()
|
wireChangeQueue.clear()
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
@@ -876,13 +877,13 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it is CuedByTerrainChange) {
|
/*if (it is CuedByTerrainChange) {
|
||||||
printdbg(this, "actor is CuedByTerrainChange: ${terrainChangeQueue}")
|
printdbg(this, "actor is CuedByTerrainChange: ${terrainChangeQueue}")
|
||||||
terrainChangeQueue.forEach { cue ->
|
terrainChangeQueue.forEach { cue ->
|
||||||
printdbg(this, "Ingame actors terrainChangeCue: ${cue}")
|
printdbg(this, "Ingame actors terrainChangeCue: ${cue}")
|
||||||
it.updateForWorldChange(cue)
|
it.updateForWorldChange(cue)
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actorNowPlaying?.update(delta)
|
actorNowPlaying?.update(delta)
|
||||||
|
|||||||
@@ -145,18 +145,8 @@ open class FixtureBase(
|
|||||||
this.isVisible = false
|
this.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override fun update(delta: Float) {
|
||||||
* Fired by world's BlockChanged event (fired when blocks are placed/removed).
|
super.update(delta)
|
||||||
* The flooding check must run on every frame. use updateSelf() for that.
|
|
||||||
*
|
|
||||||
* E.g. if a fixture block that is inside of BlockBox is missing, destroy and drop self.
|
|
||||||
*/
|
|
||||||
override fun updateForWorldChange(cue: IngameInstance.BlockChangeQueueItem) {
|
|
||||||
printdbg(this, "updateForWorldChange ${nameFun()}")
|
|
||||||
// check for marker blocks.
|
|
||||||
// if at least one of them is missing, destroy all the markers and drop self as an item
|
|
||||||
|
|
||||||
// you need to implement Dropped Item first to satisfyingly implement this function
|
|
||||||
|
|
||||||
val posX = worldBlockPos!!.x
|
val posX = worldBlockPos!!.x
|
||||||
val posY = worldBlockPos!!.y
|
val posY = worldBlockPos!!.y
|
||||||
@@ -182,9 +172,10 @@ open class FixtureBase(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO drop self as an item (instance of DroppedItem)
|
// TODO drop self as an item (instance of DroppedItem)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CuedByTerrainChange {
|
interface CuedByTerrainChange {
|
||||||
@@ -194,7 +185,7 @@ interface CuedByTerrainChange {
|
|||||||
*
|
*
|
||||||
* E.g. if a fixture block that is inside of BlockBox is missing, destroy and drop self.
|
* E.g. if a fixture block that is inside of BlockBox is missing, destroy and drop self.
|
||||||
*/
|
*/
|
||||||
fun updateForWorldChange(cue: IngameInstance.BlockChangeQueueItem)
|
//fun updateForWorldChange(cue: IngameInstance.BlockChangeQueueItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ internal object BlocksDrawer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes to buffer. Actual draw code must be called after this operation.
|
* Autotiling; writes to buffer. Actual draw code must be called after this operation.
|
||||||
*
|
*
|
||||||
* @param drawModeTilesBlendMul If current drawing mode is MULTIPLY. Doesn't matter if mode is FLUID.
|
* @param drawModeTilesBlendMul If current drawing mode is MULTIPLY. Doesn't matter if mode is FLUID.
|
||||||
* @param wire coduitTypes bit that is selected to be drawn. Must be the power of two.
|
* @param wire coduitTypes bit that is selected to be drawn. Must be the power of two.
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ class IntArrayStack {
|
|||||||
|
|
||||||
private lateinit var data: IntArray
|
private lateinit var data: IntArray
|
||||||
|
|
||||||
|
fun isEmpty() = depth == 0
|
||||||
|
fun isNotEmpty() = depth > 0
|
||||||
|
|
||||||
constructor(stackSize: Int) {
|
constructor(stackSize: Int) {
|
||||||
data = IntArray(stackSize)
|
data = IntArray(stackSize)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user