#12 event for world block change -- mainly meant for fixture updating itself

This commit is contained in:
minjaesong
2019-02-02 01:58:49 +09:00
parent 1e4e4d2b94
commit c476ca0d99
4 changed files with 96 additions and 2 deletions

View File

@@ -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<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val actorContainerInactive = ArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
protected val terrainChangeQueue = Queue<BlockChangeQueueItem>()
protected val wallChangeQueue = Queue<BlockChangeQueueItem>()
protected val wireChangeQueue = Queue<BlockChangeQueueItem>()
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) {

View File

@@ -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? {

View File

@@ -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)

View File

@@ -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) {