mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
80 fps with unsafe access
This commit is contained in:
Binary file not shown.
@@ -3,6 +3,7 @@ package net.torvald.terrarum
|
|||||||
import com.badlogic.gdx.Screen
|
import com.badlogic.gdx.Screen
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.utils.Queue
|
import com.badlogic.gdx.utils.Queue
|
||||||
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
@@ -74,7 +75,15 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
override fun resize(width: Int, height: Int) {
|
override fun resize(width: Int, height: Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You ABSOLUTELY must call this in your child classes (```super.dispose()```) and the AppLoader to properly
|
||||||
|
* dispose of the world, which uses unsafe memory allocation.
|
||||||
|
* Failing to do this will result to a memory leak!
|
||||||
|
*/
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
|
printdbg(this, "Thank you for properly disposing the world!")
|
||||||
|
|
||||||
|
world.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////
|
////////////
|
||||||
|
|||||||
@@ -27,12 +27,10 @@ import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
|||||||
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.modulebasegame.weather.WeatherMixer
|
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
|
||||||
import net.torvald.terrarum.serialise.ReadLayerData
|
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
import java.io.FileInputStream
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2017-09-02.
|
* Created by minjaesong on 2017-09-02.
|
||||||
@@ -129,7 +127,10 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
|||||||
printdbg(this, "Intro pre-load")
|
printdbg(this, "Intro pre-load")
|
||||||
|
|
||||||
|
|
||||||
demoWorld = ReadLayerData(FileInputStream(ModMgr.getFile("basegame", "demoworld")))
|
demoWorld = GameWorldExtension(1, 64, 64, 0L, 0L, 0)
|
||||||
|
|
||||||
|
printdbg(this, "Demo world gen complete")
|
||||||
|
|
||||||
// set time to summer
|
// set time to summer
|
||||||
demoWorld.time.addTime(WorldTime.DAY_LENGTH * 32)
|
demoWorld.time.addTime(WorldTime.DAY_LENGTH * 32)
|
||||||
|
|
||||||
@@ -138,7 +139,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
|
|||||||
cameraNodes = kotlin.FloatArray(nodeCount) { it ->
|
cameraNodes = kotlin.FloatArray(nodeCount) { it ->
|
||||||
val tileXPos = (demoWorld.width.toFloat() * it / nodeCount).floorInt()
|
val tileXPos = (demoWorld.width.toFloat() * it / nodeCount).floorInt()
|
||||||
var travelDownCounter = 0
|
var travelDownCounter = 0
|
||||||
while (!BlockCodex[demoWorld.getTileFromTerrain(tileXPos, travelDownCounter)].isSolid) {
|
while (travelDownCounter < demoWorld.height && !BlockCodex[demoWorld.getTileFromTerrain(tileXPos, travelDownCounter)].isSolid) {
|
||||||
travelDownCounter += 4
|
travelDownCounter += 4
|
||||||
}
|
}
|
||||||
travelDownCounter * CreateTileAtlas.TILE_SIZE.toFloat()
|
travelDownCounter * CreateTileAtlas.TILE_SIZE.toFloat()
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import net.torvald.terrarum.AppLoader
|
|||||||
import net.torvald.terrarum.AppLoader.printmsg
|
import net.torvald.terrarum.AppLoader.printmsg
|
||||||
import net.torvald.terrarum.gameworld.FluidType
|
import net.torvald.terrarum.gameworld.FluidType
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.MapLayer
|
|
||||||
import net.torvald.terrarum.gameworld.PairedMapLayer
|
|
||||||
import net.torvald.terrarum.utils.CSVFetcher
|
import net.torvald.terrarum.utils.CSVFetcher
|
||||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||||
import org.apache.commons.csv.CSVRecord
|
import org.apache.commons.csv.CSVRecord
|
||||||
@@ -20,7 +18,7 @@ object BlockCodex {
|
|||||||
private var blockProps = HashMap<Int, BlockProp>()
|
private var blockProps = HashMap<Int, BlockProp>()
|
||||||
|
|
||||||
/** 4096 */
|
/** 4096 */
|
||||||
const val MAX_TERRAIN_TILES = MapLayer.RANGE * PairedMapLayer.RANGE
|
const val MAX_TERRAIN_TILES = GameWorld.TILES_SUPPORTED
|
||||||
|
|
||||||
private val nullProp = BlockProp()
|
private val nullProp = BlockProp()
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package net.torvald.terrarum.blockstats
|
|||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.MapLayer
|
|
||||||
import net.torvald.terrarum.modulebasegame.Ingame
|
import net.torvald.terrarum.modulebasegame.Ingame
|
||||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||||
@@ -71,11 +70,5 @@ object BlockStats {
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
* @return copy of the stat data
|
|
||||||
*/
|
|
||||||
val statCopy: ShortArray
|
|
||||||
get() = Arrays.copyOf(tilestat, MapLayer.RANGE)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
147
src/net/torvald/terrarum/gameworld/BlockLayer.kt
Normal file
147
src/net/torvald/terrarum/gameworld/BlockLayer.kt
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
|
import sun.misc.Unsafe
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2016-01-17.
|
||||||
|
*/
|
||||||
|
open class BlockLayer(val width: Int, val height: Int) : Disposable {
|
||||||
|
|
||||||
|
private val unsafe: Unsafe
|
||||||
|
init {
|
||||||
|
val unsafeConstructor = Unsafe::class.java.getDeclaredConstructor()
|
||||||
|
unsafeConstructor.isAccessible = true
|
||||||
|
unsafe = unsafeConstructor.newInstance()
|
||||||
|
}
|
||||||
|
private var unsafeArrayInitialised = false
|
||||||
|
|
||||||
|
private var layerPtr = unsafe.allocateMemory(width * height * BYTES_PER_BLOCK.toLong())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data Byte array representation of the layer, where:
|
||||||
|
* - every 2n-th byte is lowermost 8 bits of the tile number
|
||||||
|
* - every (2n+1)th byte is uppermost 4 (4096 blocks) or 8 (65536 blocks) bits of the tile number.
|
||||||
|
*
|
||||||
|
* When 4096-block mode is being used, every (2n+1)th byte is filled in this format:
|
||||||
|
* ```
|
||||||
|
* (MSB) 0 0 0 0 a b c d (LSB)
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* In other words, the valid range for the every (2n+1)th byte is 0..15.
|
||||||
|
*
|
||||||
|
* TL;DR: LITTLE ENDIAN PLEASE
|
||||||
|
*/
|
||||||
|
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||||
|
unsafe.allocateMemory(width * height * BYTES_PER_BLOCK.toLong())
|
||||||
|
data.forEachIndexed { index, byte -> unsafe.putByte(layerPtr + index, byte) }
|
||||||
|
unsafeArrayInitialised = true
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (!unsafeArrayInitialised) {
|
||||||
|
unsafe.setMemory(layerPtr, width * height * BYTES_PER_BLOCK.toLong(), 0)
|
||||||
|
unsafeArrayInitialised = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over blocks of type `Int`.
|
||||||
|
*
|
||||||
|
* @return an Iterator.
|
||||||
|
*/
|
||||||
|
fun blocksIterator(): Iterator<Int> {
|
||||||
|
return object : Iterator<Int> {
|
||||||
|
|
||||||
|
private var iteratorCount = 0
|
||||||
|
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return iteratorCount < width * height
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun next(): Int {
|
||||||
|
val y = iteratorCount / width
|
||||||
|
val x = iteratorCount % width
|
||||||
|
// advance counter
|
||||||
|
iteratorCount += 2
|
||||||
|
|
||||||
|
val offset = 2 * (y * width + x)
|
||||||
|
val lsb = unsafe.getByte(layerPtr + offset)
|
||||||
|
val msb = unsafe.getByte(layerPtr + offset + 1)
|
||||||
|
|
||||||
|
//return data[y * width + x]
|
||||||
|
return lsb.toUint() + msb.toUint().shl(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over stored bytes.
|
||||||
|
*
|
||||||
|
* @return an Iterator.
|
||||||
|
*/
|
||||||
|
fun bytesIterator(): Iterator<Byte> {
|
||||||
|
return object : Iterator<Byte> {
|
||||||
|
|
||||||
|
private var iteratorCount = 0
|
||||||
|
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return iteratorCount < width * height
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun next(): Byte {
|
||||||
|
val y = iteratorCount / width
|
||||||
|
val x = iteratorCount % width
|
||||||
|
// advance counter
|
||||||
|
iteratorCount += 1
|
||||||
|
|
||||||
|
return unsafe.getByte(layerPtr + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
|
val offset = BYTES_PER_BLOCK * (y * width + x)
|
||||||
|
val lsb = unsafe.getByte(layerPtr + offset)
|
||||||
|
val msb = unsafe.getByte(layerPtr + 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()
|
||||||
|
|
||||||
|
unsafe.putByte(layerPtr + offset, lsb)
|
||||||
|
unsafe.putByte(layerPtr + 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 = 2 * 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() {
|
||||||
|
unsafe.freeMemory(layerPtr)
|
||||||
|
printdbg(this, "BlockLayer successfully freed")
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Transient val BYTES_PER_BLOCK = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this)
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
import net.torvald.gdx.graphics.Cvec
|
import net.torvald.gdx.graphics.Cvec
|
||||||
import net.torvald.terrarum.AppLoader.printdbg
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
@@ -17,14 +18,14 @@ import kotlin.math.sign
|
|||||||
|
|
||||||
typealias BlockAddress = Long
|
typealias BlockAddress = Long
|
||||||
|
|
||||||
open class GameWorld {
|
open class GameWorld : Disposable {
|
||||||
|
|
||||||
var worldName: String = "New World"
|
var worldName: String = "New World"
|
||||||
/** Index start at 1 */
|
/** Index start at 1 */
|
||||||
var worldIndex: Int
|
var worldIndex: Int
|
||||||
set(value) {
|
set(value) {
|
||||||
if (value <= 0)
|
if (value <= 0)
|
||||||
throw Error("World index start at 1; you entered $value")
|
throw Error("World index start at 1; you've entered $value")
|
||||||
|
|
||||||
printdbg(this, "Creation of new world with index $value, called by:")
|
printdbg(this, "Creation of new world with index $value, called by:")
|
||||||
Thread.currentThread().stackTrace.forEach {
|
Thread.currentThread().stackTrace.forEach {
|
||||||
@@ -46,17 +47,12 @@ open class GameWorld {
|
|||||||
val loadTime: Long = System.currentTimeMillis() / 1000L
|
val loadTime: Long = System.currentTimeMillis() / 1000L
|
||||||
|
|
||||||
//layers
|
//layers
|
||||||
@TEMzPayload("WALL", TEMzPayload.EIGHT_MSB)
|
@TEMzPayload("WALL", TEMzPayload.TWELVE_BITS_LITTLE)
|
||||||
val layerWall: MapLayer
|
val layerWall: BlockLayer
|
||||||
@TEMzPayload("TERR", TEMzPayload.EIGHT_MSB)
|
@TEMzPayload("TERR", TEMzPayload.EIGHT_MSB)
|
||||||
val layerTerrain: MapLayer
|
val layerTerrain: BlockLayer
|
||||||
//val layerWire: MapLayer
|
//val layerWire: MapLayer
|
||||||
|
|
||||||
@TEMzPayload("WALL", TEMzPayload.FOUR_LSB)
|
|
||||||
val layerWallLowBits: PairedMapLayer
|
|
||||||
@TEMzPayload("TERR", TEMzPayload.FOUR_LSB)
|
|
||||||
val layerTerrainLowBits: PairedMapLayer
|
|
||||||
|
|
||||||
//val layerThermal: MapLayerHalfFloat // in Kelvins
|
//val layerThermal: MapLayerHalfFloat // in Kelvins
|
||||||
//val layerFluidPressure: MapLayerHalfFloat // (milibar - 1000)
|
//val layerFluidPressure: MapLayerHalfFloat // (milibar - 1000)
|
||||||
|
|
||||||
@@ -108,11 +104,9 @@ open class GameWorld {
|
|||||||
this.spawnX = width / 2
|
this.spawnX = width / 2
|
||||||
this.spawnY = 200
|
this.spawnY = 200
|
||||||
|
|
||||||
layerTerrain = MapLayer(width, height)
|
layerTerrain = BlockLayer(width, height)
|
||||||
layerWall = MapLayer(width, height)
|
layerWall = BlockLayer(width, height)
|
||||||
//layerWire = MapLayer(width, height)
|
//layerWire = MapLayer(width, height)
|
||||||
layerTerrainLowBits = PairedMapLayer(width, height)
|
|
||||||
layerWallLowBits = PairedMapLayer(width, height)
|
|
||||||
|
|
||||||
wallDamages = HashMap()
|
wallDamages = HashMap()
|
||||||
terrainDamages = HashMap()
|
terrainDamages = HashMap()
|
||||||
@@ -140,8 +134,6 @@ open class GameWorld {
|
|||||||
layerTerrain = layerData.layerTerrain
|
layerTerrain = layerData.layerTerrain
|
||||||
layerWall = layerData.layerWall
|
layerWall = layerData.layerWall
|
||||||
//layerWire = layerData.layerWire
|
//layerWire = layerData.layerWire
|
||||||
layerTerrainLowBits = layerData.layerTerrainLowBits
|
|
||||||
layerWallLowBits = layerData.layerWallLowBits
|
|
||||||
|
|
||||||
wallDamages = layerData.wallDamages
|
wallDamages = layerData.wallDamages
|
||||||
terrainDamages = layerData.terrainDamages
|
terrainDamages = layerData.terrainDamages
|
||||||
@@ -163,23 +155,6 @@ open class GameWorld {
|
|||||||
this.totalPlayTime = totalPlayTime
|
this.totalPlayTime = totalPlayTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get 2d array data of terrain
|
|
||||||
|
|
||||||
* @return byte[][] terrain layer
|
|
||||||
*/
|
|
||||||
val terrainArray: ByteArray
|
|
||||||
get() = layerTerrain.data
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get 2d array data of wall
|
|
||||||
|
|
||||||
* @return byte[][] wall layer
|
|
||||||
*/
|
|
||||||
val wallArray: ByteArray
|
|
||||||
get() = layerWall.data
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get 2d array data of wire
|
* Get 2d array data of wire
|
||||||
|
|
||||||
@@ -190,34 +165,18 @@ open class GameWorld {
|
|||||||
|
|
||||||
private fun coerceXY(x: Int, y: Int) = (x fmod width) to (y.coerceIn(0, height - 1))
|
private fun coerceXY(x: Int, y: Int) = (x fmod width) to (y.coerceIn(0, height - 1))
|
||||||
|
|
||||||
fun getTileFromWall(x: Int, y: Int): Int? {
|
fun getTileFromWall(x: Int, y: Int): Int {
|
||||||
val (x, y) = coerceXY(x, y)
|
val (x, y) = coerceXY(x, y)
|
||||||
val wall: Int? = layerWall.getTile(x, y)
|
if (y !in 0 until height) throw Error("Y coord out of world boundary: $y")
|
||||||
val wallDamage: Int? = getWallLowBits(x, y)
|
|
||||||
return if (wall == null || wallDamage == null)
|
return layerWall.unsafeGetTile(x, y)
|
||||||
null
|
|
||||||
else
|
|
||||||
wall * PairedMapLayer.RANGE + wallDamage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTileFromTerrain(x: Int, y: Int): Int? {
|
fun getTileFromTerrain(x: Int, y: Int): Int {
|
||||||
val (x, y) = coerceXY(x, y)
|
val (x, y) = coerceXY(x, y)
|
||||||
val terrain: Int? = layerTerrain.getTile(x, y)
|
if (y !in 0 until height) throw Error("Y coord out of world boundary: $y")
|
||||||
val terrainDamage: Int? = getTerrainLowBits(x, y)
|
|
||||||
return if (terrain == null || terrainDamage == null)
|
|
||||||
null
|
|
||||||
else
|
|
||||||
terrain * PairedMapLayer.RANGE + terrainDamage
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getWallLowBits(x: Int, y: Int): Int? {
|
return layerTerrain.unsafeGetTile(x, y)
|
||||||
val (x, y) = coerceXY(x, y)
|
|
||||||
return layerWallLowBits.getData(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getTerrainLowBits(x: Int, y: Int): Int? {
|
|
||||||
val (x, y) = coerceXY(x, y)
|
|
||||||
return layerTerrainLowBits.getData(x, y)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -233,11 +192,9 @@ open class GameWorld {
|
|||||||
val tilenum = tilenum % TILES_SUPPORTED // does work without this, but to be safe...
|
val tilenum = tilenum % TILES_SUPPORTED // does work without this, but to be safe...
|
||||||
|
|
||||||
val oldWall = getTileFromWall(x, y)
|
val oldWall = getTileFromWall(x, y)
|
||||||
layerWall.setTile(x, y, (tilenum / PairedMapLayer.RANGE).toByte())
|
layerWall.unsafeSetTile(x, y, tilenum)
|
||||||
layerWallLowBits.setData(x, y, tilenum % PairedMapLayer.RANGE)
|
|
||||||
wallDamages.remove(LandUtil.getBlockAddr(this, x, y))
|
wallDamages.remove(LandUtil.getBlockAddr(this, x, y))
|
||||||
|
|
||||||
if (oldWall != null)
|
|
||||||
Terrarum.ingame?.queueWallChangedEvent(oldWall, tilenum, LandUtil.getBlockAddr(this, x, y))
|
Terrarum.ingame?.queueWallChangedEvent(oldWall, tilenum, LandUtil.getBlockAddr(this, x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,8 +213,7 @@ open class GameWorld {
|
|||||||
val (x, y) = coerceXY(x, y)
|
val (x, y) = coerceXY(x, y)
|
||||||
|
|
||||||
val oldTerrain = getTileFromTerrain(x, y)
|
val oldTerrain = getTileFromTerrain(x, y)
|
||||||
layerTerrain.setTile(x, y, (tilenum / PairedMapLayer.RANGE).toByte())
|
layerTerrain.unsafeSetTile(x, y, tilenum)
|
||||||
layerTerrainLowBits.setData(x, y, tilenum % PairedMapLayer.RANGE)
|
|
||||||
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
||||||
terrainDamages.remove(blockAddr)
|
terrainDamages.remove(blockAddr)
|
||||||
|
|
||||||
@@ -267,7 +223,6 @@ open class GameWorld {
|
|||||||
}
|
}
|
||||||
// fluid tiles-item should be modified so that they will also place fluid onto their respective map
|
// fluid tiles-item should be modified so that they will also place fluid onto their respective map
|
||||||
|
|
||||||
if (oldTerrain != null)
|
|
||||||
Terrarum.ingame?.queueTerrainChangedEvent(oldTerrain, tilenum, LandUtil.getBlockAddr(this, x, y))
|
Terrarum.ingame?.queueTerrainChangedEvent(oldTerrain, tilenum, LandUtil.getBlockAddr(this, x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,16 +461,19 @@ open class GameWorld {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
layerWall.dispose()
|
||||||
|
layerTerrain.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val WALL = 0
|
@Transient const val WALL = 0
|
||||||
@Transient val TERRAIN = 1
|
@Transient const val TERRAIN = 1
|
||||||
@Transient val WIRE = 2
|
@Transient const val WIRE = 2
|
||||||
|
|
||||||
/** 4096 */
|
@Transient const val TILES_SUPPORTED = 4096
|
||||||
@Transient val TILES_SUPPORTED = MapLayer.RANGE * PairedMapLayer.RANGE
|
//@Transient val SIZEOF: Byte = 2
|
||||||
@Transient val SIZEOF: Byte = MapLayer.SIZEOF
|
@Transient const val LAYERS: Byte = 4 // terrain, wall (layerTerrainLowBits + layerWallLowBits), wire
|
||||||
@Transient val LAYERS: Byte = 4 // terrain, wall (layerTerrainLowBits + layerWallLowBits), wire
|
|
||||||
|
|
||||||
fun makeNullWorld() = GameWorld(1, 1, 1, 0, 0, 0)
|
fun makeNullWorld() = GameWorld(1, 1, 1, 0, 0, 0)
|
||||||
}
|
}
|
||||||
@@ -547,5 +505,6 @@ annotation class TEMzPayload(val payloadName: String, val arg: Int) {
|
|||||||
const val INT48_FLOAT_PAIR = 2
|
const val INT48_FLOAT_PAIR = 2
|
||||||
const val INT48_SHORT_PAIR = 3
|
const val INT48_SHORT_PAIR = 3
|
||||||
const val INT48_INT_PAIR = 4
|
const val INT48_INT_PAIR = 4
|
||||||
|
const val TWELVE_BITS_LITTLE = 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by minjaesong on 2016-01-17.
|
|
||||||
*/
|
|
||||||
open class MapLayer : Iterable<Byte> {
|
|
||||||
|
|
||||||
val width: Int; val height: Int
|
|
||||||
internal @Volatile var data: ByteArray // in parallel programming: do not trust your register; always read freshly from RAM!
|
|
||||||
|
|
||||||
constructor(width: Int, height: Int) {
|
|
||||||
this.width = width
|
|
||||||
this.height = height
|
|
||||||
data = ByteArray(width * height)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(width: Int, height: Int, data: ByteArray) {
|
|
||||||
this.data = data
|
|
||||||
this.width = width
|
|
||||||
this.height = height
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator over elements of type `T`.
|
|
||||||
|
|
||||||
* @return an Iterator.
|
|
||||||
*/
|
|
||||||
override fun iterator(): Iterator<Byte> {
|
|
||||||
return object : Iterator<Byte> {
|
|
||||||
|
|
||||||
private var iteratorCount = 0
|
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
return iteratorCount < width * height
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun next(): Byte {
|
|
||||||
val y = iteratorCount / width
|
|
||||||
val x = iteratorCount % width
|
|
||||||
// advance counter
|
|
||||||
iteratorCount += 1
|
|
||||||
|
|
||||||
return data[y * width + x]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun getTile(x: Int, y: Int): Int? {
|
|
||||||
return if (x !in 0..width - 1 || y !in 0..height - 1)
|
|
||||||
null
|
|
||||||
else
|
|
||||||
data[y * width + x].toUint()
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun setTile(x: Int, y: Int, tile: Byte) {
|
|
||||||
data[y * width + x] = tile
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Transient const val RANGE = 256
|
|
||||||
@Transient const val SIZEOF: Byte = 1 // 1 for 8-bit, 2 for 16-bit, ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this)
|
|
||||||
@@ -3,7 +3,7 @@ package net.torvald.terrarum.gameworld
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2016-02-15.
|
* Created by minjaesong on 2016-02-15.
|
||||||
*/
|
*/
|
||||||
open class PairedMapLayer : Iterable<Byte> {
|
/*open class PairedMapLayer : Iterable<Byte> {
|
||||||
|
|
||||||
val width: Int; val height: Int
|
val width: Int; val height: Int
|
||||||
|
|
||||||
@@ -87,4 +87,4 @@ open class PairedMapLayer : Iterable<Byte> {
|
|||||||
@Transient const val RANGE = 16
|
@Transient const val RANGE = 16
|
||||||
@Transient const val SIZEOF: Byte = 1 // 1 for 8-bit, 2 for 16-bit, ...
|
@Transient const val SIZEOF: Byte = 1 // 1 for 8-bit, 2 for 16-bit, ...
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
@@ -1010,6 +1010,8 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
it.handler.dispose()
|
it.handler.dispose()
|
||||||
it.dispose()
|
it.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
package net.torvald.terrarum.modulebasegame.worldgenerator
|
||||||
|
|
||||||
import net.torvald.random.HQRNG
|
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import com.sudoplay.joise.Joise
|
import com.sudoplay.joise.Joise
|
||||||
import com.sudoplay.joise.module.*
|
import com.sudoplay.joise.module.*
|
||||||
|
import net.torvald.random.HQRNG
|
||||||
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
import net.torvald.terrarum.LoadScreen
|
import net.torvald.terrarum.LoadScreen
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
import net.torvald.terrarum.concurrent.ThreadParallel
|
import net.torvald.terrarum.concurrent.ThreadParallel
|
||||||
import net.torvald.terrarum.modulebasegame.RNGConsumer
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.roundInt
|
import net.torvald.terrarum.roundInt
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ object WorldGenerator {
|
|||||||
*/
|
*/
|
||||||
fun generateMap() {
|
fun generateMap() {
|
||||||
random = HQRNG(SEED)
|
random = HQRNG(SEED)
|
||||||
println("[mapgenerator] Seed: " + SEED)
|
printdbg(this, "Seed: " + SEED)
|
||||||
|
|
||||||
worldOceanPosition = if (random.nextBoolean()) TYPE_OCEAN_LEFT else TYPE_OCEAN_RIGHT
|
worldOceanPosition = if (random.nextBoolean()) TYPE_OCEAN_LEFT else TYPE_OCEAN_RIGHT
|
||||||
|
|
||||||
@@ -491,7 +491,7 @@ object WorldGenerator {
|
|||||||
val joise = Joise(ground_select)
|
val joise = Joise(ground_select)
|
||||||
|
|
||||||
// fill the area as Joise map
|
// fill the area as Joise map
|
||||||
println("[mapgenerator] Raising and eroding terrain...")
|
printdbg(this, "Raising and eroding terrain...")
|
||||||
LoadScreen.addMessage("Raising and eroding terrain...")
|
LoadScreen.addMessage("Raising and eroding terrain...")
|
||||||
for (y in 0..(TERRAIN_UNDULATION - 1)) {
|
for (y in 0..(TERRAIN_UNDULATION - 1)) {
|
||||||
for (x in 0..WIDTH) {
|
for (x in 0..WIDTH) {
|
||||||
@@ -549,7 +549,7 @@ object WorldGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun placeGlacierMount(heightMap: IntArray) {
|
private fun placeGlacierMount(heightMap: IntArray) {
|
||||||
println("[mapgenerator] Putting glacier...")
|
printdbg(this, "Putting glacier...")
|
||||||
|
|
||||||
// raise
|
// raise
|
||||||
for (i in heightMap.indices) {
|
for (i in heightMap.indices) {
|
||||||
@@ -579,7 +579,7 @@ object WorldGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun heightMapToObjectMap(fs: IntArray) {
|
private fun heightMapToObjectMap(fs: IntArray) {
|
||||||
println("[mapgenerator] Shaping world as processed...")
|
printdbg(this, "Shaping world as processed...")
|
||||||
|
|
||||||
// iterate for heightmap
|
// iterate for heightmap
|
||||||
for (x in 0..WIDTH - 1) {
|
for (x in 0..WIDTH - 1) {
|
||||||
@@ -602,7 +602,7 @@ object WorldGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun fillMapByNoiseMap() {
|
private fun fillMapByNoiseMap() {
|
||||||
println("[mapgenerator] Shaping world...")
|
printdbg(this, "Shaping world...")
|
||||||
LoadScreen.addMessage("Reticulating splines...") // RETICULATING SPLINES
|
LoadScreen.addMessage("Reticulating splines...") // RETICULATING SPLINES
|
||||||
// generate dirt-stone transition line
|
// generate dirt-stone transition line
|
||||||
// use catmull spline
|
// use catmull spline
|
||||||
@@ -686,7 +686,7 @@ object WorldGenerator {
|
|||||||
filter: NoiseFilter = NoiseFilterQuadratic,
|
filter: NoiseFilter = NoiseFilterQuadratic,
|
||||||
filterStart: Double = NOISE_GRAD_START,
|
filterStart: Double = NOISE_GRAD_START,
|
||||||
filterEnd: Double = NOISE_GRAD_END) {
|
filterEnd: Double = NOISE_GRAD_END) {
|
||||||
println("[mapgenerator] " + message)
|
printdbg(this, "" + message)
|
||||||
|
|
||||||
for (y in 0..HEIGHT - 1) {
|
for (y in 0..HEIGHT - 1) {
|
||||||
for (x in 0..WIDTH - 1) {
|
for (x in 0..WIDTH - 1) {
|
||||||
@@ -716,7 +716,7 @@ object WorldGenerator {
|
|||||||
filter: NoiseFilter = NoiseFilterQuadratic,
|
filter: NoiseFilter = NoiseFilterQuadratic,
|
||||||
filterStart: Double = NOISE_GRAD_START,
|
filterStart: Double = NOISE_GRAD_START,
|
||||||
filterEnd: Double = NOISE_GRAD_END) {
|
filterEnd: Double = NOISE_GRAD_END) {
|
||||||
println("[mapgenerator] " + message)
|
printdbg(this, "" + message)
|
||||||
|
|
||||||
for (y in 0..HEIGHT - 1) {
|
for (y in 0..HEIGHT - 1) {
|
||||||
for (x in 0..WIDTH - 1) {
|
for (x in 0..WIDTH - 1) {
|
||||||
@@ -747,7 +747,7 @@ object WorldGenerator {
|
|||||||
filter: NoiseFilter = NoiseFilterQuadratic,
|
filter: NoiseFilter = NoiseFilterQuadratic,
|
||||||
filterStart: Double = NOISE_GRAD_START,
|
filterStart: Double = NOISE_GRAD_START,
|
||||||
filterEnd: Double = NOISE_GRAD_END) {
|
filterEnd: Double = NOISE_GRAD_END) {
|
||||||
println("[mapgenerator] " + message)
|
printdbg(this, "" + message)
|
||||||
|
|
||||||
for (y in 0..HEIGHT - 1) {
|
for (y in 0..HEIGHT - 1) {
|
||||||
for (x in 0..WIDTH - 1) {
|
for (x in 0..WIDTH - 1) {
|
||||||
@@ -797,7 +797,7 @@ object WorldGenerator {
|
|||||||
private val islandSpacing = 1024
|
private val islandSpacing = 1024
|
||||||
|
|
||||||
private fun generateFloatingIslands() {
|
private fun generateFloatingIslands() {
|
||||||
println("[mapgenerator] Placing floating islands...")
|
printdbg(this, "Placing floating islands...")
|
||||||
LoadScreen.addMessage("Placing floating islands...")
|
LoadScreen.addMessage("Placing floating islands...")
|
||||||
|
|
||||||
val nIslandsMax = Math.round(world.width * 6f / 8192f)
|
val nIslandsMax = Math.round(world.width * 6f / 8192f)
|
||||||
@@ -830,7 +830,7 @@ object WorldGenerator {
|
|||||||
/* Flood */
|
/* Flood */
|
||||||
|
|
||||||
private fun floodBottomLava() {
|
private fun floodBottomLava() {
|
||||||
/*println("[mapgenerator] Flooding with lava...")
|
/*printdbg(this, "Flooding with lava...")
|
||||||
LoadScreen.addMessage("Flooding with lava...")
|
LoadScreen.addMessage("Flooding with lava...")
|
||||||
for (i in HEIGHT * 14 / 15..HEIGHT - 1) {
|
for (i in HEIGHT * 14 / 15..HEIGHT - 1) {
|
||||||
for (j in 0..WIDTH - 1) {
|
for (j in 0..WIDTH - 1) {
|
||||||
@@ -844,7 +844,7 @@ object WorldGenerator {
|
|||||||
/* Plant */
|
/* Plant */
|
||||||
|
|
||||||
private fun plantGrass() {
|
private fun plantGrass() {
|
||||||
println("[mapgenerator] Planting grass...")
|
printdbg(this, "Planting grass...")
|
||||||
LoadScreen.addMessage("Planting grass...")
|
LoadScreen.addMessage("Planting grass...")
|
||||||
|
|
||||||
/* TODO composing dirt and stone
|
/* TODO composing dirt and stone
|
||||||
@@ -910,7 +910,7 @@ object WorldGenerator {
|
|||||||
"yellow"
|
"yellow"
|
||||||
else
|
else
|
||||||
"white"
|
"white"
|
||||||
println("[mapgenerator] Beach sand type: $thisSandStr")
|
printdbg(this, "Beach sand type: $thisSandStr")
|
||||||
|
|
||||||
var ix = 0
|
var ix = 0
|
||||||
while (ix < OCEAN_WIDTH * 1.5) {
|
while (ix < OCEAN_WIDTH * 1.5) {
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
package net.torvald.terrarum.serialise
|
package net.torvald.terrarum.serialise
|
||||||
|
|
||||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
|
||||||
import java.io.IOException
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only being used by the title screen and the demoworld. This object may get deleted at any update
|
* Only being used by the title screen and the demoworld. This object may get deleted at any update
|
||||||
*
|
*
|
||||||
@@ -14,8 +9,11 @@ import java.util.*
|
|||||||
@Deprecated("TEMD is deprecated format; use TEMz which does compression")
|
@Deprecated("TEMD is deprecated format; use TEMz which does compression")
|
||||||
internal object ReadLayerData {
|
internal object ReadLayerData {
|
||||||
|
|
||||||
|
init {
|
||||||
|
throw Error("TEMD is old and removed format; use TEMz which does compression")
|
||||||
|
}
|
||||||
|
|
||||||
internal operator fun invoke(inputStream: InputStream, inWorld: GameWorldExtension? = null): GameWorldExtension {
|
/*internal operator fun invoke(inputStream: InputStream, inWorld: GameWorldExtension? = null): GameWorldExtension {
|
||||||
val magicBytes = ByteArray(4)
|
val magicBytes = ByteArray(4)
|
||||||
val layerSizeBytes = ByteArray(1)
|
val layerSizeBytes = ByteArray(1)
|
||||||
val layerCountBytes = ByteArray(1)
|
val layerCountBytes = ByteArray(1)
|
||||||
@@ -109,7 +107,7 @@ internal object ReadLayerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return i
|
return i
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Int.toLittle() = byteArrayOf(
|
fun Int.toLittle() = byteArrayOf(
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ package net.torvald.terrarum.serialise
|
|||||||
import com.badlogic.gdx.utils.compression.Lzma
|
import com.badlogic.gdx.utils.compression.Lzma
|
||||||
import net.torvald.terrarum.AppLoader.printdbg
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
|
import net.torvald.terrarum.gameworld.BlockLayer
|
||||||
import net.torvald.terrarum.gameworld.FluidType
|
import net.torvald.terrarum.gameworld.FluidType
|
||||||
import net.torvald.terrarum.gameworld.MapLayer
|
|
||||||
import net.torvald.terrarum.gameworld.PairedMapLayer
|
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import java.io.*
|
import java.io.*
|
||||||
@@ -143,15 +142,8 @@ internal object ReadLayerDataLzma {
|
|||||||
|
|
||||||
val inflatedFile = inflatedOS.toByteArray()
|
val inflatedFile = inflatedOS.toByteArray()
|
||||||
|
|
||||||
// deal with (MSB ++ LSB)
|
|
||||||
if (t == "TERR" || t == "WALL") {
|
|
||||||
payloadBytes["${t}_MSB"] = inflatedFile.sliceArray(0 until worldSize.toInt()) // FIXME deflated stream cannot be larger than 2 GB
|
|
||||||
payloadBytes["${t}_LSB"] = inflatedFile.sliceArray(worldSize.toInt() until u.uncompressedSize.toInt()) // FIXME deflated stream cannot be larger than 2 GB
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
payloadBytes[t] = inflatedFile
|
payloadBytes[t] = inflatedFile
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val spawnPoint = LandUtil.resolveBlockAddr(width, spawnAddress)
|
val spawnPoint = LandUtil.resolveBlockAddr(width, spawnAddress)
|
||||||
|
|
||||||
@@ -186,11 +178,8 @@ internal object ReadLayerDataLzma {
|
|||||||
|
|
||||||
|
|
||||||
return ReadLayerDataZip.LayerData(
|
return ReadLayerDataZip.LayerData(
|
||||||
MapLayer(width, height, payloadBytes["WALL_MSB"]!!),
|
BlockLayer(width, height, payloadBytes["WALL"]!!),
|
||||||
MapLayer(width, height, payloadBytes["TERR_MSB"]!!),
|
BlockLayer(width, height, payloadBytes["TERR"]!!),
|
||||||
MapLayer(width, height, payloadBytes["WIRE"]!!),
|
|
||||||
PairedMapLayer(width, height, payloadBytes["WALL_LSB"]!!),
|
|
||||||
PairedMapLayer(width, height, payloadBytes["TERR_LSB"]!!),
|
|
||||||
|
|
||||||
spawnPoint.first, spawnPoint.second,
|
spawnPoint.first, spawnPoint.second,
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ package net.torvald.terrarum.serialise
|
|||||||
|
|
||||||
import net.torvald.terrarum.AppLoader.printdbg
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
|
import net.torvald.terrarum.gameworld.BlockLayer
|
||||||
import net.torvald.terrarum.gameworld.FluidType
|
import net.torvald.terrarum.gameworld.FluidType
|
||||||
import net.torvald.terrarum.gameworld.MapLayer
|
|
||||||
import net.torvald.terrarum.gameworld.PairedMapLayer
|
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -144,15 +143,8 @@ internal object ReadLayerDataZip {
|
|||||||
if (uncompLen.toLong() != u.uncompressedSize)
|
if (uncompLen.toLong() != u.uncompressedSize)
|
||||||
throw InternalError("Payload $t DEFLATE size mismatch -- expected ${u.uncompressedSize}, got $uncompLen")
|
throw InternalError("Payload $t DEFLATE size mismatch -- expected ${u.uncompressedSize}, got $uncompLen")
|
||||||
|
|
||||||
// deal with (MSB ++ LSB)
|
|
||||||
if (t == "TERR" || t == "WALL") {
|
|
||||||
payloadBytes["${t}_MSB"] = inflatedFile.sliceArray(0 until worldSize.toInt()) // FIXME deflated stream cannot be larger than 2 GB
|
|
||||||
payloadBytes["${t}_LSB"] = inflatedFile.sliceArray(worldSize.toInt() until uncompLen) // FIXME deflated stream cannot be larger than 2 GB
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
payloadBytes[t] = inflatedFile
|
payloadBytes[t] = inflatedFile
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val spawnPoint = LandUtil.resolveBlockAddr(width, spawnAddress)
|
val spawnPoint = LandUtil.resolveBlockAddr(width, spawnAddress)
|
||||||
|
|
||||||
@@ -187,11 +179,8 @@ internal object ReadLayerDataZip {
|
|||||||
|
|
||||||
|
|
||||||
return LayerData(
|
return LayerData(
|
||||||
MapLayer(width, height, payloadBytes["WALL_MSB"]!!),
|
BlockLayer(width, height, payloadBytes["WALL"]!!),
|
||||||
MapLayer(width, height, payloadBytes["TERR_MSB"]!!),
|
BlockLayer(width, height, payloadBytes["TERR"]!!),
|
||||||
MapLayer(width, height, payloadBytes["WIRE"]!!),
|
|
||||||
PairedMapLayer(width, height, payloadBytes["WALL_LSB"]!!),
|
|
||||||
PairedMapLayer(width, height, payloadBytes["TERR_LSB"]!!),
|
|
||||||
|
|
||||||
spawnPoint.first, spawnPoint.second,
|
spawnPoint.first, spawnPoint.second,
|
||||||
|
|
||||||
@@ -203,16 +192,15 @@ internal object ReadLayerDataZip {
|
|||||||
* Immediately deployable, a part of the gameworld
|
* Immediately deployable, a part of the gameworld
|
||||||
*/
|
*/
|
||||||
internal data class LayerData(
|
internal data class LayerData(
|
||||||
val layerWall: MapLayer,
|
val layerWall: BlockLayer,
|
||||||
val layerTerrain: MapLayer,
|
val layerTerrain: BlockLayer,
|
||||||
val layerWire: MapLayer,
|
|
||||||
val layerWallLowBits: PairedMapLayer,
|
|
||||||
val layerTerrainLowBits: PairedMapLayer,
|
|
||||||
//val layerThermal: MapLayerHalfFloat, // in Kelvins
|
//val layerThermal: MapLayerHalfFloat, // in Kelvins
|
||||||
//val layerAirPressure: MapLayerHalfFloat, // (milibar - 1000)
|
//val layerAirPressure: MapLayerHalfFloat, // (milibar - 1000)
|
||||||
|
|
||||||
val spawnX: Int,
|
val spawnX: Int,
|
||||||
val spawnY: Int,
|
val spawnY: Int,
|
||||||
|
|
||||||
|
//val wirings: HashMap<BlockAddress, SortedArrayList<GameWorld.WiringNode>>,
|
||||||
val wallDamages: HashMap<BlockAddress, Float>,
|
val wallDamages: HashMap<BlockAddress, Float>,
|
||||||
val terrainDamages: HashMap<BlockAddress, Float>,
|
val terrainDamages: HashMap<BlockAddress, Float>,
|
||||||
val fluidTypes: HashMap<BlockAddress, FluidType>,
|
val fluidTypes: HashMap<BlockAddress, FluidType>,
|
||||||
|
|||||||
@@ -1,27 +1,21 @@
|
|||||||
package net.torvald.terrarum.serialise
|
package net.torvald.terrarum.serialise
|
||||||
|
|
||||||
import net.torvald.terrarum.AppLoader
|
|
||||||
import net.torvald.terrarum.Terrarum
|
|
||||||
import net.torvald.terrarum.console.EchoError
|
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.IOException
|
|
||||||
import java.nio.charset.Charset
|
|
||||||
import java.util.zip.GZIPOutputStream
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO this one does not use TerranVirtualDisk
|
* TODO this one does not use TerranVirtualDisk
|
||||||
*
|
*
|
||||||
* Created by minjaesong on 2016-03-18.
|
* Created by minjaesong on 2016-03-18.
|
||||||
*/
|
*/
|
||||||
// internal for everything: prevent malicious module from messing up the savedata
|
// internal for everything: prevent malicious module from messing up the savedata
|
||||||
@Deprecated("TEMD is deprecated format; use TEMz which does compression")
|
@Deprecated("TEMD is old and removed format; use TEMz which does compression")
|
||||||
internal object WriteLayerData {
|
internal object WriteLayerData {
|
||||||
|
|
||||||
|
init {
|
||||||
|
throw Error("TEMD is old and removed format; use TEMz which does compression")
|
||||||
|
}
|
||||||
|
|
||||||
val LAYERS_FILENAME = "worldinfo1"
|
val LAYERS_FILENAME = "worldinfo1"
|
||||||
|
|
||||||
val MAGIC = "TEMD".toByteArray(charset = Charset.forName("US-ASCII"))
|
/*val MAGIC = "TEMD".toByteArray(charset = Charset.forName("US-ASCII"))
|
||||||
|
|
||||||
val BYTE_NULL: Byte = 0
|
val BYTE_NULL: Byte = 0
|
||||||
|
|
||||||
@@ -83,7 +77,7 @@ internal object WriteLayerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,15 +101,23 @@ internal object WriteLayerDataLzma {
|
|||||||
|
|
||||||
wb(PAYLOAD_HEADER); wb("TERR".toByteArray())
|
wb(PAYLOAD_HEADER); wb("TERR".toByteArray())
|
||||||
wi48(world.width * world.height * 3L / 2)
|
wi48(world.width * world.height * 3L / 2)
|
||||||
Lzma.compress(ByteArrayInputStream(world.terrainArray), outputStream)
|
world.layerTerrain.bytesIterator().forEach {
|
||||||
Lzma.compress(ByteArrayInputStream(world.layerTerrainLowBits.data), outputStream)
|
val tempByteArray = ByteArray(1)
|
||||||
|
tempByteArray[0] = it
|
||||||
|
val tempByteArrayStream = ByteArrayInputStream(tempByteArray)
|
||||||
|
Lzma.compress(tempByteArrayStream, outputStream)
|
||||||
|
}
|
||||||
wb(PAYLOAD_FOOTER)
|
wb(PAYLOAD_FOOTER)
|
||||||
|
|
||||||
// WALL payload
|
// WALL payload
|
||||||
wb(PAYLOAD_HEADER); wb("WALL".toByteArray())
|
wb(PAYLOAD_HEADER); wb("WALL".toByteArray())
|
||||||
wi48(world.width * world.height * 3L / 2)
|
wi48(world.width * world.height * 3L / 2)
|
||||||
Lzma.compress(ByteArrayInputStream(world.wallArray), outputStream)
|
world.layerWall.bytesIterator().forEach {
|
||||||
Lzma.compress(ByteArrayInputStream(world.layerWallLowBits.data), outputStream)
|
val tempByteArray = ByteArray(1)
|
||||||
|
tempByteArray[0] = it
|
||||||
|
val tempByteArrayStream = ByteArrayInputStream(tempByteArray)
|
||||||
|
Lzma.compress(tempByteArrayStream, outputStream)
|
||||||
|
}
|
||||||
wb(PAYLOAD_FOOTER)
|
wb(PAYLOAD_FOOTER)
|
||||||
|
|
||||||
// WIRE payload
|
// WIRE payload
|
||||||
|
|||||||
@@ -113,8 +113,7 @@ internal object WriteLayerDataZip {
|
|||||||
wb(PAYLOAD_HEADER); wb("TERR".toByteArray())
|
wb(PAYLOAD_HEADER); wb("TERR".toByteArray())
|
||||||
wi48(world.width * world.height * 3L / 2)
|
wi48(world.width * world.height * 3L / 2)
|
||||||
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false)
|
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false)
|
||||||
deflater.write(world.terrainArray)
|
world.layerTerrain.bytesIterator().forEach { deflater.write(it.toInt()) }
|
||||||
deflater.write(world.layerTerrainLowBits.data)
|
|
||||||
deflater.flush(); deflater.finish()
|
deflater.flush(); deflater.finish()
|
||||||
wb(PAYLOAD_FOOTER)
|
wb(PAYLOAD_FOOTER)
|
||||||
|
|
||||||
@@ -122,8 +121,7 @@ internal object WriteLayerDataZip {
|
|||||||
wb(PAYLOAD_HEADER); wb("WALL".toByteArray())
|
wb(PAYLOAD_HEADER); wb("WALL".toByteArray())
|
||||||
wi48(world.width * world.height * 3L / 2)
|
wi48(world.width * world.height * 3L / 2)
|
||||||
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false)
|
deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false)
|
||||||
deflater.write(world.wallArray)
|
world.layerWall.bytesIterator().forEach { deflater.write(it.toInt()) }
|
||||||
deflater.write(world.layerWallLowBits.data)
|
|
||||||
deflater.flush(); deflater.finish()
|
deflater.flush(); deflater.finish()
|
||||||
wb(PAYLOAD_FOOTER)
|
wb(PAYLOAD_FOOTER)
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,11 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.graphics.*
|
import com.badlogic.gdx.graphics.*
|
||||||
import com.badlogic.gdx.math.Matrix4
|
import com.badlogic.gdx.math.Matrix4
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import com.badlogic.gdx.graphics.Color
|
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.AppLoader.printdbg
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.PairedMapLayer
|
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator
|
import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator
|
||||||
@@ -59,7 +57,6 @@ internal object BlocksDrawer {
|
|||||||
val wallOverlayColour = Color(5f / 9f, 5f / 9f, 5f / 9f, 1f)
|
val wallOverlayColour = Color(5f / 9f, 5f / 9f, 5f / 9f, 1f)
|
||||||
|
|
||||||
const val BREAKAGE_STEPS = 10
|
const val BREAKAGE_STEPS = 10
|
||||||
const val TILES_PER_BLOCK = PairedMapLayer.RANGE
|
|
||||||
|
|
||||||
val WALL = GameWorld.WALL
|
val WALL = GameWorld.WALL
|
||||||
val TERRAIN = GameWorld.TERRAIN
|
val TERRAIN = GameWorld.TERRAIN
|
||||||
@@ -257,7 +254,7 @@ internal object BlocksDrawer {
|
|||||||
val fluidNum = this.type.abs()
|
val fluidNum = this.type.abs()
|
||||||
|
|
||||||
if (this.amount >= WorldSimulator.FLUID_MIN_MASS) {
|
if (this.amount >= WorldSimulator.FLUID_MIN_MASS) {
|
||||||
val fluidLevel = this.amount.coerceIn(0f,1f).times(PairedMapLayer.RANGE - 1).roundToInt()
|
val fluidLevel = this.amount.coerceIn(0f,1f).times(15).roundToInt()
|
||||||
|
|
||||||
return fluidLevel * 16 + fluidNum
|
return fluidLevel * 16 + fluidNum
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,14 +50,11 @@ Ord Hex Description
|
|||||||
# "EndPYLd\xFF" Payload footer [45, 6E, 64, 50, 59, 4C, 64, FF]
|
# "EndPYLd\xFF" Payload footer [45, 6E, 64, 50, 59, 4C, 64, FF]
|
||||||
|
|
||||||
|
|
||||||
Payload "TERR" -- world terrain data, concatenation of MSB and LSB arrays. In Haskell style: Deflate(MSB ++ LSB)
|
Payload "TERR" -- world terrain data in Uint16
|
||||||
Uncompressed size will be 1.5x of (width * height)
|
Uncompressed size will be 2x of (width * height)
|
||||||
|
|
||||||
Payload "WALL" -- world walls data, concatenation of MSB and LSB arrays. In Haskell style: Deflate(MSB ++ LSB)
|
Payload "WALL" -- world walls data in Unit16
|
||||||
Uncompressed size will be 1.5x of (width * height)
|
Uncompressed size will be 2x of (width * height)
|
||||||
|
|
||||||
Payload "WIRE" -- world wires data
|
|
||||||
Uncompressed size will be as same as (width * height)
|
|
||||||
|
|
||||||
Payload "TdMG" -- world terrain damage data, array of: (Int48 tileAddress, Float32 damage)
|
Payload "TdMG" -- world terrain damage data, array of: (Int48 tileAddress, Float32 damage)
|
||||||
Uncompressed size will be arbitrary (multiple of tens)
|
Uncompressed size will be arbitrary (multiple of tens)
|
||||||
@@ -71,8 +68,12 @@ Payload "FlTP" -- world fluid types, array of: (Int48 tileAddress, Signed Int16
|
|||||||
Payload "FlFL" -- world fluid fills, array of: (Int48 tileAddress, Float32 amount)
|
Payload "FlFL" -- world fluid fills, array of: (Int48 tileAddress, Float32 amount)
|
||||||
Uncompressed size will be arbitrary (multiple of tens)
|
Uncompressed size will be arbitrary (multiple of tens)
|
||||||
If the 'amount' < 0.0001f (WorldSimulator.FLUID_MIN_MASS), the entry must be discarded
|
If the 'amount' < 0.0001f (WorldSimulator.FLUID_MIN_MASS), the entry must be discarded
|
||||||
|
|
||||||
|
Payload "WiNt" -- wiring nodes, in JSON format
|
||||||
|
|
||||||
Payload "CtYP" -- conduit types, array of: (Int48 tileAddress, Uint32 bitarray)
|
Payload "CtYP" -- conduit types, array of: (Int48 tileAddress, Uint32 bitarray)
|
||||||
can hold 32 different wires simultaneously
|
can hold 32 different wires simultaneously
|
||||||
|
|
||||||
Payload "CfL0" -- conduit fills, aka size of liquid/gas packet, array of: (Int48 tileAddress, Float32 fill)
|
Payload "CfL0" -- conduit fills, aka size of liquid/gas packet, array of: (Int48 tileAddress, Float32 fill)
|
||||||
CfL0..CfL9, CfLa..CfLf are available to store values for 16 different things.
|
CfL0..CfL9, CfLa..CfLf are available to store values for 16 different things.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user