huge wippie

This commit is contained in:
minjaesong
2024-11-10 22:30:01 +09:00
parent 4c9db1ef60
commit 0eccc4dbea
38 changed files with 1196 additions and 646 deletions

View File

@@ -31,6 +31,7 @@ import net.torvald.terrarum.gamecontroller.KeyToggler;
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent;
import net.torvald.terrarum.gameitems.GameItem;
import net.torvald.terrarum.gameworld.GameWorld;
import net.torvald.terrarum.gameworld.TheGameWorld;
import net.torvald.terrarum.imagefont.BigAlphNum;
import net.torvald.terrarum.imagefont.TinyAlphNum;
import net.torvald.terrarum.langpack.Lang;
@@ -1016,7 +1017,7 @@ public class App implements ApplicationListener {
ModMgr.INSTANCE.disposeMods();
GameWorld.Companion.makeNullWorld().dispose();
TheGameWorld.Companion.makeNullWorld().dispose();
Terrarum.INSTANCE.dispose();

View File

@@ -12,6 +12,8 @@ import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.gameworld.TitlescreenGameWorld
import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
@@ -105,7 +107,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
printStackTrace(this)
}
open var world: GameWorld = GameWorld.makeNullWorld()
open var world: GameWorld = TheGameWorld.makeNullWorld()
set(value) {
val oldWorld = field
newWorldLoadedLatch = true

View File

@@ -2,26 +2,17 @@ package net.torvald.terrarum.blockstats
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.utils.Disposable
import com.badlogic.gdx.utils.GdxRuntimeException
import com.badlogic.gdx.utils.Queue
import net.torvald.terrarum.App
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.abs
import net.torvald.terrarum.concurrent.ThreadExecutor
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_HEIGHT
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_WIDTH
import net.torvald.terrarum.sqr
import net.torvald.terrarum.toInt
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.Companion.WALL_OVERLAY_COLOUR
import java.util.concurrent.Callable
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.absoluteValue
import kotlin.math.max
import kotlin.math.roundToInt
object MinimapComposer : Disposable {
@@ -32,7 +23,7 @@ object MinimapComposer : Disposable {
val MINIMAP_TILE_WIDTH = (MINIMAP_WIDTH.toInt() * 3) / SQUARE_SIZE + 4
val MINIMAP_TILE_HEIGHT = (MINIMAP_HEIGHT.toInt() * 3) / SQUARE_SIZE + 4
private var world: GameWorld = GameWorld.makeNullWorld()
private var world: GameWorld = TheGameWorld.makeNullWorld()
fun setWorld(world: GameWorld) {
try {

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.*
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
/**
@@ -8,7 +9,7 @@ import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
*/
internal object GetGR : ConsoleCommand {
override fun execute(args: Array<String>) {
val gameRules = INGAME.world.gameRules
val gameRules = (INGAME.world as TheGameWorld).gameRules
// check if args[1] is number or not
if (args.size > 1 && !args[1].isNum()) { // args[1] is Gamerule name

View File

@@ -18,6 +18,7 @@ import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameparticles.createRandomBlockParticle
import net.torvald.terrarum.gameworld.BlockAddress
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.itemproperties.Calculate
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid

View File

@@ -5,15 +5,46 @@ import com.badlogic.gdx.utils.Disposable
/**
* Created by minjaesong on 2023-10-10.
*/
abstract class BlockLayer : Disposable {
abstract val chunkPool: ChunkPool
abstract val width: Int
abstract val height: Int
abstract val bytesPerBlock: Long
abstract fun unsafeToBytes(x: Int, y: Int): ByteArray
abstract fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray)
abstract fun unsafeGetTile(x: Int, y: Int): Int
open class BlockLayer() : Disposable {
// abstract val chunkPool: ChunkPool
open val width: Int = 0
open val height: Int = 0
open val bytesPerBlock: Long = 0
open fun unsafeToBytes(x: Int, y: Int): ByteArray = byteArrayOf(0,0,0,0)
open fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) { }
// for I16; other layer must throw UnsupportedOperationException
open fun unsafeSetTile(x: Int, y: Int, tile: Int) { }
// for I16F16; other layer must throw UnsupportedOperationException
open fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) { }
// for I16I8; other layer must throw UnsupportedOperationException
open fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) { }
open fun unsafeGetTile(x: Int, y: Int): Int = 0
open fun getOffset(x: Int, y: Int): Long {
return this.bytesPerBlock * (y * this.width + x)
}
open val disposed: Boolean = false
override fun dispose() {
}
open fun unsafeGetTileI16F16(x: Int, y: Int): Pair<Int, Float> = 0 to 0f
open fun unsafeGetTileI16I8(x: Int, y: Int): Pair<Int, Int> = 0 to 0
open fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) { }
}
abstract class BlockLayerWithChunkPool : BlockLayer() {
abstract val chunkPool: ChunkPool
/**
* Unsupported for BlockLayerWithChunkPool
*/
override fun getOffset(x: Int, y: Int): Long {
throw UnsupportedOperationException()
}
}
/*inline fun BlockLayer.getOffset(x: Int, y: Int): Long {

View File

@@ -1,14 +1,8 @@
package net.torvald.terrarum.gameworld
import net.torvald.terrarum.App
import net.torvald.terrarum.gameworld.BlockLayerGenericI16.Companion
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
import net.torvald.terrarum.savegame.DiskSkimmer
import net.torvald.terrarum.serialise.toUint
import net.torvald.unsafe.UnsafeHelper
import net.torvald.unsafe.UnsafePtr
import net.torvald.util.Float16
const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smaller than epsilon of float16)
@@ -20,9 +14,10 @@ const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smalle
* * ```
* * where a_n is a fluid number, f_n is a fluid fill
*
* Created by minjaesong on 2023-10-10.
* Unsafe version Created by minjaesong on 2023-10-10.
* Chunkpool version Created by minjaesong on 2024-10-22.
*/
class BlockLayerFluidI16F16 : BlockLayer {
class BlockLayerFluidI16F16 : BlockLayerWithChunkPool {
override val width: Int
override val height: Int
@@ -33,7 +28,7 @@ class BlockLayerFluidI16F16 : BlockLayer {
height: Int,
disk: ClusteredFormatDOM,
layerNum: Int,
world: GameWorld
world: TheGameWorld
) {
this.width = width
this.height = height
@@ -46,7 +41,7 @@ class BlockLayerFluidI16F16 : BlockLayer {
height: Int,
disk: DiskSkimmer,
layerNum: Int,
world: GameWorld
world: TheGameWorld
) {
this.width = width
this.height = height
@@ -58,16 +53,16 @@ class BlockLayerFluidI16F16 : BlockLayer {
override val bytesPerBlock = BYTES_PER_BLOCK
override fun unsafeGetTile(x: Int, y: Int): Int {
return unsafeGetTile1(x, y).first
return unsafeGetTileI16F16(x, y).first
}
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Float> {
override fun unsafeGetTileI16F16(x: Int, y: Int): Pair<Int, Float> {
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
return chunkPool.getTileI16F16(chunk, ox, oy)
}
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
val (tile, fill0) = unsafeGetTile1(x, y)
val (tile, fill0) = unsafeGetTileI16F16(x, y)
val fill = Float16.fromFloat(fill0).toUint()
return byteArrayOf(
((tile ushr 8) and 255).toByte(),
@@ -76,7 +71,15 @@ class BlockLayerFluidI16F16 : BlockLayer {
(fill and 255).toByte(), )
}
internal fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
val fill = Float16.fromFloat(fill).toUint()
chunkPool.setTileRaw(chunk, ox, oy, tile0.and(65535) or fill.shl(16))
@@ -103,8 +106,11 @@ class BlockLayerFluidI16F16 : BlockLayer {
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
override var disposed: Boolean = false
override fun dispose() {
chunkPool.dispose()
disposed = true
}
override fun toString(): String = "BlockLayerI16F16 (${width}x$height)"

View File

@@ -1,13 +1,10 @@
package net.torvald.terrarum.gameworld
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
import net.torvald.terrarum.savegame.DiskSkimmer
import net.torvald.terrarum.serialise.toUint
import net.torvald.unsafe.UnsafeHelper
import net.torvald.unsafe.UnsafePtr
/**
* Memory layout:
@@ -18,21 +15,24 @@ import net.torvald.unsafe.UnsafePtr
*
* Original version Created by minjaesong on 2016-01-17.
* Unsafe version Created by minjaesong on 2019-06-08.
* Chunkpool version Created by minjaesong on 2024-10-22.
*
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
*/
class BlockLayerGenericI16: BlockLayer {
class BlockLayerGenericI16: BlockLayerWithChunkPool {
override val width: Int
override val height: Int
override val chunkPool: ChunkPool
private var _hashcode = 0
constructor(
width: Int,
height: Int,
disk: ClusteredFormatDOM,
layerNum: Int,
world: GameWorld
world: TheGameWorld
) {
this.width = width
this.height = height
@@ -42,6 +42,8 @@ class BlockLayerGenericI16: BlockLayer {
WALL -> ChunkPool.getRenameFunTerrain(world)
else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum")
})
_hashcode = disk.uuid.hashCode()
}
constructor(
@@ -49,7 +51,7 @@ class BlockLayerGenericI16: BlockLayer {
height: Int,
disk: DiskSkimmer,
layerNum: Int,
world: GameWorld
world: TheGameWorld
) {
this.width = width
this.height = height
@@ -59,8 +61,12 @@ class BlockLayerGenericI16: BlockLayer {
WALL -> ChunkPool.getRenameFunTerrain(world)
else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum")
})
_hashcode = disk.diskFile.hashCode()
}
override fun hashCode() = _hashcode
override val bytesPerBlock = BYTES_PER_BLOCK
override fun unsafeGetTile(x: Int, y: Int): Int {
@@ -76,13 +82,21 @@ class BlockLayerGenericI16: BlockLayer {
)
}
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
chunkPool.setTileRaw(chunk, ox, oy, tile)
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
val tile = (0..3).fold(0) { acc, i -> acc or (bytes[i].toUint()).shl(8*i) }
val tile = (0..1).fold(0) { acc, i -> acc or (bytes[i].toUint()).shl(8*i) }
unsafeSetTile(x, y, tile)
}
@@ -101,8 +115,11 @@ class BlockLayerGenericI16: BlockLayer {
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
override var disposed: Boolean = false
override fun dispose() {
chunkPool.dispose()
disposed = true
}
override fun toString(): String = "BlockLayerI16 (${width}x$height)"

View File

@@ -0,0 +1,133 @@
package net.torvald.terrarum.gameworld
import com.badlogic.gdx.utils.Disposable
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
import net.torvald.terrarum.serialise.toUint
import net.torvald.unsafe.UnsafeHelper
import net.torvald.unsafe.UnsafePtr
/**
* Memory layout:
* ```
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 ||
* ```
* where a_n is a tile number
*
* Original version Created by minjaesong on 2016-01-17.
* Unsafe version Created by minjaesong on 2019-06-08.
*
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
*/
class BlockLayerInMemoryI16(
override val width: Int,
override val height: Int,
): BlockLayer() {
private constructor() : this(0, 0)
override val bytesPerBlock = BYTES_PER_BLOCK
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
val ptrDestroyed: Boolean
get() = ptr.destroyed
init {
ptr.fillWith(-1)
}
/**
* Returns an iterator over stored bytes.
*
* @return an Iterator.
*/
fun bytesIterator(): Iterator<Byte> {
return object : Iterator<Byte> {
private var iteratorCount = 0L
override fun hasNext(): Boolean {
return iteratorCount < width * height * bytesPerBlock
}
override fun next(): Byte {
iteratorCount += 1
return ptr[iteratorCount - 1]
}
}
}
override fun unsafeGetTile(x: Int, y: Int): Int {
val offset = getOffset(x, y)
val lsb = ptr[offset]
val msb = ptr[offset + 1]
return lsb.toUint() or msb.toUint().shl(8)
}
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
val offset = getOffset(x, y)
return byteArrayOf(ptr[offset + 1], ptr[offset + 0])
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
val offset = getOffset(x, y)
val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte()
// try {
ptr[offset] = lsb
ptr[offset + 1] = msb
// }
// catch (e: IndexOutOfBoundsException) {
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
// throw e
// }
}
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
val offset = getOffset(x, y)
ptr[offset] = bytes[1]
ptr[offset + 1] = bytes[0]
}
/**
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
*/
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
val offset = BYTES_PER_BLOCK * blockOffset
val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte()
unsafe.putByte(layerPtr + offset, lsb)
unsafe.putByte(layerPtr + offset + 1, msb)
}*/
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
override val disposed: Boolean
get() = ptr.destroyed
override fun dispose() {
ptr.destroy()
printdbg(this, "BlockLayerI16 with ptr ($ptr) successfully freed")
}
override fun toString(): String = ptr.toString("BlockLayerI16")
companion object {
@Transient val BYTES_PER_BLOCK = 2L
}
}

View File

@@ -0,0 +1,145 @@
package net.torvald.terrarum.gameworld
import net.torvald.terrarum.App
import net.torvald.terrarum.serialise.toUint
import net.torvald.unsafe.UnsafeHelper
import net.torvald.unsafe.UnsafePtr
import net.torvald.util.Float16
/**
* * Memory layout:
* * ```
* * a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | f7 f6 f5 f4 f3 f2 f1 f0 | fF fE fD fC fB fA f9 f8 ||
* * ```
* * where a_n is a fluid number, f_n is a fluid fill
*
* Created by minjaesong on 2023-10-10.
*/
class BlockLayerInMemoryI16F16(override val width: Int, override val height: Int) : BlockLayer() {
override val bytesPerBlock = BYTES_PER_BLOCK
// for some reason, all the efforts of saving the memory space were futile.
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
val ptrDestroyed: Boolean
get() = ptr.destroyed
init {
ptr.fillWith(-1)
}
/**
* @param data Byte array representation of the layer
*/
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
TODO()
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
}
/**
* Returns an iterator over stored bytes.
*
* @return an Iterator.
*/
fun bytesIterator(): Iterator<Byte> {
return object : Iterator<Byte> {
private var iteratorCount = 0L
override fun hasNext(): Boolean {
return iteratorCount < width * height * bytesPerBlock
}
override fun next(): Byte {
iteratorCount += 1
return ptr[iteratorCount - 1]
}
}
}
override fun unsafeGetTile(x: Int, y: Int): Int {
val offset = getOffset(x, y)
val lsb = ptr[offset]
val msb = ptr[offset + 1]
return lsb.toUint() or msb.toUint().shl(8)
}
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Float> {
val offset = getOffset(x, y)
val lsb = ptr[offset]
val msb = ptr[offset + 1]
val hbits = (ptr[offset + 2].toUint() or ptr[offset + 3].toUint().shl(8)).toShort()
val fill = Float16.toFloat(hbits)
return lsb.toUint() or msb.toUint().shl(8) to fill
}
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
val offset = getOffset(x, y)
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 3], ptr[offset + 2])
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
val offset = getOffset(x, y)
val hbits = Float16.fromFloat(fill).toInt().and(0xFFFF)
val tile = if (fill < FLUID_MIN_MASS) 0 else tile0
val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte()
val hlsb = hbits.and(0xff).toByte()
val hmsb = hbits.ushr(8).and(0xff).toByte()
ptr[offset] = lsb
ptr[offset + 1] = msb
ptr[offset + 2] = hlsb
ptr[offset + 3] = hmsb
}
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
val offset = getOffset(x, y)
ptr[offset] = bytes[1]
ptr[offset + 1] = bytes[0]
ptr[offset + 2] = bytes[3]
ptr[offset + 3] = bytes[2]
}
/**
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
*/
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
val offset = BYTES_PER_BLOCK * blockOffset
val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte()
unsafe.putByte(layerPtr + offset, lsb)
unsafe.putByte(layerPtr + offset + 1, msb)
}*/
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
override val disposed: Boolean
get() = ptr.destroyed
override fun dispose() {
ptr.destroy()
App.printdbg(this, "BlockLayerI16F16 with ptr ($ptr) successfully freed")
}
override fun toString(): String = ptr.toString("BlockLayerI16F16")
companion object {
@Transient val BYTES_PER_BLOCK = 4L
}
}

View File

@@ -0,0 +1,151 @@
package net.torvald.terrarum.gameworld
import net.torvald.terrarum.App
import net.torvald.terrarum.serialise.toUint
import net.torvald.unsafe.UnsafeHelper
import net.torvald.unsafe.UnsafePtr
/**
* Memory layout:
* ```
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | p7 p6 p5 p4 p3 p2 p1 p0 ||
* ```
* where a_n is a tile number, p_n is a placement index
* Created by minjaesong on 2023-10-10.
*/
class BlockLayerInMemoryI16I8 (override val width: Int, override val height: Int) : BlockLayer() {
override val bytesPerBlock = BYTES_PER_BLOCK
// for some reason, all the efforts of saving the memory space were futile.
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
val ptrDestroyed: Boolean
get() = ptr.destroyed
init {
ptr.fillWith(0) // there is no NOT-GENERATED for ores, keep it as 0
}
/**
* @param data Byte array representation of the layer
*/
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
TODO()
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
}
/**
* Returns an iterator over stored bytes.
*
* @return an Iterator.
*/
fun bytesIterator(): Iterator<Byte> {
return object : Iterator<Byte> {
private var iteratorCount = 0L
override fun hasNext(): Boolean {
return iteratorCount < width * height * bytesPerBlock
}
override fun next(): Byte {
iteratorCount += 1
return ptr[iteratorCount - 1]
}
}
}
override fun unsafeGetTile(x: Int, y: Int): Int {
val offset = getOffset(x, y)
val lsb = ptr[offset]
val msb = ptr[offset + 1]
val placement = ptr[offset + 2]
return lsb.toUint() + msb.toUint().shl(8)
}
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Int> {
val offset = getOffset(x, y)
val lsb = ptr[offset]
val msb = ptr[offset + 1]
val placement = ptr[offset + 2]
return lsb.toUint() or msb.toUint().shl(8) to placement.toUint()
}
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
val offset = getOffset(x, y)
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 2])
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
val offset = getOffset(x, y)
val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte()
// try {
ptr[offset] = lsb
ptr[offset + 1] = msb
ptr[offset + 2] = placement.toByte()
// }
// catch (e: IndexOutOfBoundsException) {
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
// throw e
// }
}
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
val offset = getOffset(x, y)
ptr[offset] = bytes[1]
ptr[offset + 1] = bytes[0]
ptr[offset + 2] = bytes[2]
}
override fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) {
val offset = getOffset(x, y)
val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte()
ptr[offset] = lsb
ptr[offset + 1] = msb
}
/**
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
*/
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
val offset = BYTES_PER_BLOCK * blockOffset
val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte()
unsafe.putByte(layerPtr + offset, lsb)
unsafe.putByte(layerPtr + offset + 1, msb)
}*/
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
override val disposed: Boolean
get() = ptr.destroyed
override fun dispose() {
ptr.destroy()
App.printdbg(this, "BlockLayerI16I8 with ptr ($ptr) successfully freed")
}
override fun toString(): String = ptr.toString("BlockLayerI16I8")
companion object {
@Transient val BYTES_PER_BLOCK = 3L
}
}

View File

@@ -1,14 +1,8 @@
package net.torvald.terrarum.gameworld
import net.torvald.terrarum.App
import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16.Companion
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
import net.torvald.terrarum.savegame.DiskSkimmer
import net.torvald.terrarum.serialise.toUint
import net.torvald.unsafe.UnsafeHelper
import net.torvald.unsafe.UnsafePtr
/**
* Memory layout:
@@ -16,9 +10,11 @@ import net.torvald.unsafe.UnsafePtr
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | p7 p6 p5 p4 p3 p2 p1 p0 ||
* ```
* where a_n is a tile number, p_n is a placement index
* Created by minjaesong on 2023-10-10.
*
* Unsafe version Created by minjaesong on 2023-10-10.
* Chunkpool version Created by minjaesong on 2024-10-22.
*/
class BlockLayerOresI16I8 : BlockLayer {
class BlockLayerOresI16I8 : BlockLayerWithChunkPool {
override val width: Int
override val height: Int
@@ -29,7 +25,7 @@ class BlockLayerOresI16I8 : BlockLayer {
height: Int,
disk: ClusteredFormatDOM,
layerNum: Int,
world: GameWorld
world: TheGameWorld
) {
this.width = width
this.height = height
@@ -42,7 +38,7 @@ class BlockLayerOresI16I8 : BlockLayer {
height: Int,
disk: DiskSkimmer,
layerNum: Int,
world: GameWorld
world: TheGameWorld
) {
this.width = width
this.height = height
@@ -54,16 +50,16 @@ class BlockLayerOresI16I8 : BlockLayer {
override val bytesPerBlock = BYTES_PER_BLOCK
override fun unsafeGetTile(x: Int, y: Int): Int {
return unsafeGetTile1(x, y).first
return unsafeGetTileI16I8(x, y).first
}
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Int> {
override fun unsafeGetTileI16I8(x: Int, y: Int): Pair<Int, Int> {
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
return chunkPool.getTileI16I8(chunk, ox, oy)
}
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
val (tile, fill) = unsafeGetTile1(x, y)
val (tile, fill) = unsafeGetTileI16I8(x, y)
return byteArrayOf(
((tile ushr 8) and 255).toByte(),
(tile and 255).toByte(),
@@ -71,7 +67,15 @@ class BlockLayerOresI16I8 : BlockLayer {
)
}
internal fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
throw UnsupportedOperationException()
}
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
chunkPool.setTileRaw(chunk, ox, oy, tile or placement.shl(16))
}
@@ -82,8 +86,8 @@ class BlockLayerOresI16I8 : BlockLayer {
unsafeSetTile(x, y, tile, placement)
}
internal fun unsafeSetTileKeepPlacement(x: Int, y: Int, tile: Int) {
val oldPlacement = unsafeGetTile1(x, y).second
override fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) {
val oldPlacement = unsafeGetTileI16I8(x, y).second
unsafeSetTile(x, y, tile, oldPlacement)
}
@@ -102,8 +106,11 @@ class BlockLayerOresI16I8 : BlockLayer {
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
override var disposed: Boolean = false
override fun dispose() {
chunkPool.dispose()
disposed = true
}
override fun toString(): String = "BlockLayerI16I8 (${width}x$height)"

View File

@@ -35,6 +35,8 @@ enum class ChunkAllocClass {
}
/**
* FIXME: loading a chunk from disk will attempt to create a chunk because the chunk-to-be-loaded is not on the pointers map, and this operation will want to create a new chunk file but the file already exists
*
* Single layer gets single Chunk Pool.
*
* Created by minjaesong on 2024-09-07.
@@ -45,7 +47,7 @@ open class ChunkPool {
private val disk: Any
private val layerIndex: Int
private val wordSizeInBytes: Long
private val world: GameWorld
private val world: TheGameWorld
private val initialValue: Int // bytes to fill the new chunk
private val renumberFun: (Int) -> Int
@@ -60,7 +62,7 @@ open class ChunkPool {
disk: DiskSkimmer,
layerIndex: Int,
wordSizeInBytes: Long,
world: GameWorld,
world: TheGameWorld,
initialValue: Int,
renumberFun: (Int) -> Int,
) {
@@ -79,7 +81,7 @@ open class ChunkPool {
disk: ClusteredFormatDOM,
layerIndex: Int,
wordSizeInBytes: Long,
world: GameWorld,
world: TheGameWorld,
initialValue: Int,
renumberFun: (Int) -> Int,
) {
@@ -393,7 +395,7 @@ open class ChunkPool {
private fun Int.get2LSB() = this.get3MSB()
private fun Int.getLSB() = this.get4MSB()
fun getRenameFunTerrain(world: GameWorld): (Int) -> Int {
fun getRenameFunTerrain(world: TheGameWorld): (Int) -> Int {
// word size: 2
return { oldTileNum ->
val oldOreName = world.oldTileNumberToNameMap[oldTileNum.toLong()]
@@ -402,7 +404,7 @@ open class ChunkPool {
}
}
fun getRenameFunOres(world: GameWorld): (Int) -> Int {
fun getRenameFunOres(world: TheGameWorld): (Int) -> Int {
// word size: 3
return { oldTileNumRaw ->
val oldOreNum = oldTileNumRaw and 0x0000FFFF
@@ -413,7 +415,7 @@ open class ChunkPool {
}
}
fun getRenameFunFluids(world: GameWorld): (Int) -> Int {
fun getRenameFunFluids(world: TheGameWorld): (Int) -> Int {
// word size: 4
return { oldTileNumRaw ->
val oldFluidNum = oldTileNumRaw and 0x0000FFFF

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@ package net.torvald.terrarum.modulebasegame
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input.Keys
import com.badlogic.gdx.InputAdapter
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion
@@ -14,14 +15,14 @@ import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.*
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.gameworld.WorldTime
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
import net.torvald.terrarum.modulebasegame.ui.UIScreenZoom
import net.torvald.terrarum.savegame.DiskSkimmer
import net.torvald.terrarum.savegame.VDUtil
import net.torvald.terrarum.serialise.Common
import net.torvald.terrarum.serialise.PointOfInterest
import net.torvald.terrarum.serialise.POILayer
@@ -61,7 +62,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
- Set…
""".trimIndent())
lateinit var gameWorld: GameWorld
lateinit var gameWorld: TheGameWorld
override val musicStreamer = TerrarumMusicAndAmbientStreamer()
@@ -419,7 +420,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
for (x in for_x_start..for_x_end) {
if (wiringCounter >= maxRenderableWires) break
val (wires, nodes) = world.getAllWiresFrom(x, y)
val (wires, nodes) = gameWorld.getAllWiresFrom(x, y)
wires?.forEach {
val wireActor = wireActorsContainer[wiringCounter]
@@ -553,7 +554,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
)
}
private fun getNearbyOres8(x: Int, y: Int): List<OrePlacement> {
return getNearbyTilesPos8(x, y).map { world.getTileFromOre(it.x, it.y) }
return getNearbyTilesPos8(x, y).map { gameWorld.getTileFromOre(it.x, it.y) }
}
private fun makePenWork(x: Int, y: Int) {
@@ -877,8 +878,8 @@ class YamlCommandToolExportTest : YamlInvokable {
ui.world.tileNameToNumberMap
)
val layer = POILayer(name)
val terr = BlockLayerGenericI16(poi.w, poi.h)
val wall = BlockLayerGenericI16(poi.w, poi.h)
val terr = BlockLayerInMemoryI16(poi.w, poi.h)
val wall = BlockLayerInMemoryI16(poi.w, poi.h)
layer.blockLayer = arrayListOf(terr, wall)
poi.layers.add(layer)
@@ -934,8 +935,13 @@ class YamlCommandNewFlatTerrain : YamlInvokable {
println("[BuildingMaker] Generating builder world...")
val tempFile = FileHandle.tempFile("terrarumbuildingmaker").file()
val tempDisk = VDUtil.createNewDisk(1L shl 30, "buildingmaker", Common.CHARSET)
VDUtil.dumpToRealMachine(tempDisk, tempFile)
val tempDiskSkimmer = DiskSkimmer(tempFile)
val timeNow = System.currentTimeMillis() / 1000
ui.gameWorld = GameWorld(90*12, 90*4, timeNow, timeNow)
ui.gameWorld = TheGameWorld(90*12, 90*4, tempDiskSkimmer, timeNow, timeNow)
// remove null tiles
for (y in 0 until ui.gameWorld.height) {

View File

@@ -4,9 +4,8 @@ import net.torvald.terrarum.BlockCodex
import net.torvald.terrarum.ItemCodex
import net.torvald.terrarum.OreCodex
import net.torvald.terrarum.ceilToInt
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.getOffset
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
import net.torvald.unsafe.UnsafeHelper
import java.util.concurrent.*
@@ -34,7 +33,7 @@ object ExplosionManager {
val lineMax = world.height - ty + CALC_RADIUS
// create a copy of the tilemap
val tilemap = BlockLayerGenericI16(CALC_WIDTH, CALC_WIDTH)
val tilemap = BlockLayerInMemoryI16(CALC_WIDTH, CALC_WIDTH)
val breakmap = UnsafeFloatArray(CALC_WIDTH, CALC_WIDTH)
// fill in the tilemap copy
@@ -69,9 +68,9 @@ object ExplosionManager {
}.start()
}
private fun memcpyFromWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerGenericI16) {
private fun memcpyFromWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerInMemoryI16) {
// if the bounding box must wrap around
if (xStart > world.width - CALC_RADIUS) {
/*if (xStart > world.width - CALC_RADIUS) {
val lenLeft = world.width - xStart
val lenRight = CALC_WIDTH - lenLeft
@@ -98,12 +97,18 @@ object ExplosionManager {
out.getOffset(0, yOff),
world.layerTerrain.bytesPerBlock * CALC_WIDTH
)
}*/
// temporary: copy one by one
for (ox in xStart until xStart + CALC_WIDTH) {
val (x, y) = world.coerceXY(ox, yStart + yOff)
val tileInWorld = world.layerTerrain.unsafeGetTile(x, y)
out.unsafeSetTile(x, y, tileInWorld)
}
}
private fun memcpyToWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerGenericI16) {
private fun memcpyToWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerInMemoryI16) {
// if the bounding box must wrap around
if (xStart > world.width - CALC_RADIUS) {
/*if (xStart > world.width - CALC_RADIUS) {
val lenLeft = world.width - xStart
val lenRight = CALC_WIDTH - lenLeft
@@ -130,6 +135,12 @@ object ExplosionManager {
world.layerTerrain.getOffset(xStart, yStart + yOff),
world.layerTerrain.bytesPerBlock * CALC_WIDTH
)
}*/
// temporary: copy one by one
for (ox in xStart until xStart + CALC_WIDTH) {
val (x, y) = world.coerceXY(ox, yStart + yOff)
val tileInWorld = out.unsafeGetTile(x, y)
world.layerTerrain.unsafeSetTile(x, y, tileInWorld)
}
}
@@ -155,7 +166,7 @@ object ExplosionManager {
CALC_RADIUS: Int, CALC_WIDTH: Int,
world: GameWorld,
breakmap: UnsafeFloatArray,
tilemap: BlockLayerGenericI16,
tilemap: BlockLayerInMemoryI16,
tx: Int, ty: Int,
power: Float,
dropProbNonOre: Float,

View File

@@ -17,7 +17,6 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.FluidCodex
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.METER
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.PHYS_EPSILON_DIST
@@ -28,6 +27,7 @@ import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.mouseInInteractableRange
import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.modulebasegame.gameitems.ItemThrowable
@@ -44,8 +44,6 @@ import kotlin.math.min
import kotlin.system.exitProcess
/**
* This will be rendered to a postprocessor FBO.
*
@@ -131,7 +129,7 @@ object IngameRenderer : Disposable {
//var renderingParticleCount = 0
// private set
var world: GameWorld = GameWorld.makeNullWorld()
var world: GameWorld = TheGameWorld.makeNullWorld()
private set // the grammar "IngameRenderer.world = gameWorld" seemes mundane and this function needs special care!
private var newWorldLoadedLatch = false
@@ -393,11 +391,16 @@ object IngameRenderer : Disposable {
blendNormalStraightAlpha(batch)
val (vo, vg) = world.weatherbox.let {
if (it.currentWeather.identifier == "titlescreen")
1f to 1f
else
it.currentVibrancy.x to it.currentVibrancy.y
val (vo, vg) = if (world is TheGameWorld) {
(world as TheGameWorld).weatherbox.let {
if (it.currentWeather.identifier == "titlescreen")
1f to 1f
else
it.currentVibrancy.x to it.currentVibrancy.y
}
}
else {
1f to 1f
}
mixedOutTex.texture.bind(0)

View File

@@ -28,6 +28,7 @@ import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.mouseInInteractableRange
import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.*
@@ -46,6 +47,7 @@ import net.torvald.terrarum.modulebasegame.worldgenerator.WorldgenParams
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
import net.torvald.terrarum.savegame.DiskSkimmer
import net.torvald.terrarum.savegame.VDUtil
import net.torvald.terrarum.savegame.VirtualDisk
import net.torvald.terrarum.serialise.Common
@@ -348,7 +350,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
data class Codices(
val disk: VirtualDisk, // WORLD disk
val world: GameWorld,
val world: TheGameWorld,
// val meta: WriteMeta.WorldMeta,
// val block: BlockCodex,
// val item: ItemCodex,
@@ -383,7 +385,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
// feed info to the worldgen
Worldgen.attachMap(world, WorldgenParams.getParamsByVersion(codices.worldGenver, world.generatorSeed))
if (world is TheGameWorld)
Worldgen.attachMap(world as TheGameWorld, WorldgenParams.getParamsByVersion(codices.worldGenver, world.generatorSeed))
}
loadCallback = codices.callbackAfterLoad
@@ -443,7 +446,6 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
}
}
// try to unstuck the repositioned player
codices.player.tryUnstuck()
@@ -520,13 +522,18 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
}
else {
App.getLoadScreen().addMessage("${App.GAME_NAME} ${App.getVERSION_STRING()}")
App.getLoadScreen().addMessage("Creating new world")
val worldFile = getWorldSaveFiledesc(worldSavefileName)
VDUtil.dumpToRealMachine(worldDisk, worldFile)
val skimmer = DiskSkimmer(worldFile)
// init map as chosen size
val timeNow = App.getTIME_T()
world = GameWorld(worldParams.width, worldParams.height, timeNow, timeNow) // new game, so the creation time is right now
world = TheGameWorld(worldParams.width, worldParams.height, skimmer, timeNow, timeNow) // new game, so the creation time is right now
world.generatorSeed = worldParams.worldGenSeed
//gameworldIndices.add(world.worldIndex)
world.extraFields["basegame.economy"] = GameEconomy()

View File

@@ -24,18 +24,15 @@ import net.torvald.terrarum.gameactors.ai.ActorAI
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.WorldTime
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.gameworld.*
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.serialise.ReadSimpleWorld
import net.torvald.terrarum.serialise.ReadTitlescreenGameWorld
import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemTextButton
import net.torvald.terrarum.utils.OpenURL
import net.torvald.terrarum.weather.WeatherMixer
import net.torvald.terrarum.worlddrawer.WorldCamera
@@ -69,7 +66,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
//private var loadDone = false // not required; draw-while-loading is implemented in the AppLoader
private lateinit var demoWorld: GameWorld
private lateinit var demoWorld: TitlescreenGameWorld
private lateinit var cameraNodes: FloatArray // camera Y-pos
private val cameraNodeWidth = 15
private val lookaheadDist = cameraNodeWidth * TILE_SIZED
@@ -165,19 +162,19 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
val file = ModMgr.getFile("basegame", "demoworld")
val reader = java.io.FileReader(file)
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
val world = ReadSimpleWorld(reader, file)
val world = ReadTitlescreenGameWorld(reader, file)
demoWorld = world
demoWorld.worldTime.timeDelta = 30
printdbg(this, "Demo world loaded")
}
catch (e: IOException) {
demoWorld = GameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H, 0L, 0L)
demoWorld = TitlescreenGameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H)
demoWorld.worldTime.timeDelta = 30
printdbg(this, "Demo world not found, using empty world")
}
demoWorld.renumberTilesAfterLoad()
this.world = demoWorld
demoWorld.renumberTilesAfterLoad()
// set initial time to summer
demoWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
@@ -365,7 +362,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
gdxClearAndEnableBlend(.64f, .754f, .84f, 1f)
if (!demoWorld.layerTerrain.ptr.destroyed) { // FIXME q&d hack to circumvent the dangling pointer issue #26
if (!demoWorld.disposed) { // FIXME q&d hack to circumvent the dangling pointer issue #26
WorldCamera.update(demoWorld, cameraPlayer)
IngameRenderer.invoke(

View File

@@ -12,6 +12,7 @@ import net.torvald.terrarum.gameactors.Controllable
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.modulebasegame.TerrarumIngame.Companion.inUpdateRange
import net.torvald.terrarum.modulebasegame.gameactors.*
import net.torvald.terrarum.modulebasegame.gameitems.AxeCore

View File

@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import net.torvald.terrarum.*
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.ui.Toolkit
import kotlin.math.roundToInt
@@ -96,7 +97,7 @@ class WorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidt
try {
// q&d solution for the dangling pointer; i'm doing this only because it's this fucking load screen that's fucking the dead pointer
if (!world.layerTerrain.ptrDestroyed) {
if (!world.layerTerrain.disposed) {
val outCol = if (BlockCodex[world.getTileFromTerrain(wx, wy)].isSolid) COL_TERR
else if (BlockCodex[world.getTileFromWall(wx, wy)].isSolid) COL_WALLED
else COL_AIR

View File

@@ -4,9 +4,9 @@ import net.torvald.terrarum.App
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.gameworld.SimpleGameWorld
import net.torvald.terrarum.gameworld.TitlescreenGameWorld
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.serialise.WriteSimpleWorld
import net.torvald.terrarum.serialise.WriteTitlescreenGameWorld
import java.io.File
import java.io.IOException
@@ -21,12 +21,12 @@ object ExportWorld : ConsoleCommand {
try {
val ingame = Terrarum.ingame!! as TerrarumIngame
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
val simpleworld = SimpleGameWorld(ingame.world.width, ingame.world.height).also {
val simpleworld = TitlescreenGameWorld(ingame.world.width, ingame.world.height).also {
it.layerTerrain = ingame.world.layerTerrain
it.layerWall = ingame.world.layerWall
it.tileNumberToNameMap.putAll(ingame.world.tileNumberToNameMap)
}
file.writeText(WriteSimpleWorld(ingame, simpleworld, listOf()))
file.writeText(WriteTitlescreenGameWorld(ingame, simpleworld, listOf()))
Echo("Exportworld: exported the world as ${args[1]}.json")
}
catch (e: IOException) {

View File

@@ -5,7 +5,7 @@ import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.serialise.ReadSimpleWorld
import net.torvald.terrarum.serialise.ReadTitlescreenGameWorld
import java.io.File
import java.io.IOException
@@ -20,7 +20,7 @@ object ImportWorld : ConsoleCommand {
try {
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
val reader = java.io.FileReader(file)
ReadSimpleWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader, file)
ReadTitlescreenGameWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader, file)
Echo("Importworld: imported a world from ${args[1]}.json")
}
catch (e: IOException) {

View File

@@ -9,6 +9,7 @@ import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameitems.isWall
import net.torvald.terrarum.gameitems.mouseInInteractableRange
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase

View File

@@ -2,10 +2,11 @@ package net.torvald.terrarum.modulebasegame.serialise
import net.torvald.terrarum.*
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16
import net.torvald.terrarum.gameworld.BlockLayerOresI16I8
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.*
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
import net.torvald.terrarum.gameworld.GameWorld.Companion.ORES
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.FancyWorldReadLoadScreen
import net.torvald.terrarum.modulebasegame.TerrarumIngame
@@ -60,11 +61,10 @@ object LoadSavegame {
val worldDiskSavegameInfo = ByteArray64Reader(worldDisk.getFile(VDFileID.SAVEGAMEINFO)!!.bytes, Common.CHARSET)
val world = ReadWorld(worldDiskSavegameInfo, worldDisk.diskFile)
world.layerTerrain = BlockLayerGenericI16(world.width, world.height)
world.layerWall = BlockLayerGenericI16(world.width, world.height)
world.layerOres = BlockLayerOresI16I8(world.width, world.height)
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height)
world.layerTerrain = BlockLayerGenericI16(world.width, world.height, worldDisk, TERRAIN, world)
world.layerWall = BlockLayerGenericI16(world.width, world.height, worldDisk, WALL, world)
world.layerOres = BlockLayerOresI16I8(world.width, world.height, worldDisk, ORES, world)
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height, worldDisk, FLUID, world)
world.chunkFlags = Array(world.height / LandUtil.CHUNK_H) { ByteArray(world.width / LandUtil.CHUNK_W) }
newIngame.world = world // must be set before the loadscreen, otherwise the loadscreen will try to read from the NullWorld which is already destroyed
@@ -119,7 +119,7 @@ object LoadSavegame {
val (cx, cy) = LandUtil.chunkNumToChunkXY(world, chunk)
ReadWorld.decodeChunkToLayer(chunkFile.getContent(), worldLayer[layer]!!, cx, cy)
world.chunkFlags[cy][cx] = world.chunkFlags[cy][cx] or GameWorld.CHUNK_LOADED
world.chunkFlags[cy][cx] = world.chunkFlags[cy][cx] or TheGameWorld.CHUNK_LOADED
}
}
loadscreen.progress.getAndAdd(1)

View File

@@ -4,6 +4,7 @@ import net.torvald.gdx.graphics.PixmapIO2
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.TerrarumAppConfiguration
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
@@ -118,7 +119,7 @@ class QuickSingleplayerWorldSavingThread(
// println("Chunk xy from number $chunkNumber -> (${chunkXY.x}, ${chunkXY.y})")
if (chunkFlag and 0x7F == GameWorld.CHUNK_LOADED) {
if (chunkFlag and 0x7F == TheGameWorld.CHUNK_LOADED) {
val chunkBytes = WriteWorld.encodeChunk(layer, cx, cy)
val entryID = 0x1_0000_0000L or layerNum.toLong().shl(24) or chunkNumber.toLong()

View File

@@ -2,11 +2,11 @@ package net.torvald.terrarum.modulebasegame.serialise
import net.torvald.gdx.graphics.PixmapIO2
import net.torvald.terrarum.*
import net.torvald.terrarum.gameworld.GameWorld.Companion.CHUNK_LOADED
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
import net.torvald.terrarum.gameworld.GameWorld.Companion.ORES
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
import net.torvald.terrarum.gameworld.TheGameWorld.Companion.CHUNK_LOADED
import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase

View File

@@ -5,6 +5,7 @@ import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.NoSerialise
import net.torvald.terrarum.gameworld.BlockLayer
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
@@ -95,12 +96,12 @@ object WriteWorld {
*/
object ReadWorld {
operator fun invoke(worldDataStream: Reader, origin: File?): GameWorld =
Common.jsoner.fromJson(GameWorld::class.java, worldDataStream).also {
operator fun invoke(worldDataStream: Reader, origin: File?): TheGameWorld =
Common.jsoner.fromJson(TheGameWorld::class.java, worldDataStream).also {
fillInDetails(origin, it)
}
private fun fillInDetails(origin: File?, world: GameWorld) {
private fun fillInDetails(origin: File?, world: TheGameWorld) {
world.tileNumberToNameMap.forEach { l, s ->
world.tileNameToNumberMap[s] = l.toInt()
}

View File

@@ -15,7 +15,6 @@ import net.torvald.terrarum.serialise.toBig64
import net.torvald.terrarum.toInt
import net.torvald.terrarum.utils.OrePlacement
import net.torvald.terrarum.worlddrawer.BlocksDrawer
import kotlin.math.max
/**
* Created by minjaesong on 2023-10-26.

View File

@@ -10,6 +10,7 @@ import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.BlockAddress
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.TerrarumIngame
@@ -163,14 +164,14 @@ object Worldgen {
val jobs = getJobs()
printdbg(this, "Generating chunk on ($cx, $cy)")
Thread {
world.chunkFlags[cy][cx] = GameWorld.CHUNK_GENERATING
world.chunkFlags[cy][cx] = TheGameWorld.CHUNK_GENERATING
for (i in jobs.indices) {
val it = jobs[i]
it.theWork.getChunkDone(cx, cy)
}
world.chunkFlags[cy][cx] = GameWorld.CHUNK_LOADED
world.chunkFlags[cy][cx] = TheGameWorld.CHUNK_LOADED
callback(cx, cy)
}.let {
it.priority = 2
@@ -566,7 +567,7 @@ abstract class Gen(val world: GameWorld, val isFinal: Boolean, val seed: Long, v
draw(chunkX * LandUtil.CHUNK_W, chunkY * CHUNK_H, localJoise, sampleOffset)
loadscreen?.progress?.addAndGet(1L)
world.chunkFlags[chunkY][chunkX] = if (isFinal) GameWorld.CHUNK_LOADED else GameWorld.CHUNK_GENERATING
world.chunkFlags[chunkY][chunkX] = if (isFinal) TheGameWorld.CHUNK_LOADED else TheGameWorld.CHUNK_GENERATING
}
}
}

View File

@@ -10,8 +10,9 @@ import io.airlift.compress.zstd.ZstdOutputStream
import net.torvald.random.HQRNG
import net.torvald.terrarum.*
import net.torvald.terrarum.console.EchoError
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.gameworld.WorldTime
import net.torvald.terrarum.savegame.ByteArray64
import net.torvald.terrarum.savegame.ByteArray64GrowableOutputStream
@@ -41,7 +42,7 @@ object Common {
val CHARSET = Charsets.UTF_8
/** dispose of the `offendingObject` after rejection! */
class BlockLayerHashMismatchError(val oldHash: String, val newHash: String, val offendingObject: BlockLayerGenericI16) : Error("Old Hash $oldHash != New Hash $newHash")
class BlockLayerHashMismatchError(val oldHash: String, val newHash: String, val offendingObject: BlockLayerInMemoryI16) : Error("Old Hash $oldHash != New Hash $newHash")
private fun Byte.tostr() = this.toInt().and(255).toString(16).padStart(2,'0')
private val digester = DigestUtils.getSha256Digest()
@@ -74,8 +75,8 @@ object Common {
}
})
// BlockLayer
it.setSerializer(BlockLayerGenericI16::class.java, object : Json.Serializer<BlockLayerGenericI16> {
override fun write(json: Json, obj: BlockLayerGenericI16, knownType: Class<*>?) {
it.setSerializer(BlockLayerInMemoryI16::class.java, object : Json.Serializer<BlockLayerInMemoryI16> {
override fun write(json: Json, obj: BlockLayerInMemoryI16, knownType: Class<*>?) {
digester.reset()
obj.bytesIterator().forEachRemaining { digester.update(it) }
val hash = StringBuilder().let { sb -> digester.digest().forEach { sb.append(it.tostr()) }; sb.toString() }
@@ -85,7 +86,7 @@ object Common {
json.writeValue(layer)
}
override fun read(json: Json, jsonData: JsonValue, type: Class<*>): BlockLayerGenericI16 {
override fun read(json: Json, jsonData: JsonValue, type: Class<*>): BlockLayerInMemoryI16 {
// full manual
try {
return strToBlockLayer(LayerInfo(
@@ -435,12 +436,12 @@ object Common {
* @param b a BlockLayer
* @return Bytes in [b] which are GZip'd then Ascii85-encoded
*/
private fun blockLayerToStr(b: BlockLayerGenericI16): String {
private fun blockLayerToStr(b: BlockLayerInMemoryI16): String {
return bytesToZipdStr(b.bytesIterator())
}
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayerGenericI16 {
val layer = BlockLayerGenericI16(layerInfo.x, layerInfo.y)
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayerInMemoryI16 {
val layer = BlockLayerInMemoryI16(layerInfo.x, layerInfo.y)
val unzipdBytes = strToBytes(StringReader(layerInfo.b))
// write to blocklayer and the digester

View File

@@ -6,6 +6,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
@@ -128,7 +129,7 @@ class POILayer(
constructor() : this("undefined")
@Transient var name = name
@Transient internal lateinit var blockLayer: ArrayList<BlockLayerGenericI16>
@Transient internal lateinit var blockLayer: ArrayList<BlockLayerInMemoryI16>
@Transient internal lateinit var dat: Array<ByteArray>
@Deprecated("Used for debug print", ReplaceWith("name")) @Transient internal var id = ""
@@ -179,10 +180,10 @@ class POILayer(
if (::blockLayer.isInitialized) {
blockLayer.forEach { it.dispose() }
}
blockLayer = ArrayList<BlockLayerGenericI16>()
blockLayer = ArrayList()
dat.forEachIndexed { layerIndex, layer ->
val currentBlockLayer = BlockLayerGenericI16(width, height).also {
val currentBlockLayer = BlockLayerInMemoryI16(width, height).also {
blockLayer.add(it)
}
for (w in 0 until layer.size / byteLength) {

View File

@@ -4,56 +4,53 @@ import net.torvald.terrarum.App
import net.torvald.terrarum.IngameInstance
import net.torvald.terrarum.ItemCodex
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16
import net.torvald.terrarum.gameworld.BlockLayerOresI16I8
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.SimpleGameWorld
import net.torvald.terrarum.gameworld.*
import net.torvald.terrarum.modulebasegame.IngameRenderer
import java.io.File
import java.io.Reader
/**
* Created by minjaesong on 2022-09-03.
*/
object ReadSimpleWorld {
object ReadTitlescreenGameWorld {
operator fun invoke(worldDataStream: Reader, origin: File?): GameWorld =
Common.jsoner.fromJson(SimpleGameWorld::class.java, worldDataStream).also {
operator fun invoke(worldDataStream: Reader, origin: File?): TitlescreenGameWorld =
Common.jsoner.fromJson(TitlescreenGameWorld::class.java, worldDataStream).also {
fillInDetails(origin, it)
}
private fun fillInDetails(origin: File?, world: GameWorld) {
private fun fillInDetails(origin: File?, world: TitlescreenGameWorld) {
world.tileNumberToNameMap.forEach { l, s ->
world.tileNameToNumberMap[s] = l.toInt()
}
world.layerOres = BlockLayerOresI16I8(world.width, world.height)
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height)
world.layerOres = BlockLayerInMemoryI16I8(world.width, world.height)
world.layerFluids = BlockLayerInMemoryI16F16(world.width, world.height)
ItemCodex.loadFromSave(origin, world.dynamicToStaticTable, world.dynamicItemInventory)
}
fun readWorldAndSetNewWorld(ingame: IngameInstance, worldDataStream: Reader, origin: File?): GameWorld {
fun readWorldAndSetNewWorld(ingame: IngameInstance, worldDataStream: Reader, origin: File?): TitlescreenGameWorld {
val world = invoke(worldDataStream, origin)
ingame.world = world
return world
}
}
object WriteSimpleWorld {
object WriteTitlescreenGameWorld {
private fun preWrite(ingame: IngameInstance, time_t: Long, world: SimpleGameWorld, actorsList: List<Actor>) {
private fun preWrite(ingame: IngameInstance, time_t: Long, world: TitlescreenGameWorld, actorsList: List<Actor>) {
val currentPlayTime_t = time_t - ingame.loadedTime_t
world.comp = Common.getCompIndex()
world.lastPlayTime = time_t
world.totalPlayTime += currentPlayTime_t
world.actors.clear()
world.actors.addAll(actorsList.map { it.referenceID }.sorted().distinct())
// world.actors.clear()
// world.actors.addAll(actorsList.map { it.referenceID }.sorted().distinct())
}
operator fun invoke(ingame: IngameInstance, world: SimpleGameWorld, actorsList: List<Actor>): String {
operator fun invoke(ingame: IngameInstance, world: TitlescreenGameWorld, actorsList: List<Actor>): String {
val time_t = App.getTIME_T()
preWrite(ingame, time_t, world, actorsList)
val s = Common.jsoner.toJson(world)

View File

@@ -18,6 +18,7 @@ import net.torvald.terrarum.audio.AudioMixer.Companion.DS_FLTIDX_PAN
import net.torvald.terrarum.audio.dsp.*
import net.torvald.terrarum.controller.TerrarumController
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.imagefont.TinyAlphNum
import net.torvald.terrarum.modulebasegame.IngameRenderer
@@ -315,7 +316,7 @@ class BasicDebugInfoWindow : UICanvas() {
val wallNum = it.getTileFromWall(mouseTileX, mouseTileY)
val tileNum = it.getTileFromTerrain(mouseTileX, mouseTileY)
val (oreNum, orePlacement) = it.getTileFromOre(mouseTileX, mouseTileY)
val wires = it.getAllWiresFrom(mouseTileX, mouseTileY)
val wires = if (it is TheGameWorld) it.getAllWiresFrom(mouseTileX, mouseTileY) else null to null
val fluid = it.getFluid(mouseTileX, mouseTileY)
val wireCount = wires.first?.size?.toString() ?: "no"
val tdmg = it.getTerrainDamage(mouseTileX, mouseTileY).toIntAndFrac(2,2)

View File

@@ -1,8 +1,6 @@
package net.torvald.terrarum.utils
import com.badlogic.gdx.utils.Json
import com.badlogic.gdx.utils.JsonValue
import net.torvald.terrarum.gameactors.ActorValue
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.BlockAddress

View File

@@ -17,9 +17,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.FLUID_MIN_MASS
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.gameworld.*
import net.torvald.terrarum.modulebasegame.worldgenerator.shake
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.serialise.toBig64
@@ -43,7 +41,7 @@ import kotlin.math.roundToInt
internal object BlocksDrawer {
/** World change is managed by IngameRenderer.setWorld() */
internal var world: GameWorld = GameWorld.makeNullWorld()
internal var world: GameWorld = TheGameWorld.makeNullWorld()
/**
@@ -448,6 +446,10 @@ internal object BlocksDrawer {
*/
private fun fillInTileBuffer(mode: Int) {
// don't render fluid and ores for TitlescreenGameWorld (for now)
if (world.layerFluids !is BlockLayerFluidI16F16) return
if (world.layerOres !is BlockLayerOresI16I8) return
// TODO the real fluid rendering must use separate function, but its code should be similar to this.
// shader's tileAtlas will be fluid.tga, pixels written to the buffer is in accordance with the new
// atlas. IngameRenderer must be modified so that fluid-draw call is separated from drawing tiles.
@@ -467,7 +469,7 @@ internal object BlocksDrawer {
WALL -> world.layerWall.unsafeGetTile(wx, wy)
TERRAIN -> world.layerTerrain.unsafeGetTile(wx, wy)
ORES -> world.layerOres.unsafeGetTile(wx, wy)//.also { println(it) }
FLUID -> world.layerFluids.unsafeGetTile1(wx, wy).let { (number, fill) ->
FLUID -> world.layerFluids.unsafeGetTileI16F16(wx, wy).let { (number, fill) ->
if (number == 65535 || fill < 1f/30f) 0
else number
}
@@ -497,7 +499,7 @@ internal object BlocksDrawer {
val nearbyFluidType = fluids.asSequence().filter { it.amount >= 0.5f / 16f }.map { it.type }.filter { it.startsWith("fluid@") }.sorted().firstOrNull()
val fillThis =
world.layerFluids.unsafeGetTile1(wx, wy).second.let { if (it.isNaN()) 0f else it.coerceAtMost(1f) }
world.layerFluids.unsafeGetTileI16F16(wx, wy).second.let { if (it.isNaN()) 0f else it.coerceAtMost(1f) }
val tile = world.getTileFromTerrain(wx, wy)
@@ -671,7 +673,7 @@ internal object BlocksDrawer {
rawTileNum + nearbyTilesInfo
// special case: ores
else if (mode == ORES)
rawTileNum + world.layerOres.unsafeGetTile1(wx, wy).second
rawTileNum + world.layerOres.unsafeGetTileI16I8(wx, wy).second
// rest of the cases: terrain and walls
else rawTileNum + when (renderTag.maskType) {
CreateTileAtlas.RenderTag.MASK_NA -> 0
@@ -1188,7 +1190,7 @@ internal object BlocksDrawer {
get() {
val rate = (((Gdx.graphics.framesPerSecond / 50f) * TILE_SIZEF) / maxOf(WorldCamera.deltaX.abs(), WorldCamera.deltaY.abs()).coerceAtLeast(1)).roundToInt().coerceIn(1, 4)
App.debugTimers.put("Renderer.tilemapUpdateDivider", rate.toLong())
return (!world.layerTerrain.ptrDestroyed && App.GLOBAL_RENDER_TIMER % rate == 0L)
return (!world.layerTerrain.disposed && App.GLOBAL_RENDER_TIMER % rate == 0L)
}
private var camTransX = 0

View File

@@ -1,13 +1,11 @@
package net.torvald.terrarum.worlddrawer
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.jme3.math.FastMath
import net.torvald.colourutil.ColourTemp
import net.torvald.terrarum.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockstats.TileSurvey
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.ui.Toolkit
import kotlin.math.roundToInt
@@ -17,7 +15,7 @@ import kotlin.math.roundToInt
object FeaturesDrawer {
/** World change is managed by IngameRenderer.setWorld() */
internal var world: GameWorld = GameWorld.makeNullWorld()
internal var world: GameWorld = TheGameWorld.makeNullWorld()
//const val TILE_SIZE = TILE_SIZE

View File

@@ -19,6 +19,7 @@ import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.isBlock
import net.torvald.terrarum.gameworld.BlockAddress
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.TheGameWorld
import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.modulebasegame.ui.abs
@@ -43,7 +44,7 @@ import kotlin.math.*
object LightmapRenderer {
/** World change is managed by IngameRenderer.setWorld() */
private var world: GameWorld = GameWorld.makeNullWorld()
private var world: GameWorld = TheGameWorld.makeNullWorld()
//private lateinit var lightCalcShader: ShaderProgram
//private val SHADER_LIGHTING = AppLoader.getConfigBoolean("gpulightcalc")
@@ -141,7 +142,7 @@ object LightmapRenderer {
}
fun recalculate(actorContainer: List<ActorWithBody>) {
if (!world.layerTerrain.ptrDestroyed) _recalculate(actorContainer, lightmap)
if (!world.layerTerrain.disposed) _recalculate(actorContainer, lightmap)
}
private fun _recalculate(actorContainer: List<ActorWithBody>, lightmap: UnsafeCvecArray) {
@@ -153,7 +154,7 @@ object LightmapRenderer {
}
catch (e: NullPointerException) {
System.err.println("[LightmapRendererNew.recalculate] Attempted to refer destroyed unsafe array " +
"(${world.layerTerrain.ptr})")
"(${world.layerTerrain})")
e.printStackTrace()
return // something's wrong but we'll ignore it like a trustful AK
}
@@ -656,7 +657,7 @@ object LightmapRenderer {
internal fun draw(): Texture {
if (!world.layerTerrain.ptrDestroyed) {
if (!world.layerTerrain.disposed) {
// when shader is not used: 0.5 ms on 6700K
App.measureDebugTime("Renderer.LightToScreen") {