From daf5c026057dd23a7690714e8d4bc5c66e4ef1ab Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sat, 2 Feb 2019 01:58:49 +0900 Subject: [PATCH] #12 event for world block change -- mainly meant for fixture updating itself --- src/net/torvald/terrarum/IngameInstance.kt | 35 ++++++++++++++++++ .../torvald/terrarum/gameworld/GameWorld.kt | 13 +++++++ .../torvald/terrarum/modulebasegame/Ingame.kt | 14 ++++++++ .../modulebasegame/gameactors/FixtureBase.kt | 36 +++++++++++++++++-- 4 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/net/torvald/terrarum/IngameInstance.kt b/src/net/torvald/terrarum/IngameInstance.kt index 15ce8fb44..57d325552 100644 --- a/src/net/torvald/terrarum/IngameInstance.kt +++ b/src/net/torvald/terrarum/IngameInstance.kt @@ -2,9 +2,11 @@ package net.torvald.terrarum import com.badlogic.gdx.Screen import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.badlogic.gdx.utils.Queue import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid +import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.ui.ConsoleWindow import java.util.* import java.util.concurrent.locks.Lock @@ -45,6 +47,10 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { val actorContainer = ArrayList(ACTORCONTAINER_INITIAL_SIZE) val actorContainerInactive = ArrayList(ACTORCONTAINER_INITIAL_SIZE) + protected val terrainChangeQueue = Queue() + protected val wallChangeQueue = Queue() + protected val wireChangeQueue = Queue() + override fun hide() { } @@ -96,6 +102,33 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { open fun worldSecondaryClickEnd(delta: Float) { } + /** + * Event for triggering fixture update when something is placed/removed on the world. + * Normally only called by GameWorld.setTileTerrain + * + * Queueing schema is used to make sure things are synchronised. + */ + open fun queueTerrainChangedEvent(old: Int, new: Int, position: Long) { + val (x, y) = LandUtil.resolveBlockAddr(world, position) + terrainChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y)) + } + + /** + * Wall version of terrainChanged() event + */ + open fun queueWallChangedEvent(old: Int, new: Int, position: Long) { + val (x, y) = LandUtil.resolveBlockAddr(world, position) + wallChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y)) + } + + /** + * Wire version of terrainChanged() event + */ + open fun queueWireChangedEvent(old: Int, new: Int, position: Long) { + val (x, y) = LandUtil.resolveBlockAddr(world, position) + wireChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y)) + } + /////////////////////// @@ -215,6 +248,8 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { } } + + data class BlockChangeQueueItem(val old: Int, val new: Int, val posX: Int, val posY: Int) } inline fun Lock.lock(body: () -> Unit) { diff --git a/src/net/torvald/terrarum/gameworld/GameWorld.kt b/src/net/torvald/terrarum/gameworld/GameWorld.kt index 604c26706..914d243de 100644 --- a/src/net/torvald/terrarum/gameworld/GameWorld.kt +++ b/src/net/torvald/terrarum/gameworld/GameWorld.kt @@ -2,6 +2,7 @@ package net.torvald.terrarum.gameworld import com.badlogic.gdx.graphics.Color +import net.torvald.terrarum.Terrarum import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.Fluid @@ -220,9 +221,13 @@ open class GameWorld { fun setTileWall(x: Int, y: Int, tile: Byte, damage: Int) { val (x, y) = coerceXY(x, y) + val oldWall = getTileFromWall(x, y) layerWall.setTile(x, y, tile) layerWallLowBits.setData(x, y, damage) wallDamages.remove(LandUtil.getBlockAddr(this, x, y)) + + if (oldWall != null) + Terrarum.ingame?.queueWallChangedEvent(oldWall, tile.toUint() * PairedMapLayer.RANGE + damage, LandUtil.getBlockAddr(this, x, y)) } /** @@ -230,6 +235,7 @@ open class GameWorld { */ fun setTileTerrain(x: Int, y: Int, tile: Byte, damage: Int) { val (x, y) = coerceXY(x, y) + val oldTerrain = getTileFromTerrain(x, y) layerTerrain.setTile(x, y, tile) layerTerrainLowBits.setData(x, y, damage) val blockAddr = LandUtil.getBlockAddr(this, x, y) @@ -240,11 +246,18 @@ open class GameWorld { fluidTypes.remove(blockAddr) } // fluid tiles-item should be modified so that they will also place fluid onto their respective map + + if (oldTerrain != null) + Terrarum.ingame?.queueTerrainChangedEvent(oldTerrain, tile.toUint() * PairedMapLayer.RANGE + damage, LandUtil.getBlockAddr(this, x, y)) } fun setTileWire(x: Int, y: Int, tile: Byte) { val (x, y) = coerceXY(x, y) + val oldWire = getTileFromWire(x, y) layerWire.setTile(x, y, tile) + + if (oldWire != null) + Terrarum.ingame?.queueWireChangedEvent(oldWire, tile.toUint(), LandUtil.getBlockAddr(this, x, y)) } fun getTileFrom(mode: Int, x: Int, y: Int): Int? { diff --git a/src/net/torvald/terrarum/modulebasegame/Ingame.kt b/src/net/torvald/terrarum/modulebasegame/Ingame.kt index 8de0d01c8..f0e29942c 100644 --- a/src/net/torvald/terrarum/modulebasegame/Ingame.kt +++ b/src/net/torvald/terrarum/modulebasegame/Ingame.kt @@ -405,6 +405,8 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) { itemOnGrip?.endSecondaryUse(delta) } + + private var firstTimeRun = true /////////////// @@ -505,6 +507,12 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) { CollisionSolver.process() WorldCamera.update(gameworld, actorNowPlaying) + + + // completely consume block change queues because why not + terrainChangeQueue.clear() + wallChangeQueue.clear() + wireChangeQueue.clear() } @@ -665,6 +673,12 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) { } } } + + if (it is CuedByTerrainChange) { + terrainChangeQueue.forEach { 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 4d3026d29..524647b01 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.modulebasegame.gameactors +import net.torvald.terrarum.IngameInstance import net.torvald.terrarum.Point2d import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.gameactors.ActorWBMovable @@ -7,9 +8,9 @@ import net.torvald.terrarum.gameactors.ActorWBMovable /** * Created by minjaesong on 2016-06-17. */ -open class FixtureBase(val blockBox: BlockBox) : +open class FixtureBase(val blockBox: BlockBox, val blockBoxProps: BlockBoxProps = BlockBoxProps(0)) : // disabling physics (not allowing the fixture to move) WILL make things easier - ActorWBMovable(RenderOrder.BEHIND, immobileBody = true, usePhysics = false) { + ActorWBMovable(RenderOrder.BEHIND, immobileBody = true, usePhysics = false), CuedByTerrainChange { /** * Block-wise position of this fixture when it's placed on the world. Null if it's not on the world @@ -32,6 +33,10 @@ open class FixtureBase(val blockBox: BlockBox) : + } + + open fun updateSelf() { + } /** @@ -42,6 +47,33 @@ open class FixtureBase(val blockBox: BlockBox) : } } +interface CuedByTerrainChange { + /** + * 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. + */ + fun updateForWorldChange(cue: IngameInstance.BlockChangeQueueItem) { + + } +} + +/** + * Standard 32-bit binary flags. + * + * (LSB) + * - 0: fluid resist - when FALSE, the fixture will break itself to item/nothing. For example, crops has this flag FALSE. + * - 1: don't drop item when broken - when TRUE, the fixture will simply disappear instead of dropping itself. For example, crop has this flag TRUE. + * + * (MSB) + * + * In the savegame's JSON, this flag set should be stored as signed integer. + */ +inline class BlockBoxProps(val flags: Int) { + +} + data class BlockBox(var collisionType: Int, var width: Int, var height: Int) { fun redefine(collisionType: Int, width: Int, height: Int) {