mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-10 05:41:51 +09:00
preparing fluid updater: debug water bucket
This commit is contained in:
@@ -229,6 +229,8 @@ object ModMgr {
|
||||
val className = it["classname"].toString()
|
||||
val itemID = it["id"].toInt()
|
||||
|
||||
printdbg(this, "Reading item #$itemID with className $className")
|
||||
|
||||
val loadedClass = Class.forName(className)
|
||||
val loadedClassConstructor = loadedClass.getConstructor(ItemID::class.java)
|
||||
val loadedClassInstance = loadedClassConstructor.newInstance(itemID)
|
||||
|
||||
@@ -171,6 +171,10 @@ class UIItemInventoryElem(
|
||||
|
||||
// equip da shit
|
||||
val itemEquipSlot = item!!.equipPosition
|
||||
if (itemEquipSlot == GameItem.EquipPosition.NULL) {
|
||||
TODO("Equip position is NULL, does this mean it's single-consume items like a potion?")
|
||||
}
|
||||
|
||||
val player = (Terrarum.ingame!! as Ingame).actorNowPlaying
|
||||
|
||||
if (player == null) return false
|
||||
|
||||
13
src/net/torvald/terrarum/blockproperties/Fluid.kt
Normal file
13
src/net/torvald/terrarum/blockproperties/Fluid.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
package net.torvald.terrarum.blockproperties
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-08-06.
|
||||
*/
|
||||
object Fluid {
|
||||
|
||||
val NULL = 0
|
||||
|
||||
val WATER = 1
|
||||
val STATIC_WATER = -1
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.Color
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator
|
||||
import net.torvald.terrarum.serialise.ReadLayerDataLzma
|
||||
import org.dyn4j.geometry.Vector2
|
||||
|
||||
@@ -341,9 +342,24 @@ open class GameWorld {
|
||||
|
||||
fun setFluid(x: Int, y: Int, fluidType: Int, fill: Float) {
|
||||
val addr = LandUtil.getBlockAddr(this, x, y)
|
||||
fluidTypes[addr] = fluidType
|
||||
fluidFills[addr] = fill
|
||||
setTileTerrain(x, y, Block.FLUID_MARKER)
|
||||
if (fill <= WorldSimulator.FLUID_MIN_MASS) {
|
||||
fluidTypes.remove(addr)
|
||||
fluidFills.remove(addr)
|
||||
setTileTerrain(x, y, 0)
|
||||
}
|
||||
else {
|
||||
fluidTypes[addr] = fluidType
|
||||
fluidFills[addr] = fill
|
||||
setTileTerrain(x, y, Block.FLUID_MARKER)
|
||||
}
|
||||
}
|
||||
|
||||
fun getFluid(x: Int, y: Int): Pair<Int, Float>? {
|
||||
val addr = LandUtil.getBlockAddr(this, x, y)
|
||||
val fill = fluidFills[addr]
|
||||
val type = fluidTypes[addr]
|
||||
|
||||
return if (type == null) null else Pair(type!!, fill!!)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import net.torvald.terrarum.KVHashMap
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.CanBeAnItem
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||
import net.torvald.terrarum.modulebasegame.Ingame
|
||||
@@ -32,12 +33,14 @@ object ItemCodex {
|
||||
|
||||
private val itemImagePlaceholder = TextureRegion(Texture("./assets/item_kari_24.tga"))
|
||||
|
||||
//private val ingame = Terrarum.ingame!! as Ingame
|
||||
//private val ingame = Terrarum.ingame!! as Ingame // WARNING you can't put this here, ExceptionInInitializerError
|
||||
|
||||
|
||||
// TODO: when generalised, there's no guarantee that blocks will be used as an item. Write customised item prop loader and init it on the Ingame
|
||||
|
||||
init {
|
||||
//val ingame = Terrarum.ingame!! as Ingame // WARNING you can't put this here, ExceptionInInitializerError
|
||||
|
||||
|
||||
/*println("[ItemCodex] recording item ID ")
|
||||
|
||||
@@ -186,8 +189,12 @@ object ItemCodex {
|
||||
override val isDynamic: Boolean = false
|
||||
override val material: Material = Material(1,1,1,1,1,1,1,1,1,1.0)
|
||||
|
||||
override val equipPosition: Int = EquipPosition.HAND_GRIP
|
||||
|
||||
override fun startSecondaryUse(delta: Float): Boolean {
|
||||
return super.startSecondaryUse(delta)
|
||||
val ingame = Terrarum.ingame!! as Ingame // must be in here
|
||||
ingame.world.setFluid(Terrarum.mouseTileX, Terrarum.mouseTileY, Fluid.WATER, 1f)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -519,7 +519,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
///////////////////////////
|
||||
BlockPropUtil.dynamicLumFuncTickClock()
|
||||
world.updateWorldTime(delta)
|
||||
//WorldSimulator(player, delta)
|
||||
WorldSimulator.invoke(actorNowPlaying, delta)
|
||||
WeatherMixer.update(delta, actorNowPlaying, world)
|
||||
BlockStats.update()
|
||||
|
||||
|
||||
@@ -177,6 +177,9 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode
|
||||
if (item.stackable && !item.isDynamic) {
|
||||
remove(item, 1)
|
||||
}
|
||||
else if (item.isUnique) {
|
||||
return // don't consume a bike!
|
||||
}
|
||||
else {
|
||||
val newItem: GameItem
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ object PlayerBuilderSigrid {
|
||||
blocks.forEach { p.addItem(it, 999) }
|
||||
walls.forEach { p.addItem(it + 4096, 999) }
|
||||
p.inventory.add(ItemCodex.ITEM_STATIC.first)
|
||||
p.inventory.add(9000)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
import net.torvald.terrarum.gameworld.FluidCodex
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.Ingame
|
||||
@@ -17,6 +18,9 @@ import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
* Created by minjaesong on 2016-08-03.
|
||||
*/
|
||||
object WorldSimulator {
|
||||
|
||||
// FLUID-RELATED STUFFS //
|
||||
|
||||
/**
|
||||
* In tiles;
|
||||
* square width/height = field * 2
|
||||
@@ -24,11 +28,14 @@ object WorldSimulator {
|
||||
const val FLUID_UPDATING_SQUARE_RADIUS = 64 // larger value will have dramatic impact on performance
|
||||
const private val DOUBLE_RADIUS = FLUID_UPDATING_SQUARE_RADIUS * 2
|
||||
|
||||
private val fluidMap = Array<ByteArray>(DOUBLE_RADIUS, { ByteArray(DOUBLE_RADIUS) })
|
||||
private val fluidTypeMap = Array<ByteArray>(DOUBLE_RADIUS, { ByteArray(DOUBLE_RADIUS) })
|
||||
private val fluidMap = Array(DOUBLE_RADIUS, { FloatArray(DOUBLE_RADIUS) })
|
||||
private val fluidTypeMap = Array(DOUBLE_RADIUS, { IntArray(DOUBLE_RADIUS) })
|
||||
|
||||
const val DISPLACE_CAP = 4
|
||||
const val FLUID_MAX = 16
|
||||
const val FLUID_MAX_MASS = 1f // The normal, un-pressurized mass of a full water cell
|
||||
const val FLUID_MAX_COMP = 0.02f // How much excess water a cell can store, compared to the cell above it
|
||||
const val FLUID_MIN_MASS = 0.0001f //Ignore cells that are almost dry
|
||||
|
||||
// END OF FLUID-RELATED STUFFS
|
||||
|
||||
var updateXFrom = 0
|
||||
var updateXTo = 0
|
||||
@@ -65,67 +72,6 @@ object WorldSimulator {
|
||||
// build fluidmap //
|
||||
////////////////////
|
||||
purgeFluidMap()
|
||||
worldToFluidMap(world)
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// displace fluids. Record displacements into the fluidMap //
|
||||
/////////////////////////////////////////////////////////////
|
||||
for (y in updateYFrom..updateYTo) {
|
||||
for (x in updateXFrom..updateXTo) {
|
||||
val tile = world.getTileFromTerrain(x, y) ?: Block.STONE
|
||||
val tileBottom = world.getTileFromTerrain(x, y + 1) ?: Block.STONE
|
||||
val tileLeft = world.getTileFromTerrain(x - 1, y) ?: Block.STONE
|
||||
val tileRight = world.getTileFromTerrain(x + 1, y) ?: Block.STONE
|
||||
if (tile.isFluid()) {
|
||||
|
||||
// move down if not obstructed
|
||||
/*if (!tileBottom.isSolid()) {
|
||||
val drainage = drain(world, x, y, DISPLACE_CAP)
|
||||
pour(world, x, y + 1, drainage)
|
||||
}
|
||||
// left and right both open
|
||||
else if (!tileLeft.isSolid() && !tileRight.isSolid()) {
|
||||
// half-breaker
|
||||
val moreToTheRight = HQRNG().nextBoolean()
|
||||
val displacement = drain(world, x, y, DISPLACE_CAP)
|
||||
|
||||
if (displacement.isEven()) {
|
||||
pour(world, x - 1, y, displacement shr 1)
|
||||
pour(world, x + 1, y, displacement shr 1)
|
||||
}
|
||||
else {
|
||||
pour(world, x - 1, y, (displacement shr 1) + if (moreToTheRight) 0 else 1)
|
||||
pour(world, x + 1, y, (displacement shr 1) + if (moreToTheRight) 1 else 0)
|
||||
}
|
||||
}
|
||||
// left open
|
||||
else if (!tileLeft.isSolid()) {
|
||||
val displacement = drain(world, x, y, DISPLACE_CAP)
|
||||
pour(world, x - 1, y, displacement)
|
||||
}
|
||||
// right open
|
||||
else if (!tileRight.isSolid()) {
|
||||
val displacement = drain(world, x, y, DISPLACE_CAP)
|
||||
pour(world, x + 1, y, displacement)
|
||||
}
|
||||
// nowhere open; do default (fill top)
|
||||
else {
|
||||
pour(world, x, y - 1, DISPLACE_CAP)
|
||||
}*/
|
||||
if (!tileBottom.isSolid()) {
|
||||
pour(x, y + 1, drain(x, y, FLUID_MAX))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// replace fluids in the map according to fluidMap //
|
||||
/////////////////////////////////////////////////////
|
||||
fluidMapToWorld(world)
|
||||
|
||||
}
|
||||
|
||||
@@ -134,7 +80,7 @@ object WorldSimulator {
|
||||
* falling, each tiles are displaced by ONLY ONE TILE below.
|
||||
*/
|
||||
fun displaceFallables(delta: Float) {
|
||||
for (y in updateYFrom..updateYTo) {
|
||||
/*for (y in updateYFrom..updateYTo) {
|
||||
for (x in updateXFrom..updateXTo) {
|
||||
val tile = world.getTileFromTerrain(x, y) ?: Block.STONE
|
||||
val tileBelow = world.getTileFromTerrain(x, y + 1) ?: Block.STONE
|
||||
@@ -155,7 +101,7 @@ object WorldSimulator {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
@@ -163,143 +109,18 @@ object WorldSimulator {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun drawFluidMapDebug(batch: SpriteBatch) {
|
||||
batch.color = colourWater
|
||||
|
||||
for (y in 0..fluidMap.size - 1) {
|
||||
for (x in 0..fluidMap[0].size - 1) {
|
||||
val data = fluidMap[y][x]
|
||||
if (BlocksDrawer.tileInCamera(x + updateXFrom, y + updateYFrom)) {
|
||||
if (data == 0.toByte())
|
||||
batch.color = colourNone
|
||||
else
|
||||
batch.color = colourWater
|
||||
|
||||
Terrarum.fontSmallNumbers.draw(batch,
|
||||
data.toString(),
|
||||
updateXFrom.plus(x).times(FeaturesDrawer.TILE_SIZE).toFloat()
|
||||
+ if (data < 10) 4f else 0f,
|
||||
updateYFrom.plus(y).times(FeaturesDrawer.TILE_SIZE) + 4f
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
//if (data > 0) println(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun purgeFluidMap() {
|
||||
for (y in 1..DOUBLE_RADIUS) {
|
||||
for (x in 1..DOUBLE_RADIUS) {
|
||||
fluidMap[y - 1][x - 1] = 0
|
||||
fluidTypeMap[y - 1][x - 1] = 0
|
||||
fluidMap[y - 1][x - 1] = 0f
|
||||
fluidTypeMap[y - 1][x - 1] = Fluid.NULL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun worldToFluidMap(world: GameWorld) {
|
||||
for (y in updateYFrom..updateYTo) {
|
||||
for (x in updateXFrom..updateXTo) {
|
||||
val tile = world.getTileFromTerrain(x, y) ?: Block.STONE
|
||||
if (tile.isFluid()) {
|
||||
fluidMap[y - updateYFrom][x - updateXFrom] = tile.fluidLevel().toByte()
|
||||
fluidTypeMap[y - updateYFrom][x - updateXFrom] = tile.fluidType().toByte()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fluidMapToWorld(world: GameWorld) {
|
||||
for (y in 0..fluidMap.size - 1) {
|
||||
for (x in 0..fluidMap[0].size - 1) {
|
||||
placeFluid(world, updateXFrom + x, updateYFrom + y
|
||||
, FluidCodex.FLUID_WATER, fluidMap[y][x] - 1
|
||||
)
|
||||
// FIXME test code: deals with water only!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.isFluid() = BlockCodex[this].isFluid
|
||||
fun Int.isSolid() = this.fluidLevel() == FLUID_MAX || BlockCodex[this].isSolid
|
||||
//fun Int.viscosity() = BlockCodex[this].
|
||||
fun Int.fluidLevel() = if (!this.isFluid()) 0 else (this % FLUID_MAX).plus(1)
|
||||
fun Int.fluidType() = (this / 16) // 0 - 255, 255 being water, 254 being lava
|
||||
fun Int.isEven() = (this and 0x01) == 0
|
||||
fun Int.isFallable() = BlockCodex[this].isFallable
|
||||
|
||||
private fun placeFluid(world: GameWorld, x: Int, y: Int, fluidType: Byte, amount: Int) {
|
||||
if (world.layerTerrain.isInBound(x, y)) {
|
||||
if (amount > 0 && !world.getTileFromTerrain(x, y)!!.isSolid()) {
|
||||
world.setTileTerrain(x, y, fluidType, amount - 1)
|
||||
}
|
||||
else if (amount == 0 && world.getTileFromTerrain(x, y)!!.isFluid()) {
|
||||
world.setTileTerrain(x, y, Block.AIR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x and y: world tile coord
|
||||
* @return amount of fluid actually drained.
|
||||
* (intended drainage - this) will give you how much fluid is not yet drained.
|
||||
* TODO add fluidType support
|
||||
*/
|
||||
private fun drain(x: Int, y: Int, amount: Int): Int {
|
||||
val displacement = Math.min(fluidMap[y - updateYFrom][x - updateXFrom].toInt(), amount)
|
||||
|
||||
fluidMap[y - updateYFrom][x - updateXFrom] =
|
||||
(fluidMap[y - updateYFrom][x - updateXFrom] - displacement).toByte()
|
||||
|
||||
return displacement
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x and y: world tile coord
|
||||
* TODO add fluidType support
|
||||
*/
|
||||
private fun pour(x: Int, y: Int, amount: Int) {
|
||||
/**
|
||||
* @param x and y: world tile coord
|
||||
* @return spillage
|
||||
* TODO add fluidType support
|
||||
*/
|
||||
fun pourInternal(worldXpos: Int, worldYPos: Int, volume: Int): Int {
|
||||
var spil = 0
|
||||
|
||||
val addrX = worldXpos - updateXFrom
|
||||
val addrY = worldYPos - updateYFrom
|
||||
|
||||
if (addrX >= 0 && addrY >= 0 && addrX < DOUBLE_RADIUS && addrY < DOUBLE_RADIUS) {
|
||||
fluidMap[addrY][addrX] = (fluidMap[addrY][addrX] + volume).toByte()
|
||||
if (fluidMap[addrY][addrX] > FLUID_MAX) {
|
||||
spil = fluidMap[addrY][addrX] - FLUID_MAX
|
||||
fluidMap[addrY][addrX] = FLUID_MAX.toByte()
|
||||
}
|
||||
}
|
||||
|
||||
return spil
|
||||
}
|
||||
|
||||
// pour the fluid
|
||||
var spillage = pourInternal(x, y, amount)
|
||||
|
||||
if (spillage <= 0) return
|
||||
|
||||
// deal with the spillage
|
||||
|
||||
val tileUp = world.getTileFromTerrain(x - updateXFrom, y - updateYFrom - 1)
|
||||
val tileDown = world.getTileFromTerrain(x - updateXFrom, y - updateYFrom + 1)
|
||||
|
||||
// try to fill downward
|
||||
if (tileDown != null && !tileDown.isSolid()) {
|
||||
spillage = pourInternal(x, y + 1, spillage)
|
||||
}
|
||||
// else, try to fill upward. if there is no space, just discard
|
||||
if (spillage >= 0 && tileUp != null && !tileUp.isSolid()) {
|
||||
pourInternal(x, y - 1, spillage)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user