diff --git a/src/net/torvald/terrarum/IngameInstance.kt b/src/net/torvald/terrarum/IngameInstance.kt index d635e6bca..e37936883 100644 --- a/src/net/torvald/terrarum/IngameInstance.kt +++ b/src/net/torvald/terrarum/IngameInstance.kt @@ -71,9 +71,9 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { val actorContainerInactive = SortedArrayList(ACTORCONTAINER_INITIAL_SIZE) // FIXME queues will not work; input processing (blocks will queue) and queue consuming cannot be synchronised - protected val terrainChangeQueue = ArrayList() - protected val wallChangeQueue = ArrayList() - protected val wireChangeQueue = ArrayList() // if 'old' is set and 'new' is blank, it's a wire cutter + //protected val terrainChangeQueue = ArrayList() + //protected val wallChangeQueue = ArrayList() + //protected val wireChangeQueue = ArrayList() // if 'old' is set and 'new' is blank, it's a wire cutter override fun hide() { } @@ -153,15 +153,14 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { * Queueing schema is used to make sure things are synchronised. */ 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 */ 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. */ 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)) } diff --git a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt index 3e1e9f461..54627d33d 100644 --- a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt +++ b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt @@ -16,6 +16,8 @@ import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.BlockBoxIndex import net.torvald.terrarum.modulebasegame.gameactors.Electric import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase +import net.torvald.util.IntArrayStack +import org.dyn4j.geometry.Vector2 import org.khelekore.prtree.* import java.util.* import kotlin.collections.ArrayList @@ -200,44 +202,38 @@ object WorldSimulator { // 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) // 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) { - var fallDownCounter = 0 - var fallableStackProcessed = false - // 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, - // otherwise you'll get an artefact. - for (y in updateYTo downTo updateYFrom) { - val currentTile = world.getTileFromTerrain(x, y) - val prop = BlockCodex[currentTile] - val isAir = currentTile == Block.AIR - val support = prop.maxSupport - val isFallable = support != -1 + for (x in updateXFrom..updateXTo) { + var fallDownCounter = 0 + var fallableStackProcessed = false + // 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, + // otherwise you'll get an artefact. + for (y in updateYTo downTo updateYFrom) { + val currentTile = world.getTileFromTerrain(x, y) + val prop = BlockCodex[currentTile] + val isAir = currentTile == Block.AIR + val support = prop.maxSupport + val isFallable = support != -1 - // mark the beginnig of the new "stack" - if (fallableStackProcessed && !isFallable) { - fallableStackProcessed = false - } // do not chain with "else if" + // mark the beginnig of the new "stack" + if (fallableStackProcessed && !isFallable) { + fallableStackProcessed = false + } // do not chain with "else if" - // process the gradual falling of the selected "stack" - if (!fallableStackProcessed && fallDownCounter != 0 && isFallable) { - // replace blocks - world.setTileTerrain(x, y, Block.AIR, true) - world.setTileTerrain(x, y + fallDownCounter, currentTile, true) + // process the gradual falling of the selected "stack" + if (!fallableStackProcessed && fallDownCounter != 0 && isFallable) { + // replace blocks + world.setTileTerrain(x, y, Block.AIR, true) + world.setTileTerrain(x, y + fallDownCounter, currentTile, true) - fallableStackProcessed = true - } - else if (!isAir) { - fallDownCounter = 0 - } - else if (!isFallable && fallDownCounter < FALLABLE_MAX_FALL_SPEED) { - fallDownCounter += 1 - } + fallableStackProcessed = true + } + else if (!isAir) { + fallDownCounter = 0 + } + else if (!isFallable && fallDownCounter < FALLABLE_MAX_FALL_SPEED) { + fallDownCounter += 1 } - } - - if (DEBUG_STEPPING_MODE) { - KeyToggler.forceSet(Input.Keys.PERIOD, false) } } @@ -491,9 +487,14 @@ object WorldSimulator { var terminate = false fun dequeue() { + //printdbg(this, "points before deq: $points") points.removeAt(0) + //printdbg(this, "points after deq: $points") if (points.size == 0) terminate = true - else point = points[0] + else { + point = points[0] + //printdbg(this, "new point: $point") + } } points.add(point.copy()) @@ -510,7 +511,7 @@ object WorldSimulator { 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 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") @@ -526,7 +527,7 @@ object WorldSimulator { else { when (nextDirBit.bitCount()) { - in 4..64 -> { throw IllegalArgumentException("Bad nextDirBit: $nextDirBit") } + in 5..64 -> { throw IllegalArgumentException("Bad nextDirBit: $nextDirBit") } // nowhere to go 0 -> { dequeue() @@ -539,17 +540,35 @@ object WorldSimulator { // propagate the signal to next position 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 -> { - return - - // propagate the signal - // 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 { return arrayOf( Point2i(x + 1, y), @@ -580,15 +604,17 @@ object WorldSimulator { ) { constructor(point2i: Point2i): this(point2i.x, point2i.y, 0, 0) - fun moveOneCell(dir: Int) { + fun moveOneCell(dir: Int): WireGraphCursor { when (dir) { - 1 -> { x += 1; fromWhere = 4 } - 2 -> { y += 1; fromWhere = 8 } - 4 -> { x -= 1; fromWhere = 1 } - 8 -> { y -= 1; fromWhere = 2 } + 1 -> { x += 1; fromWhere = LEFT } + 2 -> { y += 1; fromWhere = UP } + 4 -> { x -= 1; fromWhere = RIGHT } + 8 -> { y -= 1; fromWhere = DOWN } else -> throw IllegalArgumentException("Unacceptable direction: $dir") } len += 1 + + return this } } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index 5f5dc7284..6a9d49564 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -589,6 +589,8 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { if (!paused) { + //hypothetical_input_capturing_function_if_you_finally_decided_to_forgo_gdx_input_processor_and_implement_your_own_to_synchronise_everything() + 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 ingameController.update(delta) - if (!paused) { - printdbg(this, "Clear tile change queues") + /*if (!paused) { // completely consume block change queues because why not terrainChangeQueue.clear() wallChangeQueue.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}") terrainChangeQueue.forEach { cue -> printdbg(this, "Ingame actors terrainChangeCue: ${cue}") it.updateForWorldChange(cue) } - } + }*/ } } actorNowPlaying?.update(delta) diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt index a353512b4..f3ac42784 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt @@ -145,18 +145,8 @@ open class FixtureBase( this.isVisible = false } - /** - * Fired by world's BlockChanged event (fired when blocks are placed/removed). - * 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 + override fun update(delta: Float) { + super.update(delta) val posX = worldBlockPos!!.x val posY = worldBlockPos!!.y @@ -182,9 +172,10 @@ open class FixtureBase( } // TODO drop self as an item (instance of DroppedItem) - + } } + } 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. */ - fun updateForWorldChange(cue: IngameInstance.BlockChangeQueueItem) + //fun updateForWorldChange(cue: IngameInstance.BlockChangeQueueItem) } /** diff --git a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt index 318037d74..4bce6fec9 100644 --- a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt +++ b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt @@ -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 wire coduitTypes bit that is selected to be drawn. Must be the power of two. diff --git a/src/net/torvald/util/IntArrayStack.kt b/src/net/torvald/util/IntArrayStack.kt index 8f8349da9..294ab1ef3 100644 --- a/src/net/torvald/util/IntArrayStack.kt +++ b/src/net/torvald/util/IntArrayStack.kt @@ -18,6 +18,9 @@ class IntArrayStack { private lateinit var data: IntArray + fun isEmpty() = depth == 0 + fun isNotEmpty() = depth > 0 + constructor(stackSize: Int) { data = IntArray(stackSize) }