diff --git a/src/net/torvald/terrarum/gameitems/GameItem.kt b/src/net/torvald/terrarum/gameitems/GameItem.kt index 7270ac945..4981cfafa 100644 --- a/src/net/torvald/terrarum/gameitems/GameItem.kt +++ b/src/net/torvald/terrarum/gameitems/GameItem.kt @@ -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@") diff --git a/src/net/torvald/terrarum/gameworld/BlockLayer.kt b/src/net/torvald/terrarum/gameworld/BlockLayer.kt index 620e55eb1..888518e61 100644 --- a/src/net/torvald/terrarum/gameworld/BlockLayer.kt +++ b/src/net/torvald/terrarum/gameworld/BlockLayer.kt @@ -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 { - return object : Iterator { - 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 - } -} +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameworld/BlockLayerI16.kt b/src/net/torvald/terrarum/gameworld/BlockLayerI16.kt new file mode 100644 index 000000000..670b49838 --- /dev/null +++ b/src/net/torvald/terrarum/gameworld/BlockLayerI16.kt @@ -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 { + return object : Iterator { + 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 + } +} diff --git a/src/net/torvald/terrarum/gameworld/BlockLayerI16I8.kt b/src/net/torvald/terrarum/gameworld/BlockLayerI16I8.kt new file mode 100644 index 000000000..a0775ba23 --- /dev/null +++ b/src/net/torvald/terrarum/gameworld/BlockLayerI16I8.kt @@ -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 { + return object : Iterator { + 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 { + 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 + } +} diff --git a/src/net/torvald/terrarum/gameworld/GameWorld.kt b/src/net/torvald/terrarum/gameworld/GameWorld.kt index 0f263e319..a8134925c 100644 --- a/src/net/torvald/terrarum/gameworld/GameWorld.kt +++ b/src/net/torvald/terrarum/gameworld/GameWorld.kt @@ -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() val terrainDamages = HashArray() - 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 { return object : Iterator { diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/PlayerBuilderSigrid.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/PlayerBuilderSigrid.kt index 1751b35af..cec715d01 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/PlayerBuilderSigrid.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/PlayerBuilderSigrid.kt @@ -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") + } } } } diff --git a/src/net/torvald/terrarum/modulebasegame/serialise/WriteSavegame.kt b/src/net/torvald/terrarum/modulebasegame/serialise/WriteSavegame.kt index 72461be69..840a6301f 100644 --- a/src/net/torvald/terrarum/modulebasegame/serialise/WriteSavegame.kt +++ b/src/net/torvald/terrarum/modulebasegame/serialise/WriteSavegame.kt @@ -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) diff --git a/src/net/torvald/terrarum/modulebasegame/serialise/WriteWorld.kt b/src/net/torvald/terrarum/modulebasegame/serialise/WriteWorld.kt index 2e5dc3058..a1050227d 100644 --- a/src/net/torvald/terrarum/modulebasegame/serialise/WriteWorld.kt +++ b/src/net/torvald/terrarum/modulebasegame/serialise/WriteWorld.kt @@ -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") diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt index 82b8d16bd..43363e438 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt @@ -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) + } } /* diff --git a/src/net/torvald/terrarum/serialise/Common.kt b/src/net/torvald/terrarum/serialise/Common.kt index eff34fc29..3a6715a3a 100644 --- a/src/net/torvald/terrarum/serialise/Common.kt +++ b/src/net/torvald/terrarum/serialise/Common.kt @@ -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 { - override fun write(json: Json, obj: BlockLayer, knownType: Class<*>?) { + jsoner.setSerializer(BlockLayerI16::class.java, object : Json.Serializer { + 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 diff --git a/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt b/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt index a2fcc6516..34d09d851 100644 --- a/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt +++ b/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt @@ -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) } diff --git a/src/net/torvald/unsafe/UnsafePtr.kt b/src/net/torvald/unsafe/UnsafePtr.kt index 44858f755..6e08f167a 100644 --- a/src/net/torvald/unsafe/UnsafePtr.kt +++ b/src/net/torvald/unsafe/UnsafePtr.kt @@ -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 }