mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
Generalised BlockLayer
This commit is contained in:
@@ -423,3 +423,4 @@ fun ItemID.isVirtual() = this.startsWith("$PREFIX_VIRTUALTILE@")
|
||||
fun ItemID.isBlock() = !this.contains('@') && !this.isDynamic()
|
||||
fun ItemID.isWall() = this.startsWith("wall@")
|
||||
fun ItemID.isFluid() = this.startsWith("fluid@")
|
||||
fun ItemID.isOre() = this.startsWith("ores@")
|
||||
|
||||
@@ -1,110 +1,14 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
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
|
||||
* Created by minjaesong on 2023-10-10.
|
||||
*/
|
||||
open class BlockLayer(val width: Int, val height: Int) : Disposable {
|
||||
// for some reason, all the efforts of saving the memory space were futile.
|
||||
interface BlockLayer : Disposable {
|
||||
|
||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * BYTES_PER_BLOCK)
|
||||
val bytesPerBlock: Long
|
||||
fun unsafeToBytes(x: Int, y: Int): ByteArray
|
||||
fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray)
|
||||
|
||||
val ptrDestroyed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
init {
|
||||
ptr.fillWith(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 * BYTES_PER_BLOCK
|
||||
}
|
||||
override fun next(): Byte {
|
||||
iteratorCount += 1
|
||||
return ptr[iteratorCount - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
|
||||
return lsb.toUint() + msb.toUint().shl(8)
|
||||
}
|
||||
|
||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||
|
||||
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
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 fun dispose() {
|
||||
ptr.destroy()
|
||||
printdbg(this, "BlockLayer with ptr ($ptr) successfully freed")
|
||||
}
|
||||
|
||||
override fun toString(): String = ptr.toString()
|
||||
|
||||
companion object {
|
||||
@Transient val BYTES_PER_BLOCK = 2L
|
||||
}
|
||||
}
|
||||
}
|
||||
126
src/net/torvald/terrarum/gameworld/BlockLayerI16.kt
Normal file
126
src/net/torvald/terrarum/gameworld/BlockLayerI16.kt
Normal file
@@ -0,0 +1,126 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
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
|
||||
*/
|
||||
open class BlockLayerI16(val width: Int, 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 * BYTES_PER_BLOCK)
|
||||
|
||||
val ptrDestroyed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
init {
|
||||
ptr.fillWith(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 * BYTES_PER_BLOCK
|
||||
}
|
||||
override fun next(): Byte {
|
||||
iteratorCount += 1
|
||||
return ptr[iteratorCount - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
|
||||
return lsb.toUint() + msb.toUint().shl(8)
|
||||
}
|
||||
|
||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
|
||||
return byteArrayOf(msb, lsb)
|
||||
}
|
||||
|
||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||
|
||||
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 = BYTES_PER_BLOCK * (y * width + x)
|
||||
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 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
|
||||
}
|
||||
}
|
||||
126
src/net/torvald/terrarum/gameworld/BlockLayerI16I8.kt
Normal file
126
src/net/torvald/terrarum/gameworld/BlockLayerI16I8.kt
Normal file
@@ -0,0 +1,126 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
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 BlockLayerI16I8 (val width: Int, 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 * BYTES_PER_BLOCK)
|
||||
|
||||
val ptrDestroyed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
init {
|
||||
ptr.fillWith(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 * BYTES_PER_BLOCK
|
||||
}
|
||||
override fun next(): Byte {
|
||||
iteratorCount += 1
|
||||
return ptr[iteratorCount - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun unsafeGetTile(x: Int, y: Int): Pair<Int, Int> {
|
||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
val placement = ptr[offset + 2]
|
||||
|
||||
return lsb.toUint() + msb.toUint().shl(8) to placement.toUint()
|
||||
}
|
||||
|
||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
val placement = ptr[offset + 2]
|
||||
|
||||
return byteArrayOf(msb, lsb, placement)
|
||||
}
|
||||
|
||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||
|
||||
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 = BYTES_PER_BLOCK * (y * width + x)
|
||||
ptr[offset] = bytes[1]
|
||||
ptr[offset + 1] = bytes[0]
|
||||
ptr[offset + 2] = 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 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
|
||||
}
|
||||
}
|
||||
@@ -7,22 +7,20 @@ import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
import net.torvald.terrarum.concurrent.ThreadExecutor
|
||||
import net.torvald.terrarum.gameactors.ActorID
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameitems.isFluid
|
||||
import net.torvald.terrarum.gameitems.isOre
|
||||
import net.torvald.terrarum.itemproperties.ItemRemapTable
|
||||
import net.torvald.terrarum.itemproperties.ItemTable
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.utils.*
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
import net.torvald.terrarum.weather.WeatherSchedule
|
||||
import net.torvald.terrarum.weather.Weatherbox
|
||||
import net.torvald.util.SortedArrayList
|
||||
import org.dyn4j.geometry.Vector2
|
||||
import java.util.*
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
typealias BlockAddress = Long
|
||||
|
||||
@@ -40,8 +38,8 @@ class PhysicalStatus() {
|
||||
* Special version of GameWorld where everything, including layer data, are saved in a single JSON file (i.e. not chunked)
|
||||
*/
|
||||
class SimpleGameWorld(width: Int, height: Int) : GameWorld(width, height) {
|
||||
override lateinit var layerWall: BlockLayer
|
||||
override lateinit var layerTerrain: BlockLayer
|
||||
override lateinit var layerWall: BlockLayerI16
|
||||
override lateinit var layerTerrain: BlockLayerI16
|
||||
constructor() : this(0, 0)
|
||||
}
|
||||
|
||||
@@ -83,12 +81,12 @@ open class GameWorld(
|
||||
}
|
||||
|
||||
//layers
|
||||
@Transient lateinit open var layerWall: BlockLayer
|
||||
@Transient lateinit open var layerTerrain: BlockLayer
|
||||
val layerOres = HashedOres() // damage to the block follows `terrainDamages`
|
||||
@Transient lateinit open var layerWall: BlockLayerI16
|
||||
@Transient lateinit open var layerTerrain: BlockLayerI16
|
||||
@Transient lateinit open var layerOres: BlockLayerI16I8 // damage to the block follows `terrainDamages`
|
||||
val wallDamages = HashArray<Float>()
|
||||
val terrainDamages = HashArray<Float>()
|
||||
val layerFluids = HashedFluidTypeAndFills()
|
||||
val layerFluids = HashedFluidTypeAndFills() // TODO: chunk them using BlockLayerI32
|
||||
|
||||
|
||||
|
||||
@@ -201,8 +199,8 @@ open class GameWorld(
|
||||
this.spawnX = width / 2
|
||||
this.spawnY = 150
|
||||
|
||||
layerTerrain = BlockLayer(width, height)
|
||||
layerWall = BlockLayer(width, height)
|
||||
layerTerrain = BlockLayerI16(width, height)
|
||||
layerWall = BlockLayerI16(width, height)
|
||||
|
||||
// temperature layer: 2x2 is one cell
|
||||
//layerThermal = MapLayerHalfFloat(width, height, averageTemperature)
|
||||
@@ -277,6 +275,7 @@ open class GameWorld(
|
||||
fun getLayer(index: Int) = when(index) {
|
||||
0 -> layerTerrain
|
||||
1 -> layerWall
|
||||
2 -> layerOres
|
||||
else -> null//throw IllegalArgumentException("Unknown layer index: $index")
|
||||
}
|
||||
|
||||
@@ -549,6 +548,21 @@ open class GameWorld(
|
||||
throw IllegalArgumentException("illegal mode input: " + mode.toString())
|
||||
}
|
||||
|
||||
fun getTileFromOre(rawX: Int, rawY: Int): OrePlacement? {
|
||||
val (x, y) = coerceXY(rawX, rawY)
|
||||
val (tileNum, placement) = layerOres.unsafeGetTile(x, y)
|
||||
val tileName = tileNumberToNameMap[tileNum.toLong()]
|
||||
if (tileName == Block.AIR)
|
||||
return null
|
||||
else
|
||||
return OrePlacement(tileName ?: Block.UPDATE, placement)
|
||||
}
|
||||
|
||||
fun setTileOre(rawX: Int, rawY: Int, ore: ItemID, placement: Int) {
|
||||
val (x, y) = coerceXY(rawX, rawY)
|
||||
layerOres.unsafeSetTile(x, y, tileNameToNumberMap[ore]!!, placement)
|
||||
}
|
||||
|
||||
fun terrainIterator(): Iterator<ItemID> {
|
||||
return object : Iterator<ItemID> {
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package net.torvald.terrarum.modulebasegame.gameactors
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.BlockCodex
|
||||
import net.torvald.terrarum.WireCodex
|
||||
import net.torvald.terrarum.gameitems.isBlock
|
||||
import net.torvald.terrarum.gameitems.isWall
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2016-02-03.
|
||||
@@ -74,19 +76,22 @@ object PlayerBuilderSigrid {
|
||||
fun fillTestInventory(inventory: ActorInventory) {
|
||||
|
||||
App.tileMaker.tags.forEach { (t, _) ->
|
||||
val prop = BlockCodex[t]
|
||||
if (!prop.isActorBlock && !prop.hasTag("AIR") && !prop.hasTag("INTERNAL")) {
|
||||
if (t.isBlock() || t.isWall()) {
|
||||
val prop = BlockCodex[t]
|
||||
if (!prop.isActorBlock && !prop.hasTag("AIR") && !prop.hasTag("INTERNAL")) {
|
||||
|
||||
inventory.add(t, 9995)
|
||||
try {
|
||||
inventory.add(
|
||||
"wall@$t",
|
||||
9995
|
||||
) // this code will try to add nonexisting wall items, do not get surprised with NPEs
|
||||
}
|
||||
catch (e: NullPointerException) { /* tHiS iS fInE */ }
|
||||
catch (e: Throwable) {
|
||||
System.err.println("[PlayerBuilder] $e")
|
||||
inventory.add(t, 9995)
|
||||
try {
|
||||
inventory.add(
|
||||
"wall@$t",
|
||||
9995
|
||||
) // this code will try to add nonexisting wall items, do not get surprised with NPEs
|
||||
}
|
||||
catch (e: NullPointerException) { /* tHiS iS fInE */
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
System.err.println("[PlayerBuilder] $e")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,17 @@ import com.badlogic.gdx.graphics.Pixmap
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.gameworld.BlockLayer
|
||||
import net.torvald.terrarum.gameworld.BlockLayerI16
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.ChunkLoadingLoadScreen
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.SavegameMigrator
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.savegame.*
|
||||
import net.torvald.terrarum.savegame.VDFileID.SAVEGAMEINFO
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import net.torvald.terrarum.utils.JsonFetcher
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
import java.io.File
|
||||
import java.io.Reader
|
||||
@@ -145,8 +143,8 @@ object LoadSavegame {
|
||||
val worldDiskSavegameInfo = ByteArray64Reader(worldDisk.getFile(SAVEGAMEINFO)!!.bytes, Common.CHARSET)
|
||||
val world = ReadWorld(worldDiskSavegameInfo, worldDisk.diskFile)
|
||||
|
||||
world.layerTerrain = BlockLayer(world.width, world.height)
|
||||
world.layerWall = BlockLayer(world.width, world.height)
|
||||
world.layerTerrain = BlockLayerI16(world.width, world.height)
|
||||
world.layerWall = BlockLayerI16(world.width, world.height)
|
||||
|
||||
newIngame.world = world // must be set before the loadscreen, otherwise the loadscreen will try to read from the NullWorld which is already destroyed
|
||||
newIngame.worldDisk = VDUtil.readDiskArchive(worldDisk.diskFile, Level.INFO)
|
||||
|
||||
@@ -4,6 +4,8 @@ import net.torvald.terrarum.ItemCodex
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameactors.NoSerialise
|
||||
import net.torvald.terrarum.gameworld.BlockLayer
|
||||
import net.torvald.terrarum.gameworld.BlockLayerI16
|
||||
import net.torvald.terrarum.gameworld.BlockLayerI16I8
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
@@ -82,9 +84,7 @@ object WriteWorld {
|
||||
val ba = ByteArray64()
|
||||
for (y in cy * LandUtil.CHUNK_H until (cy + 1) * LandUtil.CHUNK_H) {
|
||||
for (x in cx * LandUtil.CHUNK_W until (cx + 1) * LandUtil.CHUNK_W) {
|
||||
val tilenum = layer.unsafeGetTile(x, y)
|
||||
ba.appendByte(tilenum.ushr(8).and(255).toByte())
|
||||
ba.appendByte(tilenum.and(255).toByte())
|
||||
ba.appendBytes(layer.unsafeToBytes(x, y))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,17 +116,19 @@ object ReadWorld {
|
||||
|
||||
fun decodeChunkToLayer(chunk: ByteArray64, targetLayer: BlockLayer, cx: Int, cy: Int) {
|
||||
val bytes = Common.unzip(chunk)
|
||||
if (bytes.size != cw * ch * 2L)
|
||||
if (bytes.size != cw * ch * targetLayer.bytesPerBlock)
|
||||
throw UnsupportedOperationException("Chunk size mismatch: decoded chunk size is ${bytes.size} bytes " +
|
||||
"where ${LandUtil.CHUNK_W * LandUtil.CHUNK_H * 2L} bytes (Int16 of ${LandUtil.CHUNK_W}x${LandUtil.CHUNK_H}) were expected")
|
||||
"where ${LandUtil.CHUNK_W * LandUtil.CHUNK_H * targetLayer.bytesPerBlock} bytes (Int${8 * targetLayer.bytesPerBlock} of ${LandUtil.CHUNK_W}x${LandUtil.CHUNK_H}) were expected")
|
||||
|
||||
for (k in 0 until cw * ch) {
|
||||
val tilenum = bytes[2L*k].toUint().shl(8) or bytes[2L*k + 1].toUint()
|
||||
val offx = k % cw
|
||||
val offy = k / cw
|
||||
val ba = ByteArray(targetLayer.bytesPerBlock.toInt()) {
|
||||
bytes[targetLayer.bytesPerBlock * k + it]
|
||||
}
|
||||
|
||||
// try {
|
||||
targetLayer.unsafeSetTile(cx * cw + offx, cy * ch + offy, tilenum)
|
||||
targetLayer.unsafeSetTile(cx * cw + offx, cy * ch + offy, ba)
|
||||
// }
|
||||
// catch (e: IndexOutOfBoundsException) {
|
||||
// printdbgerr(this, "IndexOutOfBoundsException, cx = $cx, cy = $cy, k = $k, offx = $offx, offy = $offy")
|
||||
|
||||
@@ -111,6 +111,12 @@ class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par
|
||||
world.setTileTerrain(x, y, newTile, true)
|
||||
|
||||
world.setTileWall(x, y, newTile, true)
|
||||
|
||||
|
||||
// TODO TEST CODE
|
||||
if (newTile == Block.DIRT) {
|
||||
world.setTileOre(x, y, "ores@basegame:1", 0)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,10 +4,9 @@ import com.badlogic.gdx.utils.Json
|
||||
import com.badlogic.gdx.utils.JsonValue
|
||||
import com.badlogic.gdx.utils.JsonWriter
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration
|
||||
import net.torvald.terrarum.console.EchoError
|
||||
import net.torvald.terrarum.gameworld.BlockLayer
|
||||
import net.torvald.terrarum.gameworld.BlockLayerI16
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
import net.torvald.terrarum.savegame.ByteArray64
|
||||
@@ -42,7 +41,7 @@ object Common {
|
||||
val CHARSET = Charsets.UTF_8
|
||||
|
||||
/** dispose of the `offendingObject` after rejection! */
|
||||
class BlockLayerHashMismatchError(val oldHash: String, val newHash: String, val offendingObject: BlockLayer) : Error("Old Hash $oldHash != New Hash $newHash")
|
||||
class BlockLayerHashMismatchError(val oldHash: String, val newHash: String, val offendingObject: BlockLayerI16) : Error("Old Hash $oldHash != New Hash $newHash")
|
||||
|
||||
private fun Byte.tostr() = this.toInt().and(255).toString(16).padStart(2,'0')
|
||||
private val digester = DigestUtils.getSha256Digest()
|
||||
@@ -76,8 +75,8 @@ object Common {
|
||||
}
|
||||
})
|
||||
// BlockLayer
|
||||
jsoner.setSerializer(BlockLayer::class.java, object : Json.Serializer<BlockLayer> {
|
||||
override fun write(json: Json, obj: BlockLayer, knownType: Class<*>?) {
|
||||
jsoner.setSerializer(BlockLayerI16::class.java, object : Json.Serializer<BlockLayerI16> {
|
||||
override fun write(json: Json, obj: BlockLayerI16, knownType: Class<*>?) {
|
||||
digester.reset()
|
||||
obj.bytesIterator().forEachRemaining { digester.update(it) }
|
||||
val hash = StringBuilder().let { sb -> digester.digest().forEach { sb.append(it.tostr()) }; sb.toString() }
|
||||
@@ -87,7 +86,7 @@ object Common {
|
||||
json.writeValue(layer)
|
||||
}
|
||||
|
||||
override fun read(json: Json, jsonData: JsonValue, type: Class<*>): BlockLayer {
|
||||
override fun read(json: Json, jsonData: JsonValue, type: Class<*>): BlockLayerI16 {
|
||||
// full manual
|
||||
try {
|
||||
return strToBlockLayer(LayerInfo(
|
||||
@@ -437,12 +436,12 @@ object Common {
|
||||
* @param b a BlockLayer
|
||||
* @return Bytes in [b] which are GZip'd then Ascii85-encoded
|
||||
*/
|
||||
private fun blockLayerToStr(b: BlockLayer): String {
|
||||
private fun blockLayerToStr(b: BlockLayerI16): String {
|
||||
return bytesToZipdStr(b.bytesIterator())
|
||||
}
|
||||
|
||||
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayer {
|
||||
val layer = BlockLayer(layerInfo.x, layerInfo.y)
|
||||
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayerI16 {
|
||||
val layer = BlockLayerI16(layerInfo.x, layerInfo.y)
|
||||
val unzipdBytes = strToBytes(StringReader(layerInfo.b))
|
||||
|
||||
// write to blocklayer and the digester
|
||||
|
||||
@@ -162,7 +162,7 @@ class CreateTileAtlas {
|
||||
if (dirName == "blocks") {
|
||||
// filter files that do not exist on the blockcodex
|
||||
dir.list()
|
||||
.filter { tgaFile -> !tgaFile.isDirectory && (BlockCodex.getOrNull("$modname:${tgaFile.nameWithoutExtension()}") != null) }
|
||||
.filter { tgaFile -> tgaFile.extension() == "tga" && !tgaFile.isDirectory && (BlockCodex.getOrNull("$modname:${tgaFile.nameWithoutExtension()}") != null) }
|
||||
.sortedBy { it.nameWithoutExtension().toInt() }
|
||||
.forEach { tgaFile: FileHandle -> // toInt() to sort by the number, not lexicographically
|
||||
// tgaFile be like: ./assets/mods/basegame/blocks/32.tga (which is not always .tga)
|
||||
@@ -173,7 +173,7 @@ class CreateTileAtlas {
|
||||
}
|
||||
else {
|
||||
// TODO test
|
||||
dir.list().filter { tgaFile -> !tgaFile.isDirectory }.sortedBy { it.nameWithoutExtension().toInt() }.forEach { tgaFile: FileHandle ->
|
||||
dir.list().filter { tgaFile -> tgaFile.extension() == "tga" && !tgaFile.isDirectory }.sortedBy { it.nameWithoutExtension().toInt() }.forEach { tgaFile: FileHandle ->
|
||||
val newFile = ModMgr.GameRetextureLoader.altFilePaths.getOrDefault(tgaFile.path(), tgaFile)
|
||||
tgaList[dirName]!!.add(modname to newFile)
|
||||
}
|
||||
|
||||
@@ -198,6 +198,7 @@ internal class UnsafePtr(pointer: Long, allocSize: Long) {
|
||||
}
|
||||
|
||||
override fun toString() = "0x${ptr.toString(16)} with size $size"
|
||||
fun toString(prefix: String) = "$prefix 0x${ptr.toString(16)} with size $size"
|
||||
override fun equals(other: Any?) = this.ptr == (other as UnsafePtr).ptr && this.size == other.size
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user