mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
Compare commits
5 Commits
426f0b0aab
...
world-chun
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc3c1c1b14 | ||
|
|
0eccc4dbea | ||
|
|
4c9db1ef60 | ||
|
|
83906e7930 | ||
|
|
39cfc3a4d9 |
@@ -31,6 +31,7 @@ import net.torvald.terrarum.gamecontroller.KeyToggler;
|
|||||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent;
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent;
|
||||||
import net.torvald.terrarum.gameitems.GameItem;
|
import net.torvald.terrarum.gameitems.GameItem;
|
||||||
import net.torvald.terrarum.gameworld.GameWorld;
|
import net.torvald.terrarum.gameworld.GameWorld;
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld;
|
||||||
import net.torvald.terrarum.imagefont.BigAlphNum;
|
import net.torvald.terrarum.imagefont.BigAlphNum;
|
||||||
import net.torvald.terrarum.imagefont.TinyAlphNum;
|
import net.torvald.terrarum.imagefont.TinyAlphNum;
|
||||||
import net.torvald.terrarum.langpack.Lang;
|
import net.torvald.terrarum.langpack.Lang;
|
||||||
@@ -1016,7 +1017,7 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
ModMgr.INSTANCE.disposeMods();
|
ModMgr.INSTANCE.disposeMods();
|
||||||
|
|
||||||
GameWorld.Companion.makeNullWorld().dispose();
|
TheGameWorld.Companion.makeNullWorld().dispose();
|
||||||
|
|
||||||
Terrarum.INSTANCE.dispose();
|
Terrarum.INSTANCE.dispose();
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import net.torvald.terrarum.gamecontroller.KeyToggler
|
|||||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
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.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
@@ -105,7 +107,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
printStackTrace(this)
|
printStackTrace(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
open var world: GameWorld = GameWorld.makeNullWorld()
|
open var world: GameWorld = TheGameWorld.makeNullWorld()
|
||||||
set(value) {
|
set(value) {
|
||||||
val oldWorld = field
|
val oldWorld = field
|
||||||
newWorldLoadedLatch = true
|
newWorldLoadedLatch = true
|
||||||
|
|||||||
@@ -2,26 +2,17 @@ package net.torvald.terrarum.blockstats
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.Pixmap
|
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.Disposable
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
|
||||||
import com.badlogic.gdx.utils.Queue
|
|
||||||
import net.torvald.terrarum.App
|
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.concurrent.ThreadExecutor
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
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_HEIGHT
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_WIDTH
|
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_WIDTH
|
||||||
import net.torvald.terrarum.sqr
|
|
||||||
import net.torvald.terrarum.toInt
|
import net.torvald.terrarum.toInt
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.Companion.WALL_OVERLAY_COLOUR
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.Companion.WALL_OVERLAY_COLOUR
|
||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
|
||||||
import kotlin.math.absoluteValue
|
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
object MinimapComposer : Disposable {
|
object MinimapComposer : Disposable {
|
||||||
|
|
||||||
@@ -32,7 +23,7 @@ object MinimapComposer : Disposable {
|
|||||||
val MINIMAP_TILE_WIDTH = (MINIMAP_WIDTH.toInt() * 3) / SQUARE_SIZE + 4
|
val MINIMAP_TILE_WIDTH = (MINIMAP_WIDTH.toInt() * 3) / SQUARE_SIZE + 4
|
||||||
val MINIMAP_TILE_HEIGHT = (MINIMAP_HEIGHT.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) {
|
fun setWorld(world: GameWorld) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.torvald.terrarum.console
|
package net.torvald.terrarum.console
|
||||||
|
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
|
import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8,7 +9,7 @@ import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
|
|||||||
*/
|
*/
|
||||||
internal object GetGR : ConsoleCommand {
|
internal object GetGR : ConsoleCommand {
|
||||||
override fun execute(args: Array<String>) {
|
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
|
// check if args[1] is number or not
|
||||||
if (args.size > 1 && !args[1].isNum()) { // args[1] is Gamerule name
|
if (args.size > 1 && !args[1].isNum()) { // args[1] is Gamerule name
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import net.torvald.terrarum.gameitems.ItemID
|
|||||||
import net.torvald.terrarum.gameparticles.createRandomBlockParticle
|
import net.torvald.terrarum.gameparticles.createRandomBlockParticle
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.itemproperties.Calculate
|
import net.torvald.terrarum.itemproperties.Calculate
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
|
|||||||
@@ -5,17 +5,48 @@ import com.badlogic.gdx.utils.Disposable
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-10-10.
|
* Created by minjaesong on 2023-10-10.
|
||||||
*/
|
*/
|
||||||
interface BlockLayer : Disposable {
|
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) { }
|
||||||
|
|
||||||
val width: Int
|
open fun unsafeGetTile(x: Int, y: Int): Int = 0
|
||||||
val height: Int
|
|
||||||
val bytesPerBlock: Long
|
open fun getOffset(x: Int, y: Int): Long {
|
||||||
fun unsafeToBytes(x: Int, y: Int): ByteArray
|
return this.bytesPerBlock * (y * this.width + x)
|
||||||
fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray)
|
}
|
||||||
fun unsafeGetTile(x: Int, y: Int): Int
|
|
||||||
|
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) { }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun BlockLayer.getOffset(x: Int, y: Int): Long {
|
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 {
|
||||||
return this.bytesPerBlock * (y * this.width + x)
|
return this.bytesPerBlock * (y * this.width + x)
|
||||||
}
|
}*/
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||||
|
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
|
||||||
import net.torvald.unsafe.UnsafePtr
|
|
||||||
import net.torvald.util.Float16
|
import net.torvald.util.Float16
|
||||||
|
|
||||||
const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smaller than epsilon of float16)
|
const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smaller than epsilon of float16)
|
||||||
@@ -15,97 +14,81 @@ 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
|
* * 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 BlockLayerI16F16(override val width: Int, override val height: Int) : BlockLayer {
|
class BlockLayerFluidI16F16 : BlockLayerWithChunkPool {
|
||||||
|
|
||||||
|
override val width: Int
|
||||||
|
override val height: Int
|
||||||
|
override val chunkPool: ChunkPool
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
disk: ClusteredFormatDOM,
|
||||||
|
layerNum: Int,
|
||||||
|
world: TheGameWorld
|
||||||
|
) {
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
|
||||||
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
disk: DiskSkimmer,
|
||||||
|
layerNum: Int,
|
||||||
|
world: TheGameWorld
|
||||||
|
) {
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
|
||||||
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
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 {
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
val offset = getOffset(x, y)
|
return unsafeGetTileI16F16(x, y).first
|
||||||
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> {
|
override fun unsafeGetTileI16F16(x: Int, y: Int): Pair<Int, Float> {
|
||||||
val offset = getOffset(x, y)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
val lsb = ptr[offset]
|
return chunkPool.getTileI16F16(chunk, ox, oy)
|
||||||
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 {
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
val offset = getOffset(x, y)
|
val (tile, fill0) = unsafeGetTileI16F16(x, y)
|
||||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 3], ptr[offset + 2])
|
val fill = Float16.fromFloat(fill0).toUint()
|
||||||
|
return byteArrayOf(
|
||||||
|
((tile ushr 8) and 255).toByte(),
|
||||||
|
(tile and 255).toByte(),
|
||||||
|
((fill ushr 8) and 255).toByte(),
|
||||||
|
(fill and 255).toByte(), )
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||||
val offset = getOffset(x, y)
|
throw UnsupportedOperationException()
|
||||||
val hbits = Float16.fromFloat(fill).toInt().and(0xFFFF)
|
}
|
||||||
|
|
||||||
val tile = if (fill < FLUID_MIN_MASS) 0 else tile0
|
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
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, 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))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
val offset = getOffset(x, y)
|
val tile = bytes[1].toUint().shl(8) or bytes[0].toUint()
|
||||||
ptr[offset] = bytes[1]
|
val fill = Float16.toFloat((bytes[3].toUint().shl(8) or bytes[2].toUint()).toShort())
|
||||||
ptr[offset + 1] = bytes[0]
|
unsafeSetTile(x, y, tile, fill)
|
||||||
ptr[offset + 2] = bytes[3]
|
|
||||||
ptr[offset + 3] = bytes[2]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,14 +106,18 @@ class BlockLayerI16F16(override val width: Int, override val height: Int) : Bloc
|
|||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
|
override var disposed: Boolean = false
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
ptr.destroy()
|
chunkPool.dispose()
|
||||||
App.printdbg(this, "BlockLayerI16F16 with ptr ($ptr) successfully freed")
|
disposed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString("BlockLayerI16F16")
|
override fun toString(): String = "BlockLayerI16F16 (${width}x$height)"
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val BYTES_PER_BLOCK = 4L
|
@Transient val BYTES_PER_BLOCK = 4L
|
||||||
|
|
||||||
|
private fun Short.toUint() = this.toInt().and(65535)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
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.TERRAIN
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||||
|
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
|
||||||
import net.torvald.unsafe.UnsafePtr
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memory layout:
|
* Memory layout:
|
||||||
@@ -18,89 +15,89 @@ import net.torvald.unsafe.UnsafePtr
|
|||||||
*
|
*
|
||||||
* Original version Created by minjaesong on 2016-01-17.
|
* Original version Created by minjaesong on 2016-01-17.
|
||||||
* Unsafe version Created by minjaesong on 2019-06-08.
|
* 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
|
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
|
||||||
*/
|
*/
|
||||||
class BlockLayerI16(
|
class BlockLayerGenericI16: BlockLayerWithChunkPool {
|
||||||
override val width: Int,
|
|
||||||
override val height: Int,
|
|
||||||
disk: ClusteredFormatDOM,
|
|
||||||
layerNum: Int,
|
|
||||||
world: GameWorld
|
|
||||||
): BlockLayer() {
|
|
||||||
|
|
||||||
override val chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, when (layerNum) {
|
override val width: Int
|
||||||
TERRAIN -> ChunkPool.getRenameFunTerrain(world)
|
override val height: Int
|
||||||
WALL -> ChunkPool.getRenameFunTerrain(world)
|
override val chunkPool: ChunkPool
|
||||||
else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum")
|
|
||||||
})
|
private var _hashcode = 0
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
disk: ClusteredFormatDOM,
|
||||||
|
layerNum: Int,
|
||||||
|
world: TheGameWorld
|
||||||
|
) {
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
|
||||||
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, when (layerNum) {
|
||||||
|
TERRAIN -> ChunkPool.getRenameFunTerrain(world)
|
||||||
|
WALL -> ChunkPool.getRenameFunTerrain(world)
|
||||||
|
else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum")
|
||||||
|
})
|
||||||
|
|
||||||
|
_hashcode = disk.uuid.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
disk: DiskSkimmer,
|
||||||
|
layerNum: Int,
|
||||||
|
world: TheGameWorld
|
||||||
|
) {
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
|
||||||
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, when (layerNum) {
|
||||||
|
TERRAIN -> ChunkPool.getRenameFunTerrain(world)
|
||||||
|
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 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 {
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
val offset = getOffset(x, y)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
val lsb = ptr[offset]
|
return chunkPool.getTileI16(chunk, ox, oy)
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
|
|
||||||
return lsb.toUint() or msb.toUint().shl(8)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
val offset = getOffset(x, y)
|
val bytes = unsafeGetTile(x, y)
|
||||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0])
|
return byteArrayOf(
|
||||||
|
((bytes ushr 8) and 255).toByte(),
|
||||||
|
(bytes and 255).toByte()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||||
val offset = getOffset(x, y)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
|
chunkPool.setTileRaw(chunk, ox, oy, tile)
|
||||||
|
}
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||||
// try {
|
throw UnsupportedOperationException()
|
||||||
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) {
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
val offset = getOffset(x, y)
|
val tile = (0..1).fold(0) { acc, i -> acc or (bytes[i].toUint()).shl(8*i) }
|
||||||
ptr[offset] = bytes[1]
|
unsafeSetTile(x, y, tile)
|
||||||
ptr[offset + 1] = bytes[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,12 +115,14 @@ class BlockLayerI16(
|
|||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
|
override var disposed: Boolean = false
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
ptr.destroy()
|
chunkPool.dispose()
|
||||||
printdbg(this, "BlockLayerI16 with ptr ($ptr) successfully freed")
|
disposed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString("BlockLayerI16")
|
override fun toString(): String = "BlockLayerI16 (${width}x$height)"
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val BYTES_PER_BLOCK = 2L
|
@Transient val BYTES_PER_BLOCK = 2L
|
||||||
|
|||||||
133
src/net/torvald/terrarum/gameworld/BlockLayerInMemoryI16.kt
Normal file
133
src/net/torvald/terrarum/gameworld/BlockLayerInMemoryI16.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
145
src/net/torvald/terrarum/gameworld/BlockLayerInMemoryI16F16.kt
Normal file
145
src/net/torvald/terrarum/gameworld/BlockLayerInMemoryI16F16.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
151
src/net/torvald/terrarum/gameworld/BlockLayerInMemoryI16I8.kt
Normal file
151
src/net/torvald/terrarum/gameworld/BlockLayerInMemoryI16I8.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||||
|
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
|
||||||
import net.torvald.unsafe.UnsafePtr
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memory layout:
|
* Memory layout:
|
||||||
@@ -11,105 +10,85 @@ 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 ||
|
* 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
|
* 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 (override val width: Int, override val height: Int) : BlockLayer {
|
class BlockLayerOresI16I8 : BlockLayerWithChunkPool {
|
||||||
|
|
||||||
|
override val width: Int
|
||||||
|
override val height: Int
|
||||||
|
override val chunkPool: ChunkPool
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
disk: ClusteredFormatDOM,
|
||||||
|
layerNum: Int,
|
||||||
|
world: TheGameWorld
|
||||||
|
) {
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
|
||||||
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
disk: DiskSkimmer,
|
||||||
|
layerNum: Int,
|
||||||
|
world: TheGameWorld
|
||||||
|
) {
|
||||||
|
this.width = width
|
||||||
|
this.height = height
|
||||||
|
|
||||||
|
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
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 {
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
val offset = getOffset(x, y)
|
return unsafeGetTileI16I8(x, y).first
|
||||||
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> {
|
override fun unsafeGetTileI16I8(x: Int, y: Int): Pair<Int, Int> {
|
||||||
val offset = getOffset(x, y)
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
val lsb = ptr[offset]
|
return chunkPool.getTileI16I8(chunk, ox, oy)
|
||||||
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 {
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
val offset = getOffset(x, y)
|
val (tile, fill) = unsafeGetTileI16I8(x, y)
|
||||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 2])
|
return byteArrayOf(
|
||||||
|
((tile ushr 8) and 255).toByte(),
|
||||||
|
(tile and 255).toByte(),
|
||||||
|
(fill and 255).toByte()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||||
val offset = getOffset(x, y)
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||||
// try {
|
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||||
ptr[offset] = lsb
|
chunkPool.setTileRaw(chunk, ox, oy, tile or placement.shl(16))
|
||||||
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) {
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
val offset = getOffset(x, y)
|
val tile = bytes[1].toUint().shl(8) or bytes[0].toUint()
|
||||||
ptr[offset] = bytes[1]
|
val placement = bytes[2].toUint()
|
||||||
ptr[offset + 1] = bytes[0]
|
unsafeSetTile(x, y, tile, placement)
|
||||||
ptr[offset + 2] = bytes[2]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun unsafeSetTileKeepPlacement(x: Int, y: Int, tile: Int) {
|
override fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) {
|
||||||
val offset = getOffset(x, y)
|
val oldPlacement = unsafeGetTileI16I8(x, y).second
|
||||||
|
unsafeSetTile(x, y, tile, oldPlacement)
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
ptr[offset] = lsb
|
|
||||||
ptr[offset + 1] = msb
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,12 +106,14 @@ class BlockLayerOresI16I8 (override val width: Int, override val height: Int) :
|
|||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
|
override var disposed: Boolean = false
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
ptr.destroy()
|
chunkPool.dispose()
|
||||||
App.printdbg(this, "BlockLayerI16I8 with ptr ($ptr) successfully freed")
|
disposed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString("BlockLayerI16I8")
|
override fun toString(): String = "BlockLayerI16I8 (${width}x$height)"
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val BYTES_PER_BLOCK = 3L
|
@Transient val BYTES_PER_BLOCK = 3L
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.INGAME
|
import net.torvald.terrarum.INGAME
|
||||||
import net.torvald.terrarum.Point2i
|
import net.torvald.terrarum.Point2i
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||||
@@ -8,6 +9,7 @@ import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.Clustf
|
|||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
||||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
||||||
|
import net.torvald.terrarum.savegame.ByteArray64
|
||||||
import net.torvald.terrarum.savegame.DiskEntry
|
import net.torvald.terrarum.savegame.DiskEntry
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||||
import net.torvald.terrarum.savegame.EntryFile
|
import net.torvald.terrarum.savegame.EntryFile
|
||||||
@@ -35,25 +37,74 @@ enum class ChunkAllocClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* WHAT IF instead of reading chunks directly from the savegame, I treat ChunkPool as a mere disk-cache?
|
||||||
|
*
|
||||||
|
* 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.
|
* Single layer gets single Chunk Pool.
|
||||||
*
|
*
|
||||||
* Created by minjaesong on 2024-09-07.
|
* Created by minjaesong on 2024-09-07.
|
||||||
*/
|
*/
|
||||||
open class ChunkPool(
|
open class ChunkPool {
|
||||||
|
|
||||||
|
private enum class ChunkLoadingStatus {
|
||||||
|
LOADING_REQUESTED, RAW, LOADED_FROM_DISK, NEWLY_GENERATED
|
||||||
|
}
|
||||||
|
|
||||||
// `DiskSkimmer` or `ClusteredFormatDOM`
|
// `DiskSkimmer` or `ClusteredFormatDOM`
|
||||||
val disk: Any,
|
private val disk: Any
|
||||||
val layerIndex: Int,
|
private val layerIndex: Int
|
||||||
val wordSizeInBytes: Long,
|
private val wordSizeInBytes: Long
|
||||||
val world: GameWorld,
|
private val world: TheGameWorld
|
||||||
val renumberFun: (Int) -> Int,
|
private val initialValue: Int // bytes to fill the new chunk
|
||||||
) {
|
private val renumberFun: (Int) -> Int
|
||||||
|
|
||||||
|
private val chunkStatus = HashMap<Long, ChunkLoadingStatus>()
|
||||||
private val pointers = TreeMap<Long, Long>()
|
private val pointers = TreeMap<Long, Long>()
|
||||||
private var allocCap = 32
|
private var allocCap = 32
|
||||||
private var allocMap = Array<ChunkAllocation?>(allocCap) { null }
|
private var allocMap = Array<ChunkAllocation?>(allocCap) { null }
|
||||||
private var allocCounter = 0
|
private var allocCounter = 0
|
||||||
|
private val chunkSize: Long
|
||||||
|
private val pool: UnsafePtr
|
||||||
|
|
||||||
private val chunkSize = (wordSizeInBytes * CHUNK_W * CHUNK_H)
|
constructor(
|
||||||
private val pool = UnsafeHelper.allocate(chunkSize * allocCap)
|
disk: DiskSkimmer,
|
||||||
|
layerIndex: Int,
|
||||||
|
wordSizeInBytes: Long,
|
||||||
|
world: TheGameWorld,
|
||||||
|
initialValue: Int,
|
||||||
|
renumberFun: (Int) -> Int,
|
||||||
|
) {
|
||||||
|
this.disk = disk
|
||||||
|
this.layerIndex = layerIndex
|
||||||
|
this.wordSizeInBytes = wordSizeInBytes
|
||||||
|
this.world = world
|
||||||
|
this.initialValue = initialValue
|
||||||
|
this.renumberFun = renumberFun
|
||||||
|
|
||||||
|
chunkSize = wordSizeInBytes * CHUNK_W * CHUNK_H
|
||||||
|
pool = UnsafeHelper.allocate(chunkSize * allocCap)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
disk: ClusteredFormatDOM,
|
||||||
|
layerIndex: Int,
|
||||||
|
wordSizeInBytes: Long,
|
||||||
|
world: TheGameWorld,
|
||||||
|
initialValue: Int,
|
||||||
|
renumberFun: (Int) -> Int,
|
||||||
|
) {
|
||||||
|
this.disk = disk
|
||||||
|
this.layerIndex = layerIndex
|
||||||
|
this.wordSizeInBytes = wordSizeInBytes
|
||||||
|
this.world = world
|
||||||
|
this.initialValue = initialValue
|
||||||
|
this.renumberFun = renumberFun
|
||||||
|
|
||||||
|
chunkSize = wordSizeInBytes * CHUNK_W * CHUNK_H
|
||||||
|
pool = UnsafeHelper.allocate(chunkSize * allocCap)
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
allocMap.fill(null)
|
allocMap.fill(null)
|
||||||
@@ -64,6 +115,9 @@ open class ChunkPool(
|
|||||||
return UnsafePtr(baseAddr, chunkSize)
|
return UnsafePtr(baseAddr, chunkSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer and the offset from the pointer. The offset is given in bytes, but always word-aligned (if block offset is `(2, 0)`, the returning offset will be `8`, assuming word size of 4)
|
||||||
|
*/
|
||||||
private fun createPointerViewOfChunk(chunkNumber: Long, offsetX: Int, offsetY: Int): Pair<UnsafePtr, Long> {
|
private fun createPointerViewOfChunk(chunkNumber: Long, offsetX: Int, offsetY: Int): Pair<UnsafePtr, Long> {
|
||||||
val baseAddr = pointers[chunkNumber]!!
|
val baseAddr = pointers[chunkNumber]!!
|
||||||
return UnsafePtr(baseAddr, chunkSize) to wordSizeInBytes * (offsetY * CHUNK_W + offsetX)
|
return UnsafePtr(baseAddr, chunkSize) to wordSizeInBytes * (offsetY * CHUNK_W + offsetX)
|
||||||
@@ -168,12 +222,17 @@ open class ChunkPool(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchFromDisk(chunkNumber: Long) {
|
/**
|
||||||
val fileName = chunkNumToFileNum(layerIndex, chunkNumber)
|
* @return `unit` if IO operation was successful, `null` if failed (e.g. file not exists)
|
||||||
|
*/
|
||||||
|
private fun fetchFromDisk(chunkNumber: Long): Unit? {
|
||||||
// read data from the disk
|
// read data from the disk
|
||||||
if (disk is ClusteredFormatDOM) {
|
return if (disk is ClusteredFormatDOM) {
|
||||||
|
val fileName = chunkNumToFileNumType17(layerIndex, chunkNumber)
|
||||||
|
|
||||||
Clustfile(disk, fileName).let {
|
Clustfile(disk, fileName).let {
|
||||||
|
if (!it.exists()) return@let null
|
||||||
|
|
||||||
val bytes = Common.unzip(it.readBytes())
|
val bytes = Common.unzip(it.readBytes())
|
||||||
val ptr = allocate(chunkNumber)
|
val ptr = allocate(chunkNumber)
|
||||||
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
||||||
@@ -181,21 +240,42 @@ open class ChunkPool(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (disk is DiskSkimmer) {
|
else if (disk is DiskSkimmer) {
|
||||||
val fileID = fileName.toLong()
|
val fileID = chunkNumToFileEntryID(layerIndex, chunkNumber)
|
||||||
disk.getFile(fileID)!!.let {
|
|
||||||
|
disk.getFile(fileID).let {
|
||||||
|
printdbg(this, "Reading chunk data: Layer $layerIndex Chunk $chunkNumber (fileID: $fileID), file: $it")
|
||||||
|
|
||||||
|
if (it == null) return@let null
|
||||||
|
|
||||||
val bytes = Common.unzip(it.bytes)
|
val bytes = Common.unzip(it.bytes)
|
||||||
val ptr = allocate(chunkNumber)
|
val ptr = allocate(chunkNumber)
|
||||||
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
memcpyFromByteArray64ToPtr(bytes, 0L, ptr, 0L, bytes.size)
|
||||||
renumber(ptr)
|
renumber(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
throw IllegalStateException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun memcpyFromByteArray64ToPtr(ba: ByteArray64, srcIndex: Long, destPtr: UnsafePtr, destOffset: Long, copyLen: Long) {
|
||||||
|
// TODO temporary
|
||||||
|
val obj = ba.toByteArray()
|
||||||
|
UnsafeHelper.memcpyFromArrToPtr(obj, srcIndex.toInt(), destPtr.ptr + destOffset, copyLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return `unit` if IO operation was successful, `null` if failed (e.g. file not exists)
|
||||||
|
*/
|
||||||
|
private fun createNewChunkFile(chunkNumber: Long): Unit? {
|
||||||
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun storeToDisk(chunkNumber: Long) {
|
private fun storeToDisk(chunkNumber: Long) {
|
||||||
val fileName = chunkNumToFileNum(layerIndex, chunkNumber)
|
|
||||||
|
|
||||||
// write to the disk (the disk must be an autosaving copy of the original)
|
// write to the disk (the disk must be an autosaving copy of the original)
|
||||||
if (disk is ClusteredFormatDOM) {
|
if (disk is ClusteredFormatDOM) {
|
||||||
|
val fileName = chunkNumToFileNumType17(layerIndex, chunkNumber)
|
||||||
|
|
||||||
Clustfile(disk, fileName).let {
|
Clustfile(disk, fileName).let {
|
||||||
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
||||||
it.overwrite(bytes.toByteArray())
|
it.overwrite(bytes.toByteArray())
|
||||||
@@ -203,7 +283,7 @@ open class ChunkPool(
|
|||||||
}
|
}
|
||||||
// append the new entry
|
// append the new entry
|
||||||
else if (disk is DiskSkimmer) {
|
else if (disk is DiskSkimmer) {
|
||||||
val fileID = fileName.toLong()
|
val fileID = chunkNumToFileEntryID(layerIndex, chunkNumber)
|
||||||
|
|
||||||
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
||||||
val oldEntry = disk.getEntry(fileID)
|
val oldEntry = disk.getEntry(fileID)
|
||||||
@@ -214,7 +294,7 @@ open class ChunkPool(
|
|||||||
|
|
||||||
private fun checkForChunk(chunkNumber: Long) {
|
private fun checkForChunk(chunkNumber: Long) {
|
||||||
if (!pointers.containsKey(chunkNumber)) {
|
if (!pointers.containsKey(chunkNumber)) {
|
||||||
fetchFromDisk(chunkNumber)
|
fetchFromDisk(chunkNumber) ?: createNewChunkFile(chunkNumber) ?: TODO("handle IO error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +305,19 @@ open class ChunkPool(
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun worldXYChunkNumAndOffset(worldx: Int, worldy: Int): Triple<Long, Int, Int> {
|
||||||
|
val chunkX = worldx / CHUNK_W
|
||||||
|
val chunkY = worldy / CHUNK_H
|
||||||
|
val chunkOx = worldx % CHUNK_W
|
||||||
|
val chunkOy = worldy % CHUNK_H
|
||||||
|
|
||||||
|
val chunkNum = LandUtil.chunkXYtoChunkNum(world, chunkX, chunkY)
|
||||||
|
return Triple(chunkNum, chunkOx, chunkOy)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateAccessTime(chunkNumber: Long) {
|
||||||
|
allocMap.find { it?.chunkNumber == chunkNumber }!!.let { it.lastAccessTime = System.nanoTime() }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
||||||
@@ -235,7 +328,7 @@ open class ChunkPool(
|
|||||||
*/
|
*/
|
||||||
fun getTileRaw(chunkNumber: Long, offX: Int, offY: Int): Int {
|
fun getTileRaw(chunkNumber: Long, offX: Int, offY: Int): Int {
|
||||||
checkForChunk(chunkNumber)
|
checkForChunk(chunkNumber)
|
||||||
allocMap.find { it?.chunkNumber == chunkNumber }!!.let { it.lastAccessTime = System.nanoTime() }
|
updateAccessTime(chunkNumber)
|
||||||
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
||||||
val numIn = (0 until wordSizeInBytes.toInt()).fold(0) { acc, off ->
|
val numIn = (0 until wordSizeInBytes.toInt()).fold(0) { acc, off ->
|
||||||
acc or (ptr[ptrOff].toUint().shl(8 * off))
|
acc or (ptr[ptrOff].toUint().shl(8 * off))
|
||||||
@@ -243,6 +336,23 @@ open class ChunkPool(
|
|||||||
return numIn
|
return numIn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the bytes of Int `B3_B2_B1_B0`
|
||||||
|
* Saved as:
|
||||||
|
* - word size is 4: `[B0, B1, B2, B3]`
|
||||||
|
* - word size is 3: `[B0, B1, B2]` (B3 is ignored)
|
||||||
|
* - word size is 2: `[B0, B1]` (B2 and B3 are ignored)
|
||||||
|
*/
|
||||||
|
fun setTileRaw(chunkNumber: Long, offX: Int, offY: Int, bytes: Int) {
|
||||||
|
checkForChunk(chunkNumber)
|
||||||
|
updateAccessTime(chunkNumber)
|
||||||
|
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
||||||
|
for (i in 0 until wordSizeInBytes.toInt()) {
|
||||||
|
val b = bytes.ushr(8*i).and(255)
|
||||||
|
ptr[ptrOff + i] = b.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
||||||
* Return format:
|
* Return format:
|
||||||
@@ -280,11 +390,18 @@ open class ChunkPool(
|
|||||||
return ibits to jbits
|
return ibits to jbits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun chunkNumToFileNum(layerNum: Int, chunkNum: Long): String {
|
fun chunkNumToFileNumType17(layerNum: Int, chunkNum: Long): String {
|
||||||
val entryID = Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
val entryID = Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
||||||
return Common.type254EntryIDtoType17Filename(entryID)
|
return Common.type254EntryIDtoType17Filename(entryID)
|
||||||
}
|
}
|
||||||
|
fun chunkNumToFileEntryID(layerNum: Int, chunkNum: Long): Long {
|
||||||
|
return Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
||||||
|
}
|
||||||
|
|
||||||
private fun Int.get1SS() = this and 65535
|
private fun Int.get1SS() = this and 65535
|
||||||
private fun Int.get2SS() = (this ushr 16) and 65535
|
private fun Int.get2SS() = (this ushr 16) and 65535
|
||||||
@@ -300,7 +417,7 @@ open class ChunkPool(
|
|||||||
private fun Int.get2LSB() = this.get3MSB()
|
private fun Int.get2LSB() = this.get3MSB()
|
||||||
private fun Int.getLSB() = this.get4MSB()
|
private fun Int.getLSB() = this.get4MSB()
|
||||||
|
|
||||||
fun getRenameFunTerrain(world: GameWorld): (Int) -> Int {
|
fun getRenameFunTerrain(world: TheGameWorld): (Int) -> Int {
|
||||||
// word size: 2
|
// word size: 2
|
||||||
return { oldTileNum ->
|
return { oldTileNum ->
|
||||||
val oldOreName = world.oldTileNumberToNameMap[oldTileNum.toLong()]
|
val oldOreName = world.oldTileNumberToNameMap[oldTileNum.toLong()]
|
||||||
@@ -309,7 +426,7 @@ open class ChunkPool(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRenameFunOres(world: GameWorld): (Int) -> Int {
|
fun getRenameFunOres(world: TheGameWorld): (Int) -> Int {
|
||||||
// word size: 3
|
// word size: 3
|
||||||
return { oldTileNumRaw ->
|
return { oldTileNumRaw ->
|
||||||
val oldOreNum = oldTileNumRaw and 0x0000FFFF
|
val oldOreNum = oldTileNumRaw and 0x0000FFFF
|
||||||
@@ -320,7 +437,7 @@ open class ChunkPool(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRenameFunFluids(world: GameWorld): (Int) -> Int {
|
fun getRenameFunFluids(world: TheGameWorld): (Int) -> Int {
|
||||||
// word size: 4
|
// word size: 4
|
||||||
return { oldTileNumRaw ->
|
return { oldTileNumRaw ->
|
||||||
val oldFluidNum = oldTileNumRaw and 0x0000FFFF
|
val oldFluidNum = oldTileNumRaw and 0x0000FFFF
|
||||||
@@ -331,7 +448,8 @@ open class ChunkPool(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val chunkOffsetsNearPlayer = listOf(
|
// this list does NOT contain `Point2i(0,0)`
|
||||||
|
val chunkOffsetsNearPlayer = listOf(
|
||||||
Point2i(-1,-2), Point2i(0,-2),Point2i(1,-2),
|
Point2i(-1,-2), Point2i(0,-2),Point2i(1,-2),
|
||||||
Point2i(-2,-1),Point2i(-1,-1),Point2i(0,-1),Point2i(1,-1),Point2i(2,-1),
|
Point2i(-2,-1),Point2i(-1,-1),Point2i(0,-1),Point2i(1,-1),Point2i(2,-1),
|
||||||
Point2i(-2,0),Point2i(-1,0),Point2i(1,0),Point2i(2,0),
|
Point2i(-2,0),Point2i(-1,0),Point2i(1,0),Point2i(2,0),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@ package net.torvald.terrarum.modulebasegame
|
|||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.Input.Keys
|
import com.badlogic.gdx.Input.Keys
|
||||||
import com.badlogic.gdx.InputAdapter
|
import com.badlogic.gdx.InputAdapter
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
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.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
import net.torvald.terrarum.gameworld.*
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
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.UIBuildingMakerBlockChooser
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
|
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
|
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIScreenZoom
|
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.Common
|
||||||
import net.torvald.terrarum.serialise.PointOfInterest
|
import net.torvald.terrarum.serialise.PointOfInterest
|
||||||
import net.torvald.terrarum.serialise.POILayer
|
import net.torvald.terrarum.serialise.POILayer
|
||||||
@@ -61,7 +62,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
- Set…
|
- Set…
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
|
||||||
lateinit var gameWorld: GameWorld
|
lateinit var gameWorld: TheGameWorld
|
||||||
|
|
||||||
override val musicStreamer = TerrarumMusicAndAmbientStreamer()
|
override val musicStreamer = TerrarumMusicAndAmbientStreamer()
|
||||||
|
|
||||||
@@ -419,7 +420,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
for (x in for_x_start..for_x_end) {
|
for (x in for_x_start..for_x_end) {
|
||||||
if (wiringCounter >= maxRenderableWires) break
|
if (wiringCounter >= maxRenderableWires) break
|
||||||
|
|
||||||
val (wires, nodes) = world.getAllWiresFrom(x, y)
|
val (wires, nodes) = gameWorld.getAllWiresFrom(x, y)
|
||||||
|
|
||||||
wires?.forEach {
|
wires?.forEach {
|
||||||
val wireActor = wireActorsContainer[wiringCounter]
|
val wireActor = wireActorsContainer[wiringCounter]
|
||||||
@@ -553,7 +554,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
private fun getNearbyOres8(x: Int, y: Int): List<OrePlacement> {
|
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) {
|
private fun makePenWork(x: Int, y: Int) {
|
||||||
@@ -877,8 +878,8 @@ class YamlCommandToolExportTest : YamlInvokable {
|
|||||||
ui.world.tileNameToNumberMap
|
ui.world.tileNameToNumberMap
|
||||||
)
|
)
|
||||||
val layer = POILayer(name)
|
val layer = POILayer(name)
|
||||||
val terr = BlockLayerGenericI16(poi.w, poi.h)
|
val terr = BlockLayerInMemoryI16(poi.w, poi.h)
|
||||||
val wall = BlockLayerGenericI16(poi.w, poi.h)
|
val wall = BlockLayerInMemoryI16(poi.w, poi.h)
|
||||||
layer.blockLayer = arrayListOf(terr, wall)
|
layer.blockLayer = arrayListOf(terr, wall)
|
||||||
poi.layers.add(layer)
|
poi.layers.add(layer)
|
||||||
|
|
||||||
@@ -934,8 +935,13 @@ class YamlCommandNewFlatTerrain : YamlInvokable {
|
|||||||
|
|
||||||
println("[BuildingMaker] Generating builder world...")
|
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
|
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
|
// remove null tiles
|
||||||
for (y in 0 until ui.gameWorld.height) {
|
for (y in 0 until ui.gameWorld.height) {
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ import net.torvald.terrarum.BlockCodex
|
|||||||
import net.torvald.terrarum.ItemCodex
|
import net.torvald.terrarum.ItemCodex
|
||||||
import net.torvald.terrarum.OreCodex
|
import net.torvald.terrarum.OreCodex
|
||||||
import net.torvald.terrarum.ceilToInt
|
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.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.getOffset
|
|
||||||
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
|
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
import java.util.concurrent.*
|
import java.util.concurrent.*
|
||||||
@@ -34,7 +33,7 @@ object ExplosionManager {
|
|||||||
val lineMax = world.height - ty + CALC_RADIUS
|
val lineMax = world.height - ty + CALC_RADIUS
|
||||||
|
|
||||||
// create a copy of the tilemap
|
// 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)
|
val breakmap = UnsafeFloatArray(CALC_WIDTH, CALC_WIDTH)
|
||||||
|
|
||||||
// fill in the tilemap copy
|
// fill in the tilemap copy
|
||||||
@@ -69,9 +68,9 @@ object ExplosionManager {
|
|||||||
}.start()
|
}.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 the bounding box must wrap around
|
||||||
if (xStart > world.width - CALC_RADIUS) {
|
/*if (xStart > world.width - CALC_RADIUS) {
|
||||||
val lenLeft = world.width - xStart
|
val lenLeft = world.width - xStart
|
||||||
val lenRight = CALC_WIDTH - lenLeft
|
val lenRight = CALC_WIDTH - lenLeft
|
||||||
|
|
||||||
@@ -98,12 +97,18 @@ object ExplosionManager {
|
|||||||
out.getOffset(0, yOff),
|
out.getOffset(0, yOff),
|
||||||
world.layerTerrain.bytesPerBlock * CALC_WIDTH
|
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 the bounding box must wrap around
|
||||||
if (xStart > world.width - CALC_RADIUS) {
|
/*if (xStart > world.width - CALC_RADIUS) {
|
||||||
val lenLeft = world.width - xStart
|
val lenLeft = world.width - xStart
|
||||||
val lenRight = CALC_WIDTH - lenLeft
|
val lenRight = CALC_WIDTH - lenLeft
|
||||||
|
|
||||||
@@ -130,6 +135,12 @@ object ExplosionManager {
|
|||||||
world.layerTerrain.getOffset(xStart, yStart + yOff),
|
world.layerTerrain.getOffset(xStart, yStart + yOff),
|
||||||
world.layerTerrain.bytesPerBlock * CALC_WIDTH
|
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,
|
CALC_RADIUS: Int, CALC_WIDTH: Int,
|
||||||
world: GameWorld,
|
world: GameWorld,
|
||||||
breakmap: UnsafeFloatArray,
|
breakmap: UnsafeFloatArray,
|
||||||
tilemap: BlockLayerGenericI16,
|
tilemap: BlockLayerInMemoryI16,
|
||||||
tx: Int, ty: Int,
|
tx: Int, ty: Int,
|
||||||
power: Float,
|
power: Float,
|
||||||
dropProbNonOre: Float,
|
dropProbNonOre: Float,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
|||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.blockproperties.FluidCodex
|
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.METER
|
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.METER
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.PHYS_EPSILON_DIST
|
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.gameitems.mouseInInteractableRange
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||||
import net.torvald.terrarum.modulebasegame.gameitems.ItemThrowable
|
import net.torvald.terrarum.modulebasegame.gameitems.ItemThrowable
|
||||||
@@ -44,8 +44,6 @@ import kotlin.math.min
|
|||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will be rendered to a postprocessor FBO.
|
* This will be rendered to a postprocessor FBO.
|
||||||
*
|
*
|
||||||
@@ -131,7 +129,7 @@ object IngameRenderer : Disposable {
|
|||||||
//var renderingParticleCount = 0
|
//var renderingParticleCount = 0
|
||||||
// private set
|
// 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 set // the grammar "IngameRenderer.world = gameWorld" seemes mundane and this function needs special care!
|
||||||
|
|
||||||
private var newWorldLoadedLatch = false
|
private var newWorldLoadedLatch = false
|
||||||
@@ -393,11 +391,16 @@ object IngameRenderer : Disposable {
|
|||||||
|
|
||||||
blendNormalStraightAlpha(batch)
|
blendNormalStraightAlpha(batch)
|
||||||
|
|
||||||
val (vo, vg) = world.weatherbox.let {
|
val (vo, vg) = if (world is TheGameWorld) {
|
||||||
if (it.currentWeather.identifier == "titlescreen")
|
(world as TheGameWorld).weatherbox.let {
|
||||||
1f to 1f
|
if (it.currentWeather.identifier == "titlescreen")
|
||||||
else
|
1f to 1f
|
||||||
it.currentVibrancy.x to it.currentVibrancy.y
|
else
|
||||||
|
it.currentVibrancy.x to it.currentVibrancy.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
1f to 1f
|
||||||
}
|
}
|
||||||
|
|
||||||
mixedOutTex.texture.bind(0)
|
mixedOutTex.texture.bind(0)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import net.torvald.terrarum.gameitems.GameItem
|
|||||||
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
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
|
||||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
||||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
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.VDUtil
|
||||||
import net.torvald.terrarum.savegame.VirtualDisk
|
import net.torvald.terrarum.savegame.VirtualDisk
|
||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
@@ -348,7 +350,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
data class Codices(
|
data class Codices(
|
||||||
val disk: VirtualDisk, // WORLD disk
|
val disk: VirtualDisk, // WORLD disk
|
||||||
val world: GameWorld,
|
val world: TheGameWorld,
|
||||||
// val meta: WriteMeta.WorldMeta,
|
// val meta: WriteMeta.WorldMeta,
|
||||||
// val block: BlockCodex,
|
// val block: BlockCodex,
|
||||||
// val item: ItemCodex,
|
// val item: ItemCodex,
|
||||||
@@ -383,7 +385,8 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
// feed info to the worldgen
|
// 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
|
loadCallback = codices.callbackAfterLoad
|
||||||
@@ -443,7 +446,6 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// try to unstuck the repositioned player
|
// try to unstuck the repositioned player
|
||||||
codices.player.tryUnstuck()
|
codices.player.tryUnstuck()
|
||||||
|
|
||||||
@@ -520,13 +522,18 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
App.getLoadScreen().addMessage("${App.GAME_NAME} ${App.getVERSION_STRING()}")
|
App.getLoadScreen().addMessage("${App.GAME_NAME} ${App.getVERSION_STRING()}")
|
||||||
|
|
||||||
App.getLoadScreen().addMessage("Creating new world")
|
App.getLoadScreen().addMessage("Creating new world")
|
||||||
|
|
||||||
|
|
||||||
|
val worldFile = getWorldSaveFiledesc(worldSavefileName)
|
||||||
|
VDUtil.dumpToRealMachine(worldDisk, worldFile)
|
||||||
|
val skimmer = DiskSkimmer(worldFile)
|
||||||
|
|
||||||
// init map as chosen size
|
// init map as chosen size
|
||||||
val timeNow = App.getTIME_T()
|
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
|
world.generatorSeed = worldParams.worldGenSeed
|
||||||
//gameworldIndices.add(world.worldIndex)
|
//gameworldIndices.add(world.worldIndex)
|
||||||
world.extraFields["basegame.economy"] = GameEconomy()
|
world.extraFields["basegame.economy"] = GameEconomy()
|
||||||
|
|||||||
@@ -24,18 +24,15 @@ import net.torvald.terrarum.gameactors.ai.ActorAI
|
|||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.*
|
||||||
import net.torvald.terrarum.gameworld.WorldTime
|
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
|
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
|
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
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.Toolkit
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import net.torvald.terrarum.ui.UIItemTextButton
|
|
||||||
import net.torvald.terrarum.utils.OpenURL
|
import net.torvald.terrarum.utils.OpenURL
|
||||||
import net.torvald.terrarum.weather.WeatherMixer
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
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 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 lateinit var cameraNodes: FloatArray // camera Y-pos
|
||||||
private val cameraNodeWidth = 15
|
private val cameraNodeWidth = 15
|
||||||
private val lookaheadDist = cameraNodeWidth * TILE_SIZED
|
private val lookaheadDist = cameraNodeWidth * TILE_SIZED
|
||||||
@@ -165,19 +162,19 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
val file = ModMgr.getFile("basegame", "demoworld")
|
val file = ModMgr.getFile("basegame", "demoworld")
|
||||||
val reader = java.io.FileReader(file)
|
val reader = java.io.FileReader(file)
|
||||||
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
||||||
val world = ReadSimpleWorld(reader, file)
|
val world = ReadTitlescreenGameWorld(reader, file)
|
||||||
demoWorld = world
|
demoWorld = world
|
||||||
demoWorld.worldTime.timeDelta = 30
|
demoWorld.worldTime.timeDelta = 30
|
||||||
printdbg(this, "Demo world loaded")
|
printdbg(this, "Demo world loaded")
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
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
|
demoWorld.worldTime.timeDelta = 30
|
||||||
printdbg(this, "Demo world not found, using empty world")
|
printdbg(this, "Demo world not found, using empty world")
|
||||||
}
|
}
|
||||||
|
|
||||||
demoWorld.renumberTilesAfterLoad()
|
|
||||||
this.world = demoWorld
|
this.world = demoWorld
|
||||||
|
demoWorld.renumberTilesAfterLoad()
|
||||||
|
|
||||||
// set initial time to summer
|
// set initial time to summer
|
||||||
demoWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
demoWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
||||||
@@ -365,7 +362,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
gdxClearAndEnableBlend(.64f, .754f, .84f, 1f)
|
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)
|
WorldCamera.update(demoWorld, cameraPlayer)
|
||||||
|
|
||||||
IngameRenderer.invoke(
|
IngameRenderer.invoke(
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import net.torvald.terrarum.gameactors.Controllable
|
|||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
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.TerrarumIngame.Companion.inUpdateRange
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
import net.torvald.terrarum.modulebasegame.gameactors.*
|
||||||
import net.torvald.terrarum.modulebasegame.gameitems.AxeCore
|
import net.torvald.terrarum.modulebasegame.gameitems.AxeCore
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.Pixmap
|
|||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ class WorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidt
|
|||||||
|
|
||||||
try {
|
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
|
// 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
|
val outCol = if (BlockCodex[world.getTileFromTerrain(wx, wy)].isSolid) COL_TERR
|
||||||
else if (BlockCodex[world.getTileFromWall(wx, wy)].isSolid) COL_WALLED
|
else if (BlockCodex[world.getTileFromWall(wx, wy)].isSolid) COL_WALLED
|
||||||
else COL_AIR
|
else COL_AIR
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import net.torvald.terrarum.App
|
|||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.console.ConsoleCommand
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
import net.torvald.terrarum.console.Echo
|
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.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.serialise.WriteSimpleWorld
|
import net.torvald.terrarum.serialise.WriteTitlescreenGameWorld
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
@@ -21,12 +21,12 @@ object ExportWorld : ConsoleCommand {
|
|||||||
try {
|
try {
|
||||||
val ingame = Terrarum.ingame!! as TerrarumIngame
|
val ingame = Terrarum.ingame!! as TerrarumIngame
|
||||||
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
|
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.layerTerrain = ingame.world.layerTerrain
|
||||||
it.layerWall = ingame.world.layerWall
|
it.layerWall = ingame.world.layerWall
|
||||||
it.tileNumberToNameMap.putAll(ingame.world.tileNumberToNameMap)
|
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")
|
Echo("Exportworld: exported the world as ${args[1]}.json")
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import net.torvald.terrarum.Terrarum
|
|||||||
import net.torvald.terrarum.console.ConsoleCommand
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
import net.torvald.terrarum.console.Echo
|
import net.torvald.terrarum.console.Echo
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
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.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ object ImportWorld : ConsoleCommand {
|
|||||||
try {
|
try {
|
||||||
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
|
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
|
||||||
val reader = java.io.FileReader(file)
|
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")
|
Echo("Importworld: imported a world from ${args[1]}.json")
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.torvald.terrarum.gameitems.ItemID
|
|||||||
import net.torvald.terrarum.gameitems.isWall
|
import net.torvald.terrarum.gameitems.isWall
|
||||||
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.serialise
|
package net.torvald.terrarum.modulebasegame.serialise
|
||||||
|
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||||
import net.torvald.terrarum.console.Echo
|
import net.torvald.terrarum.console.Echo
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
import net.torvald.terrarum.gameworld.*
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16
|
import net.torvald.terrarum.gameworld.ChunkPool.Companion.chunkOffsetsNearPlayer
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerOresI16I8
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
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.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.FancyWorldReadLoadScreen
|
import net.torvald.terrarum.modulebasegame.FancyWorldReadLoadScreen
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
@@ -13,6 +16,7 @@ import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
|||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.savegame.*
|
import net.torvald.terrarum.savegame.*
|
||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
|
import org.dyn4j.geometry.Vector2
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
import kotlin.experimental.or
|
import kotlin.experimental.or
|
||||||
@@ -60,11 +64,10 @@ object LoadSavegame {
|
|||||||
val worldDiskSavegameInfo = ByteArray64Reader(worldDisk.getFile(VDFileID.SAVEGAMEINFO)!!.bytes, Common.CHARSET)
|
val worldDiskSavegameInfo = ByteArray64Reader(worldDisk.getFile(VDFileID.SAVEGAMEINFO)!!.bytes, Common.CHARSET)
|
||||||
val world = ReadWorld(worldDiskSavegameInfo, worldDisk.diskFile)
|
val world = ReadWorld(worldDiskSavegameInfo, worldDisk.diskFile)
|
||||||
|
|
||||||
|
world.layerTerrain = BlockLayerGenericI16(world.width, world.height, worldDisk, TERRAIN, world)
|
||||||
world.layerTerrain = BlockLayerGenericI16(world.width, world.height)
|
world.layerWall = BlockLayerGenericI16(world.width, world.height, worldDisk, WALL, world)
|
||||||
world.layerWall = BlockLayerGenericI16(world.width, world.height)
|
world.layerOres = BlockLayerOresI16I8(world.width, world.height, worldDisk, ORES, world)
|
||||||
world.layerOres = BlockLayerOresI16I8(world.width, world.height)
|
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height, worldDisk, FLUID, world)
|
||||||
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height)
|
|
||||||
world.chunkFlags = Array(world.height / LandUtil.CHUNK_H) { ByteArray(world.width / LandUtil.CHUNK_W) }
|
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
|
newIngame.world = world // must be set before the loadscreen, otherwise the loadscreen will try to read from the NullWorld which is already destroyed
|
||||||
@@ -119,12 +122,24 @@ object LoadSavegame {
|
|||||||
val (cx, cy) = LandUtil.chunkNumToChunkXY(world, chunk)
|
val (cx, cy) = LandUtil.chunkNumToChunkXY(world, chunk)
|
||||||
|
|
||||||
ReadWorld.decodeChunkToLayer(chunkFile.getContent(), worldLayer[layer]!!, cx, cy)
|
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)
|
loadscreen.progress.getAndAdd(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val playerChunk = player.hitbox.canonVec.let {
|
||||||
|
(it.x / (cw * TILE_SIZED)).toInt() to (it.y / (ch * TILE_SIZED)).toInt()
|
||||||
|
}.let { Point2i(it.first, it.second) }
|
||||||
|
|
||||||
|
val chunksToLoad = chunkOffsetsNearPlayer.map {
|
||||||
|
playerChunk + it
|
||||||
|
} + playerChunk
|
||||||
|
|
||||||
|
/*for (layer in worldLayer) {
|
||||||
|
(layer as? BlockLayerWithChunkPool)?.chunkPool?.
|
||||||
|
}*/
|
||||||
|
|
||||||
loadscreen.addMessage(Lang["MENU_IO_LOAD_UPDATING_BLOCK_MAPPINGS"])
|
loadscreen.addMessage(Lang["MENU_IO_LOAD_UPDATING_BLOCK_MAPPINGS"])
|
||||||
world.renumberTilesAfterLoad()
|
world.renumberTilesAfterLoad()
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import net.torvald.gdx.graphics.PixmapIO2
|
|||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration
|
import net.torvald.terrarum.TerrarumAppConfiguration
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
@@ -118,7 +119,7 @@ class QuickSingleplayerWorldSavingThread(
|
|||||||
|
|
||||||
// println("Chunk xy from number $chunkNumber -> (${chunkXY.x}, ${chunkXY.y})")
|
// 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 chunkBytes = WriteWorld.encodeChunk(layer, cx, cy)
|
||||||
val entryID = 0x1_0000_0000L or layerNum.toLong().shl(24) or chunkNumber.toLong()
|
val entryID = 0x1_0000_0000L or layerNum.toLong().shl(24) or chunkNumber.toLong()
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package net.torvald.terrarum.modulebasegame.serialise
|
|||||||
|
|
||||||
import net.torvald.gdx.graphics.PixmapIO2
|
import net.torvald.gdx.graphics.PixmapIO2
|
||||||
import net.torvald.terrarum.*
|
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.FLUID
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.ORES
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.ORES
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
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.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import net.torvald.terrarum.gameactors.Actor
|
|||||||
import net.torvald.terrarum.gameactors.NoSerialise
|
import net.torvald.terrarum.gameactors.NoSerialise
|
||||||
import net.torvald.terrarum.gameworld.BlockLayer
|
import net.torvald.terrarum.gameworld.BlockLayer
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
|
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
|
||||||
@@ -95,12 +96,12 @@ object WriteWorld {
|
|||||||
*/
|
*/
|
||||||
object ReadWorld {
|
object ReadWorld {
|
||||||
|
|
||||||
operator fun invoke(worldDataStream: Reader, origin: File?): GameWorld =
|
operator fun invoke(worldDataStream: Reader, origin: File?): TheGameWorld =
|
||||||
Common.jsoner.fromJson(GameWorld::class.java, worldDataStream).also {
|
Common.jsoner.fromJson(TheGameWorld::class.java, worldDataStream).also {
|
||||||
fillInDetails(origin, it)
|
fillInDetails(origin, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fillInDetails(origin: File?, world: GameWorld) {
|
private fun fillInDetails(origin: File?, world: TheGameWorld) {
|
||||||
world.tileNumberToNameMap.forEach { l, s ->
|
world.tileNumberToNameMap.forEach { l, s ->
|
||||||
world.tileNameToNumberMap[s] = l.toInt()
|
world.tileNameToNumberMap[s] = l.toInt()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import net.torvald.terrarum.serialise.toBig64
|
|||||||
import net.torvald.terrarum.toInt
|
import net.torvald.terrarum.toInt
|
||||||
import net.torvald.terrarum.utils.OrePlacement
|
import net.torvald.terrarum.utils.OrePlacement
|
||||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-10-26.
|
* Created by minjaesong on 2023-10-26.
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import net.torvald.terrarum.blockproperties.Block
|
|||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
@@ -163,14 +164,14 @@ object Worldgen {
|
|||||||
val jobs = getJobs()
|
val jobs = getJobs()
|
||||||
printdbg(this, "Generating chunk on ($cx, $cy)")
|
printdbg(this, "Generating chunk on ($cx, $cy)")
|
||||||
Thread {
|
Thread {
|
||||||
world.chunkFlags[cy][cx] = GameWorld.CHUNK_GENERATING
|
world.chunkFlags[cy][cx] = TheGameWorld.CHUNK_GENERATING
|
||||||
|
|
||||||
for (i in jobs.indices) {
|
for (i in jobs.indices) {
|
||||||
val it = jobs[i]
|
val it = jobs[i]
|
||||||
it.theWork.getChunkDone(cx, cy)
|
it.theWork.getChunkDone(cx, cy)
|
||||||
}
|
}
|
||||||
|
|
||||||
world.chunkFlags[cy][cx] = GameWorld.CHUNK_LOADED
|
world.chunkFlags[cy][cx] = TheGameWorld.CHUNK_LOADED
|
||||||
callback(cx, cy)
|
callback(cx, cy)
|
||||||
}.let {
|
}.let {
|
||||||
it.priority = 2
|
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)
|
draw(chunkX * LandUtil.CHUNK_W, chunkY * CHUNK_H, localJoise, sampleOffset)
|
||||||
loadscreen?.progress?.addAndGet(1L)
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import io.airlift.compress.zstd.ZstdOutputStream
|
|||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.console.EchoError
|
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.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.gameworld.WorldTime
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
import net.torvald.terrarum.savegame.ByteArray64
|
import net.torvald.terrarum.savegame.ByteArray64
|
||||||
import net.torvald.terrarum.savegame.ByteArray64GrowableOutputStream
|
import net.torvald.terrarum.savegame.ByteArray64GrowableOutputStream
|
||||||
@@ -41,7 +42,7 @@ object Common {
|
|||||||
val CHARSET = Charsets.UTF_8
|
val CHARSET = Charsets.UTF_8
|
||||||
|
|
||||||
/** dispose of the `offendingObject` after rejection! */
|
/** 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 fun Byte.tostr() = this.toInt().and(255).toString(16).padStart(2,'0')
|
||||||
private val digester = DigestUtils.getSha256Digest()
|
private val digester = DigestUtils.getSha256Digest()
|
||||||
@@ -74,8 +75,8 @@ object Common {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
// BlockLayer
|
// BlockLayer
|
||||||
it.setSerializer(BlockLayerGenericI16::class.java, object : Json.Serializer<BlockLayerGenericI16> {
|
it.setSerializer(BlockLayerInMemoryI16::class.java, object : Json.Serializer<BlockLayerInMemoryI16> {
|
||||||
override fun write(json: Json, obj: BlockLayerGenericI16, knownType: Class<*>?) {
|
override fun write(json: Json, obj: BlockLayerInMemoryI16, knownType: Class<*>?) {
|
||||||
digester.reset()
|
digester.reset()
|
||||||
obj.bytesIterator().forEachRemaining { digester.update(it) }
|
obj.bytesIterator().forEachRemaining { digester.update(it) }
|
||||||
val hash = StringBuilder().let { sb -> digester.digest().forEach { sb.append(it.tostr()) }; sb.toString() }
|
val hash = StringBuilder().let { sb -> digester.digest().forEach { sb.append(it.tostr()) }; sb.toString() }
|
||||||
@@ -85,7 +86,7 @@ object Common {
|
|||||||
json.writeValue(layer)
|
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
|
// full manual
|
||||||
try {
|
try {
|
||||||
return strToBlockLayer(LayerInfo(
|
return strToBlockLayer(LayerInfo(
|
||||||
@@ -435,12 +436,12 @@ object Common {
|
|||||||
* @param b a BlockLayer
|
* @param b a BlockLayer
|
||||||
* @return Bytes in [b] which are GZip'd then Ascii85-encoded
|
* @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())
|
return bytesToZipdStr(b.bytesIterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayerGenericI16 {
|
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayerInMemoryI16 {
|
||||||
val layer = BlockLayerGenericI16(layerInfo.x, layerInfo.y)
|
val layer = BlockLayerInMemoryI16(layerInfo.x, layerInfo.y)
|
||||||
val unzipdBytes = strToBytes(StringReader(layerInfo.b))
|
val unzipdBytes = strToBytes(StringReader(layerInfo.b))
|
||||||
|
|
||||||
// write to blocklayer and the digester
|
// write to blocklayer and the digester
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration
|
|||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||||
|
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||||
@@ -128,7 +129,7 @@ class POILayer(
|
|||||||
constructor() : this("undefined")
|
constructor() : this("undefined")
|
||||||
|
|
||||||
@Transient var name = name
|
@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>
|
@Transient internal lateinit var dat: Array<ByteArray>
|
||||||
|
|
||||||
@Deprecated("Used for debug print", ReplaceWith("name")) @Transient internal var id = ""
|
@Deprecated("Used for debug print", ReplaceWith("name")) @Transient internal var id = ""
|
||||||
@@ -179,10 +180,10 @@ class POILayer(
|
|||||||
if (::blockLayer.isInitialized) {
|
if (::blockLayer.isInitialized) {
|
||||||
blockLayer.forEach { it.dispose() }
|
blockLayer.forEach { it.dispose() }
|
||||||
}
|
}
|
||||||
blockLayer = ArrayList<BlockLayerGenericI16>()
|
blockLayer = ArrayList()
|
||||||
|
|
||||||
dat.forEachIndexed { layerIndex, layer ->
|
dat.forEachIndexed { layerIndex, layer ->
|
||||||
val currentBlockLayer = BlockLayerGenericI16(width, height).also {
|
val currentBlockLayer = BlockLayerInMemoryI16(width, height).also {
|
||||||
blockLayer.add(it)
|
blockLayer.add(it)
|
||||||
}
|
}
|
||||||
for (w in 0 until layer.size / byteLength) {
|
for (w in 0 until layer.size / byteLength) {
|
||||||
|
|||||||
@@ -4,56 +4,53 @@ import net.torvald.terrarum.App
|
|||||||
import net.torvald.terrarum.IngameInstance
|
import net.torvald.terrarum.IngameInstance
|
||||||
import net.torvald.terrarum.ItemCodex
|
import net.torvald.terrarum.ItemCodex
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16
|
import net.torvald.terrarum.gameworld.*
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerOresI16I8
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
|
||||||
import net.torvald.terrarum.gameworld.SimpleGameWorld
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2022-09-03.
|
* Created by minjaesong on 2022-09-03.
|
||||||
*/
|
*/
|
||||||
object ReadSimpleWorld {
|
object ReadTitlescreenGameWorld {
|
||||||
|
|
||||||
operator fun invoke(worldDataStream: Reader, origin: File?): GameWorld =
|
operator fun invoke(worldDataStream: Reader, origin: File?): TitlescreenGameWorld =
|
||||||
Common.jsoner.fromJson(SimpleGameWorld::class.java, worldDataStream).also {
|
Common.jsoner.fromJson(TitlescreenGameWorld::class.java, worldDataStream).also {
|
||||||
fillInDetails(origin, it)
|
fillInDetails(origin, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fillInDetails(origin: File?, world: GameWorld) {
|
private fun fillInDetails(origin: File?, world: TitlescreenGameWorld) {
|
||||||
world.tileNumberToNameMap.forEach { l, s ->
|
world.tileNumberToNameMap.forEach { l, s ->
|
||||||
world.tileNameToNumberMap[s] = l.toInt()
|
world.tileNameToNumberMap[s] = l.toInt()
|
||||||
}
|
}
|
||||||
world.layerOres = BlockLayerOresI16I8(world.width, world.height)
|
world.layerOres = BlockLayerInMemoryI16I8(world.width, world.height)
|
||||||
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height)
|
world.layerFluids = BlockLayerInMemoryI16F16(world.width, world.height)
|
||||||
|
|
||||||
ItemCodex.loadFromSave(origin, world.dynamicToStaticTable, world.dynamicItemInventory)
|
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)
|
val world = invoke(worldDataStream, origin)
|
||||||
ingame.world = world
|
ingame.world = world
|
||||||
|
|
||||||
return 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
|
val currentPlayTime_t = time_t - ingame.loadedTime_t
|
||||||
|
|
||||||
world.comp = Common.getCompIndex()
|
world.comp = Common.getCompIndex()
|
||||||
world.lastPlayTime = time_t
|
|
||||||
world.totalPlayTime += currentPlayTime_t
|
|
||||||
|
|
||||||
world.actors.clear()
|
// world.actors.clear()
|
||||||
world.actors.addAll(actorsList.map { it.referenceID }.sorted().distinct())
|
// 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()
|
val time_t = App.getTIME_T()
|
||||||
preWrite(ingame, time_t, world, actorsList)
|
preWrite(ingame, time_t, world, actorsList)
|
||||||
val s = Common.jsoner.toJson(world)
|
val s = Common.jsoner.toJson(world)
|
||||||
@@ -18,6 +18,7 @@ import net.torvald.terrarum.audio.AudioMixer.Companion.DS_FLTIDX_PAN
|
|||||||
import net.torvald.terrarum.audio.dsp.*
|
import net.torvald.terrarum.audio.dsp.*
|
||||||
import net.torvald.terrarum.controller.TerrarumController
|
import net.torvald.terrarum.controller.TerrarumController
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.imagefont.TinyAlphNum
|
import net.torvald.terrarum.imagefont.TinyAlphNum
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
@@ -315,7 +316,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
val wallNum = it.getTileFromWall(mouseTileX, mouseTileY)
|
val wallNum = it.getTileFromWall(mouseTileX, mouseTileY)
|
||||||
val tileNum = it.getTileFromTerrain(mouseTileX, mouseTileY)
|
val tileNum = it.getTileFromTerrain(mouseTileX, mouseTileY)
|
||||||
val (oreNum, orePlacement) = it.getTileFromOre(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 fluid = it.getFluid(mouseTileX, mouseTileY)
|
||||||
val wireCount = wires.first?.size?.toString() ?: "no"
|
val wireCount = wires.first?.size?.toString() ?: "no"
|
||||||
val tdmg = it.getTerrainDamage(mouseTileX, mouseTileY).toIntAndFrac(2,2)
|
val tdmg = it.getTerrainDamage(mouseTileX, mouseTileY).toIntAndFrac(2,2)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package net.torvald.terrarum.utils
|
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.gameactors.ActorValue
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
|||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.FLUID_MIN_MASS
|
import net.torvald.terrarum.gameworld.*
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.shake
|
import net.torvald.terrarum.modulebasegame.worldgenerator.shake
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.serialise.toBig64
|
import net.torvald.terrarum.serialise.toBig64
|
||||||
@@ -43,7 +41,7 @@ import kotlin.math.roundToInt
|
|||||||
internal object BlocksDrawer {
|
internal object BlocksDrawer {
|
||||||
|
|
||||||
/** World change is managed by IngameRenderer.setWorld() */
|
/** 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) {
|
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.
|
// 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
|
// 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.
|
// 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)
|
WALL -> world.layerWall.unsafeGetTile(wx, wy)
|
||||||
TERRAIN -> world.layerTerrain.unsafeGetTile(wx, wy)
|
TERRAIN -> world.layerTerrain.unsafeGetTile(wx, wy)
|
||||||
ORES -> world.layerOres.unsafeGetTile(wx, wy)//.also { println(it) }
|
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
|
if (number == 65535 || fill < 1f/30f) 0
|
||||||
else number
|
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 nearbyFluidType = fluids.asSequence().filter { it.amount >= 0.5f / 16f }.map { it.type }.filter { it.startsWith("fluid@") }.sorted().firstOrNull()
|
||||||
|
|
||||||
val fillThis =
|
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)
|
val tile = world.getTileFromTerrain(wx, wy)
|
||||||
|
|
||||||
@@ -671,7 +673,7 @@ internal object BlocksDrawer {
|
|||||||
rawTileNum + nearbyTilesInfo
|
rawTileNum + nearbyTilesInfo
|
||||||
// special case: ores
|
// special case: ores
|
||||||
else if (mode == 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
|
// rest of the cases: terrain and walls
|
||||||
else rawTileNum + when (renderTag.maskType) {
|
else rawTileNum + when (renderTag.maskType) {
|
||||||
CreateTileAtlas.RenderTag.MASK_NA -> 0
|
CreateTileAtlas.RenderTag.MASK_NA -> 0
|
||||||
@@ -1188,7 +1190,7 @@ internal object BlocksDrawer {
|
|||||||
get() {
|
get() {
|
||||||
val rate = (((Gdx.graphics.framesPerSecond / 50f) * TILE_SIZEF) / maxOf(WorldCamera.deltaX.abs(), WorldCamera.deltaY.abs()).coerceAtLeast(1)).roundToInt().coerceIn(1, 4)
|
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())
|
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
|
private var camTransX = 0
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package net.torvald.terrarum.worlddrawer
|
package net.torvald.terrarum.worlddrawer
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.jme3.math.FastMath
|
|
||||||
import net.torvald.colourutil.ColourTemp
|
import net.torvald.colourutil.ColourTemp
|
||||||
import net.torvald.terrarum.*
|
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.blockstats.TileSurvey
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@@ -17,7 +15,7 @@ import kotlin.math.roundToInt
|
|||||||
object FeaturesDrawer {
|
object FeaturesDrawer {
|
||||||
|
|
||||||
/** World change is managed by IngameRenderer.setWorld() */
|
/** 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
|
//const val TILE_SIZE = TILE_SIZE
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import net.torvald.terrarum.gameitems.GameItem
|
|||||||
import net.torvald.terrarum.gameitems.isBlock
|
import net.torvald.terrarum.gameitems.isBlock
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||||
import net.torvald.terrarum.modulebasegame.ui.abs
|
import net.torvald.terrarum.modulebasegame.ui.abs
|
||||||
@@ -43,7 +44,7 @@ import kotlin.math.*
|
|||||||
object LightmapRenderer {
|
object LightmapRenderer {
|
||||||
|
|
||||||
/** World change is managed by IngameRenderer.setWorld() */
|
/** 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 lateinit var lightCalcShader: ShaderProgram
|
||||||
//private val SHADER_LIGHTING = AppLoader.getConfigBoolean("gpulightcalc")
|
//private val SHADER_LIGHTING = AppLoader.getConfigBoolean("gpulightcalc")
|
||||||
@@ -141,7 +142,7 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun recalculate(actorContainer: List<ActorWithBody>) {
|
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) {
|
private fun _recalculate(actorContainer: List<ActorWithBody>, lightmap: UnsafeCvecArray) {
|
||||||
@@ -153,7 +154,7 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
catch (e: NullPointerException) {
|
catch (e: NullPointerException) {
|
||||||
System.err.println("[LightmapRendererNew.recalculate] Attempted to refer destroyed unsafe array " +
|
System.err.println("[LightmapRendererNew.recalculate] Attempted to refer destroyed unsafe array " +
|
||||||
"(${world.layerTerrain.ptr})")
|
"(${world.layerTerrain})")
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
return // something's wrong but we'll ignore it like a trustful AK
|
return // something's wrong but we'll ignore it like a trustful AK
|
||||||
}
|
}
|
||||||
@@ -656,7 +657,7 @@ object LightmapRenderer {
|
|||||||
|
|
||||||
internal fun draw(): Texture {
|
internal fun draw(): Texture {
|
||||||
|
|
||||||
if (!world.layerTerrain.ptrDestroyed) {
|
if (!world.layerTerrain.disposed) {
|
||||||
// when shader is not used: 0.5 ms on 6700K
|
// when shader is not used: 0.5 ms on 6700K
|
||||||
App.measureDebugTime("Renderer.LightToScreen") {
|
App.measureDebugTime("Renderer.LightToScreen") {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user