mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 16:44:05 +09:00
Compare commits
5 Commits
world-chun
...
v0.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d460447331 | ||
|
|
63fe28eee2 | ||
|
|
2d7ef6e9ff | ||
|
|
fa3a129991 | ||
|
|
4cc74a85d1 |
@@ -132,8 +132,8 @@ id;classname;tags
|
|||||||
320;net.torvald.terrarum.modulebasegame.gameitems.ItemWorldPortal;FIXTURE,STATION
|
320;net.torvald.terrarum.modulebasegame.gameitems.ItemWorldPortal;FIXTURE,STATION
|
||||||
|
|
||||||
# industrial
|
# industrial
|
||||||
2048;net.torvald.terrarum.modulebasegame.gameitems.ItemInductionMotor;FIXTURE,POWER,KINETIC
|
#2048;net.torvald.terrarum.modulebasegame.gameitems.ItemInductionMotor;FIXTURE,POWER,KINETIC
|
||||||
2049;net.torvald.terrarum.modulebasegame.gameitems.ItemGearbox;FIXTURE,POWER,KINETIC
|
#2049;net.torvald.terrarum.modulebasegame.gameitems.ItemGearbox;FIXTURE,POWER,KINETIC
|
||||||
|
|
||||||
# data storage (discs; 256)
|
# data storage (discs; 256)
|
||||||
# 32768 is a reserved number for a blank disc
|
# 32768 is a reserved number for a blank disc
|
||||||
@@ -179,5 +179,5 @@ id;classname;tags
|
|||||||
1048835;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron03;FLUIDSTORAGE,OPENSTORAGE
|
1048835;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron03;FLUIDSTORAGE,OPENSTORAGE
|
||||||
|
|
||||||
# reserved for debug items
|
# reserved for debug items
|
||||||
16777216;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessWaterBucket;DEBUG,TOOL
|
#16777216;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessWaterBucket;DEBUG,TOOL
|
||||||
16777217;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessLavaBucket;DEBUG,TOOL
|
#16777217;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessLavaBucket;DEBUG,TOOL
|
||||||
|
|||||||
|
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ITEM_ALLOYING_FURNACE": "Alloying Furnace",
|
"ITEM_ALLOYING_FURNACE": "Alloying Furnace",
|
||||||
|
"ITEM_AXLE": "Axle",
|
||||||
"ITEM_BRICK_SINGULAR": "Brick", /* always singular */
|
"ITEM_BRICK_SINGULAR": "Brick", /* always singular */
|
||||||
"ITEM_BUCKET_IRON": "Iron Bucket %1$s",
|
"ITEM_BUCKET_IRON": "Iron Bucket %1$s",
|
||||||
"ITEM_BUCKET_WOODEN": "Wooden Bucket %1$s",
|
"ITEM_BUCKET_WOODEN": "Wooden Bucket %1$s",
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
"ITEM_ELECTRIC_WORKBENCH": "Electric Workbench",
|
"ITEM_ELECTRIC_WORKBENCH": "Electric Workbench",
|
||||||
"ITEM_ENGRAVING_WORKBENCH": "Engraving Workbench",
|
"ITEM_ENGRAVING_WORKBENCH": "Engraving Workbench",
|
||||||
"ITEM_FURNACE_AND_ANVIL": "Furnace and Anvil",
|
"ITEM_FURNACE_AND_ANVIL": "Furnace and Anvil",
|
||||||
|
"ITEM_GEARBOX": "Gearbox",
|
||||||
"ITEM_GEM_RUBY": "Raw Ruby",
|
"ITEM_GEM_RUBY": "Raw Ruby",
|
||||||
"ITEM_GEM_EMERALD": "Raw Emerald",
|
"ITEM_GEM_EMERALD": "Raw Emerald",
|
||||||
"ITEM_GEM_SAPPHIRE": "Raw Sapphire",
|
"ITEM_GEM_SAPPHIRE": "Raw Sapphire",
|
||||||
@@ -30,6 +32,7 @@
|
|||||||
"ITEM_HATCHET_STEEL": "Steel Axe",
|
"ITEM_HATCHET_STEEL": "Steel Axe",
|
||||||
"ITEM_HATCHET_STONE": "Stone Axe",
|
"ITEM_HATCHET_STONE": "Stone Axe",
|
||||||
"ITEM_HATCHET_WOODEN": "Wooden Axe",
|
"ITEM_HATCHET_WOODEN": "Wooden Axe",
|
||||||
|
"ITEM_INDUCTION_MOTOR": "Induction Motor",
|
||||||
"ITEM_INGOT_BRASS": "Brass Ingot",
|
"ITEM_INGOT_BRASS": "Brass Ingot",
|
||||||
"ITEM_INGOT_BRONZE": "Bronze Ingot",
|
"ITEM_INGOT_BRONZE": "Bronze Ingot",
|
||||||
"ITEM_INGOT_COPPER": "Copper Ingot",
|
"ITEM_INGOT_COPPER": "Copper Ingot",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ id;drop;name;renderclass;accept;inputcount;inputtype;outputtype;javaclass;invent
|
|||||||
2;2;WIRE_POWER_HIGH;power;power_high;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,6,4;1;"POWERWIRE_HIGH"
|
2;2;WIRE_POWER_HIGH;power;power_high;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,6,4;1;"POWERWIRE_HIGH"
|
||||||
16;16;WIRE_ETHERNET;network;10base2;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,7,4;1;"ETHERNETWIRE"
|
16;16;WIRE_ETHERNET;network;10base2;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,7,4;1;"ETHERNETWIRE"
|
||||||
|
|
||||||
256;256;AXLE;axle;axle;1;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceAxle;basegame.items,1,5;0;"AXLE"
|
#256;256;AXLE;axle;axle;1;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceAxle;basegame.items,1,5;0;"AXLE"
|
||||||
|
|
||||||
# accept: which wiretype (defined elsewhere) the wires acceps. Use comma to separate multiple. N/A for electronic components (aka not wires)
|
# accept: which wiretype (defined elsewhere) the wires acceps. Use comma to separate multiple. N/A for electronic components (aka not wires)
|
||||||
# inputcount: how many sides are input (outputcount is deduced from the inputcount). N/A for wires
|
# inputcount: how many sides are input (outputcount is deduced from the inputcount). N/A for wires
|
||||||
|
|||||||
|
@@ -31,7 +31,6 @@ import net.torvald.terrarum.gamecontroller.KeyToggler;
|
|||||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent;
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent;
|
||||||
import net.torvald.terrarum.gameitems.GameItem;
|
import net.torvald.terrarum.gameitems.GameItem;
|
||||||
import net.torvald.terrarum.gameworld.GameWorld;
|
import net.torvald.terrarum.gameworld.GameWorld;
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld;
|
|
||||||
import net.torvald.terrarum.imagefont.BigAlphNum;
|
import net.torvald.terrarum.imagefont.BigAlphNum;
|
||||||
import net.torvald.terrarum.imagefont.TinyAlphNum;
|
import net.torvald.terrarum.imagefont.TinyAlphNum;
|
||||||
import net.torvald.terrarum.langpack.Lang;
|
import net.torvald.terrarum.langpack.Lang;
|
||||||
@@ -1017,7 +1016,7 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
ModMgr.INSTANCE.disposeMods();
|
ModMgr.INSTANCE.disposeMods();
|
||||||
|
|
||||||
TheGameWorld.Companion.makeNullWorld().dispose();
|
GameWorld.Companion.makeNullWorld().dispose();
|
||||||
|
|
||||||
Terrarum.INSTANCE.dispose();
|
Terrarum.INSTANCE.dispose();
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ object CheckUpdate {
|
|||||||
private val checkUpdateURL = setOf(
|
private val checkUpdateURL = setOf(
|
||||||
"https://github.com/curioustorvald/Terrarum/releases/tag/v$versionNumOnly",
|
"https://github.com/curioustorvald/Terrarum/releases/tag/v$versionNumOnly",
|
||||||
"https://github.com/curioustorvald/Terrarum/releases/tag/v$versionNumFull",
|
"https://github.com/curioustorvald/Terrarum/releases/tag/v$versionNumFull",
|
||||||
).toList()
|
).map { it.replace(' ', '_') }
|
||||||
|
|
||||||
private fun wget(url: String): String? {
|
private fun wget(url: String): String? {
|
||||||
printdbg(this, "wget $url")
|
printdbg(this, "wget $url")
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import net.torvald.terrarum.gamecontroller.KeyToggler
|
|||||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.gameworld.TitlescreenGameWorld
|
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
@@ -107,7 +105,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
|||||||
printStackTrace(this)
|
printStackTrace(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
open var world: GameWorld = TheGameWorld.makeNullWorld()
|
open var world: GameWorld = GameWorld.makeNullWorld()
|
||||||
set(value) {
|
set(value) {
|
||||||
val oldWorld = field
|
val oldWorld = field
|
||||||
newWorldLoadedLatch = true
|
newWorldLoadedLatch = true
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ basegame
|
|||||||
* e.g. 0x02010034 will be translated as 2.1.52
|
* e.g. 0x02010034 will be translated as 2.1.52
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const val VERSION_RAW: Long = 0x0000_000004_000004
|
const val VERSION_RAW: Long = 0x0000_000005_000000
|
||||||
// Commit counts up to the Release 0.3.0: 2259
|
// Commit counts up to the Release 0.3.0: 2259
|
||||||
// Commit counts up to the Release 0.3.1: 2278
|
// Commit counts up to the Release 0.3.1: 2278
|
||||||
// Commit counts up to the Release 0.3.2: 2732
|
// Commit counts up to the Release 0.3.2: 2732
|
||||||
@@ -77,6 +77,7 @@ basegame
|
|||||||
// Commit counts up to the Release 0.4.0: 3631
|
// Commit counts up to the Release 0.4.0: 3631
|
||||||
// Commit counts up to the Release 0.4.1: 3678
|
// Commit counts up to the Release 0.4.1: 3678
|
||||||
// Commit counts up to the Release 0.4.2: 3762
|
// Commit counts up to the Release 0.4.2: 3762
|
||||||
|
// Commit counts up to the Release 0.5.0: 4090
|
||||||
|
|
||||||
val DEV_CYCLE: Map<String, Long> = mapOf(
|
val DEV_CYCLE: Map<String, Long> = mapOf(
|
||||||
"Alpha" to 0x0000_000004_000000,
|
"Alpha" to 0x0000_000004_000000,
|
||||||
|
|||||||
@@ -2,17 +2,26 @@ package net.torvald.terrarum.blockstats
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.Pixmap
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
|
import com.badlogic.gdx.graphics.Texture
|
||||||
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
|
import com.badlogic.gdx.utils.Queue
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import net.torvald.terrarum.abs
|
||||||
import net.torvald.terrarum.concurrent.ThreadExecutor
|
import net.torvald.terrarum.concurrent.ThreadExecutor
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_HEIGHT
|
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_HEIGHT
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_WIDTH
|
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_WIDTH
|
||||||
|
import net.torvald.terrarum.sqr
|
||||||
import net.torvald.terrarum.toInt
|
import net.torvald.terrarum.toInt
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.Companion.WALL_OVERLAY_COLOUR
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.Companion.WALL_OVERLAY_COLOUR
|
||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object MinimapComposer : Disposable {
|
object MinimapComposer : Disposable {
|
||||||
|
|
||||||
@@ -23,7 +32,7 @@ object MinimapComposer : Disposable {
|
|||||||
val MINIMAP_TILE_WIDTH = (MINIMAP_WIDTH.toInt() * 3) / SQUARE_SIZE + 4
|
val MINIMAP_TILE_WIDTH = (MINIMAP_WIDTH.toInt() * 3) / SQUARE_SIZE + 4
|
||||||
val MINIMAP_TILE_HEIGHT = (MINIMAP_HEIGHT.toInt() * 3) / SQUARE_SIZE + 4
|
val MINIMAP_TILE_HEIGHT = (MINIMAP_HEIGHT.toInt() * 3) / SQUARE_SIZE + 4
|
||||||
|
|
||||||
private var world: GameWorld = TheGameWorld.makeNullWorld()
|
private var world: GameWorld = GameWorld.makeNullWorld()
|
||||||
|
|
||||||
fun setWorld(world: GameWorld) {
|
fun setWorld(world: GameWorld) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package net.torvald.terrarum.console
|
package net.torvald.terrarum.console
|
||||||
|
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
|
import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,7 +8,7 @@ import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
|
|||||||
*/
|
*/
|
||||||
internal object GetGR : ConsoleCommand {
|
internal object GetGR : ConsoleCommand {
|
||||||
override fun execute(args: Array<String>) {
|
override fun execute(args: Array<String>) {
|
||||||
val gameRules = (INGAME.world as TheGameWorld).gameRules
|
val gameRules = INGAME.world.gameRules
|
||||||
|
|
||||||
// check if args[1] is number or not
|
// check if args[1] is number or not
|
||||||
if (args.size > 1 && !args[1].isNum()) { // args[1] is Gamerule name
|
if (args.size > 1 && !args[1].isNum()) { // args[1] is Gamerule name
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import net.torvald.terrarum.gameitems.ItemID
|
|||||||
import net.torvald.terrarum.gameparticles.createRandomBlockParticle
|
import net.torvald.terrarum.gameparticles.createRandomBlockParticle
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.itemproperties.Calculate
|
import net.torvald.terrarum.itemproperties.Calculate
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
|
|||||||
@@ -5,48 +5,17 @@ import com.badlogic.gdx.utils.Disposable
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-10-10.
|
* Created by minjaesong on 2023-10-10.
|
||||||
*/
|
*/
|
||||||
open class BlockLayer() : Disposable {
|
interface BlockLayer : Disposable {
|
||||||
// abstract val chunkPool: ChunkPool
|
|
||||||
open val width: Int = 0
|
|
||||||
open val height: Int = 0
|
|
||||||
open val bytesPerBlock: Long = 0
|
|
||||||
open fun unsafeToBytes(x: Int, y: Int): ByteArray = byteArrayOf(0,0,0,0)
|
|
||||||
open fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) { }
|
|
||||||
// for I16; other layer must throw UnsupportedOperationException
|
|
||||||
open fun unsafeSetTile(x: Int, y: Int, tile: Int) { }
|
|
||||||
// for I16F16; other layer must throw UnsupportedOperationException
|
|
||||||
open fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) { }
|
|
||||||
// for I16I8; other layer must throw UnsupportedOperationException
|
|
||||||
open fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) { }
|
|
||||||
|
|
||||||
open fun unsafeGetTile(x: Int, y: Int): Int = 0
|
val width: Int
|
||||||
|
val height: Int
|
||||||
open fun getOffset(x: Int, y: Int): Long {
|
val bytesPerBlock: Long
|
||||||
return this.bytesPerBlock * (y * this.width + x)
|
fun unsafeToBytes(x: Int, y: Int): ByteArray
|
||||||
}
|
fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray)
|
||||||
|
fun unsafeGetTile(x: Int, y: Int): Int
|
||||||
open val disposed: Boolean = false
|
|
||||||
override fun dispose() {
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun unsafeGetTileI16F16(x: Int, y: Int): Pair<Int, Float> = 0 to 0f
|
|
||||||
open fun unsafeGetTileI16I8(x: Int, y: Int): Pair<Int, Int> = 0 to 0
|
|
||||||
|
|
||||||
open fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) { }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class BlockLayerWithChunkPool : BlockLayer() {
|
inline fun BlockLayer.getOffset(x: Int, y: Int): Long {
|
||||||
abstract val chunkPool: ChunkPool
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsupported for BlockLayerWithChunkPool
|
|
||||||
*/
|
|
||||||
override fun getOffset(x: Int, y: Int): Long {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*inline fun BlockLayer.getOffset(x: Int, y: Int): Long {
|
|
||||||
return this.bytesPerBlock * (y * this.width + x)
|
return this.bytesPerBlock * (y * this.width + x)
|
||||||
}*/
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
|
import net.torvald.unsafe.UnsafePtr
|
||||||
import net.torvald.util.Float16
|
import net.torvald.util.Float16
|
||||||
|
|
||||||
const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smaller than epsilon of float16)
|
const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smaller than epsilon of float16)
|
||||||
@@ -14,81 +15,97 @@ const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smalle
|
|||||||
* * ```
|
* * ```
|
||||||
* * where a_n is a fluid number, f_n is a fluid fill
|
* * where a_n is a fluid number, f_n is a fluid fill
|
||||||
*
|
*
|
||||||
* Unsafe version Created by minjaesong on 2023-10-10.
|
* Created by minjaesong on 2023-10-10.
|
||||||
* Chunkpool version Created by minjaesong on 2024-10-22.
|
|
||||||
*/
|
*/
|
||||||
class BlockLayerFluidI16F16 : BlockLayerWithChunkPool {
|
class BlockLayerFluidI16F16(override val width: Int, override val height: Int) : BlockLayer {
|
||||||
|
|
||||||
override val width: Int
|
|
||||||
override val height: Int
|
|
||||||
override val chunkPool: ChunkPool
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
width: Int,
|
|
||||||
height: Int,
|
|
||||||
disk: ClusteredFormatDOM,
|
|
||||||
layerNum: Int,
|
|
||||||
world: TheGameWorld
|
|
||||||
) {
|
|
||||||
this.width = width
|
|
||||||
this.height = height
|
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
width: Int,
|
|
||||||
height: Int,
|
|
||||||
disk: DiskSkimmer,
|
|
||||||
layerNum: Int,
|
|
||||||
world: TheGameWorld
|
|
||||||
) {
|
|
||||||
this.width = width
|
|
||||||
this.height = height
|
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||||
|
|
||||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
// for some reason, all the efforts of saving the memory space were futile.
|
||||||
return unsafeGetTileI16F16(x, y).first
|
|
||||||
|
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||||
|
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
||||||
|
|
||||||
|
val ptrDestroyed: Boolean
|
||||||
|
get() = ptr.destroyed
|
||||||
|
|
||||||
|
init {
|
||||||
|
ptr.fillWith(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeGetTileI16F16(x: Int, y: Int): Pair<Int, Float> {
|
/**
|
||||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
* @param data Byte array representation of the layer
|
||||||
return chunkPool.getTileI16F16(chunk, ox, oy)
|
*/
|
||||||
|
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||||
|
TODO()
|
||||||
|
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over stored bytes.
|
||||||
|
*
|
||||||
|
* @return an Iterator.
|
||||||
|
*/
|
||||||
|
fun bytesIterator(): Iterator<Byte> {
|
||||||
|
return object : Iterator<Byte> {
|
||||||
|
private var iteratorCount = 0L
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return iteratorCount < width * height * bytesPerBlock
|
||||||
|
}
|
||||||
|
override fun next(): Byte {
|
||||||
|
iteratorCount += 1
|
||||||
|
return ptr[iteratorCount - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
|
val offset = getOffset(x, y)
|
||||||
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
|
||||||
|
return lsb.toUint() or msb.toUint().shl(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Float> {
|
||||||
|
val offset = getOffset(x, y)
|
||||||
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
val hbits = (ptr[offset + 2].toUint() or ptr[offset + 3].toUint().shl(8)).toShort()
|
||||||
|
val fill = Float16.toFloat(hbits)
|
||||||
|
|
||||||
|
return lsb.toUint() or msb.toUint().shl(8) to fill
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
val (tile, fill0) = unsafeGetTileI16F16(x, y)
|
val offset = getOffset(x, y)
|
||||||
val fill = Float16.fromFloat(fill0).toUint()
|
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 3], ptr[offset + 2])
|
||||||
return byteArrayOf(
|
|
||||||
((tile ushr 8) and 255).toByte(),
|
|
||||||
(tile and 255).toByte(),
|
|
||||||
((fill ushr 8) and 255).toByte(),
|
|
||||||
(fill and 255).toByte(), )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
internal fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
||||||
throw UnsupportedOperationException()
|
val offset = getOffset(x, y)
|
||||||
}
|
val hbits = Float16.fromFloat(fill).toInt().and(0xFFFF)
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
val tile = if (fill < FLUID_MIN_MASS) 0 else tile0
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
val lsb = tile.and(0xff).toByte()
|
||||||
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
val hlsb = hbits.and(0xff).toByte()
|
||||||
|
val hmsb = hbits.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
ptr[offset] = lsb
|
||||||
|
ptr[offset + 1] = msb
|
||||||
|
ptr[offset + 2] = hlsb
|
||||||
|
ptr[offset + 3] = hmsb
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
|
||||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
|
||||||
val fill = Float16.fromFloat(fill).toUint()
|
|
||||||
chunkPool.setTileRaw(chunk, ox, oy, tile0.and(65535) or fill.shl(16))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
val tile = bytes[1].toUint().shl(8) or bytes[0].toUint()
|
val offset = getOffset(x, y)
|
||||||
val fill = Float16.toFloat((bytes[3].toUint().shl(8) or bytes[2].toUint()).toShort())
|
ptr[offset] = bytes[1]
|
||||||
unsafeSetTile(x, y, tile, fill)
|
ptr[offset + 1] = bytes[0]
|
||||||
|
ptr[offset + 2] = bytes[3]
|
||||||
|
ptr[offset + 3] = bytes[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,18 +123,14 @@ class BlockLayerFluidI16F16 : BlockLayerWithChunkPool {
|
|||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
override var disposed: Boolean = false
|
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
chunkPool.dispose()
|
ptr.destroy()
|
||||||
disposed = true
|
App.printdbg(this, "BlockLayerI16F16 with ptr ($ptr) successfully freed")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "BlockLayerI16F16 (${width}x$height)"
|
override fun toString(): String = ptr.toString("BlockLayerI16F16")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val BYTES_PER_BLOCK = 4L
|
@Transient val BYTES_PER_BLOCK = 4L
|
||||||
|
|
||||||
private fun Short.toUint() = this.toInt().and(65535)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
|
import net.torvald.unsafe.UnsafePtr
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memory layout:
|
* Memory layout:
|
||||||
@@ -15,89 +18,80 @@ import net.torvald.terrarum.serialise.toUint
|
|||||||
*
|
*
|
||||||
* Original version Created by minjaesong on 2016-01-17.
|
* Original version Created by minjaesong on 2016-01-17.
|
||||||
* Unsafe version Created by minjaesong on 2019-06-08.
|
* Unsafe version Created by minjaesong on 2019-06-08.
|
||||||
* Chunkpool version Created by minjaesong on 2024-10-22.
|
|
||||||
*
|
*
|
||||||
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
|
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
|
||||||
*/
|
*/
|
||||||
class BlockLayerGenericI16: BlockLayerWithChunkPool {
|
class BlockLayerGenericI16(
|
||||||
|
override val width: Int,
|
||||||
override val width: Int
|
override val height: Int,
|
||||||
override val height: Int
|
): BlockLayer {
|
||||||
override val chunkPool: ChunkPool
|
|
||||||
|
|
||||||
private var _hashcode = 0
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
width: Int,
|
|
||||||
height: Int,
|
|
||||||
disk: ClusteredFormatDOM,
|
|
||||||
layerNum: Int,
|
|
||||||
world: TheGameWorld
|
|
||||||
) {
|
|
||||||
this.width = width
|
|
||||||
this.height = height
|
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, when (layerNum) {
|
|
||||||
TERRAIN -> ChunkPool.getRenameFunTerrain(world)
|
|
||||||
WALL -> ChunkPool.getRenameFunTerrain(world)
|
|
||||||
else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum")
|
|
||||||
})
|
|
||||||
|
|
||||||
_hashcode = disk.uuid.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
width: Int,
|
|
||||||
height: Int,
|
|
||||||
disk: DiskSkimmer,
|
|
||||||
layerNum: Int,
|
|
||||||
world: TheGameWorld
|
|
||||||
) {
|
|
||||||
this.width = width
|
|
||||||
this.height = height
|
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, when (layerNum) {
|
|
||||||
TERRAIN -> ChunkPool.getRenameFunTerrain(world)
|
|
||||||
WALL -> ChunkPool.getRenameFunTerrain(world)
|
|
||||||
else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum")
|
|
||||||
})
|
|
||||||
|
|
||||||
_hashcode = disk.diskFile.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode() = _hashcode
|
|
||||||
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||||
|
|
||||||
|
// for some reason, all the efforts of saving the memory space were futile.
|
||||||
|
|
||||||
|
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||||
|
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
||||||
|
|
||||||
|
val ptrDestroyed: Boolean
|
||||||
|
get() = ptr.destroyed
|
||||||
|
|
||||||
|
init {
|
||||||
|
ptr.fillWith(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over stored bytes.
|
||||||
|
*
|
||||||
|
* @return an Iterator.
|
||||||
|
*/
|
||||||
|
fun bytesIterator(): Iterator<Byte> {
|
||||||
|
return object : Iterator<Byte> {
|
||||||
|
private var iteratorCount = 0L
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return iteratorCount < width * height * bytesPerBlock
|
||||||
|
}
|
||||||
|
override fun next(): Byte {
|
||||||
|
iteratorCount += 1
|
||||||
|
return ptr[iteratorCount - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
val offset = getOffset(x, y)
|
||||||
return chunkPool.getTileI16(chunk, ox, oy)
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
|
||||||
|
return lsb.toUint() or msb.toUint().shl(8)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
val bytes = unsafeGetTile(x, y)
|
val offset = getOffset(x, y)
|
||||||
return byteArrayOf(
|
return byteArrayOf(ptr[offset + 1], ptr[offset + 0])
|
||||||
((bytes ushr 8) and 255).toByte(),
|
|
||||||
(bytes and 255).toByte()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
val offset = getOffset(x, y)
|
||||||
chunkPool.setTileRaw(chunk, ox, oy, tile)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
val lsb = tile.and(0xff).toByte()
|
||||||
throw UnsupportedOperationException()
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
|
||||||
throw UnsupportedOperationException()
|
// 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) {
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
val tile = (0..1).fold(0) { acc, i -> acc or (bytes[i].toUint()).shl(8*i) }
|
val offset = getOffset(x, y)
|
||||||
unsafeSetTile(x, y, tile)
|
ptr[offset] = bytes[1]
|
||||||
|
ptr[offset + 1] = bytes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,14 +109,12 @@ class BlockLayerGenericI16: BlockLayerWithChunkPool {
|
|||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
override var disposed: Boolean = false
|
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
chunkPool.dispose()
|
ptr.destroy()
|
||||||
disposed = true
|
printdbg(this, "BlockLayerI16 with ptr ($ptr) successfully freed")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "BlockLayerI16 (${width}x$height)"
|
override fun toString(): String = ptr.toString("BlockLayerI16")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val BYTES_PER_BLOCK = 2L
|
@Transient val BYTES_PER_BLOCK = 2L
|
||||||
|
|||||||
@@ -1,133 +0,0 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
|
||||||
|
|
||||||
import com.badlogic.gdx.utils.Disposable
|
|
||||||
import net.torvald.terrarum.App.printdbg
|
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
|
||||||
import net.torvald.terrarum.serialise.toUint
|
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
|
||||||
import net.torvald.unsafe.UnsafePtr
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory layout:
|
|
||||||
* ```
|
|
||||||
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 ||
|
|
||||||
* ```
|
|
||||||
* where a_n is a tile number
|
|
||||||
*
|
|
||||||
* Original version Created by minjaesong on 2016-01-17.
|
|
||||||
* Unsafe version Created by minjaesong on 2019-06-08.
|
|
||||||
*
|
|
||||||
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
|
|
||||||
*/
|
|
||||||
class BlockLayerInMemoryI16(
|
|
||||||
override val width: Int,
|
|
||||||
override val height: Int,
|
|
||||||
): BlockLayer() {
|
|
||||||
|
|
||||||
private constructor() : this(0, 0)
|
|
||||||
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
|
||||||
|
|
||||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
|
||||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
|
||||||
|
|
||||||
val ptrDestroyed: Boolean
|
|
||||||
get() = ptr.destroyed
|
|
||||||
|
|
||||||
init {
|
|
||||||
ptr.fillWith(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator over stored bytes.
|
|
||||||
*
|
|
||||||
* @return an Iterator.
|
|
||||||
*/
|
|
||||||
fun bytesIterator(): Iterator<Byte> {
|
|
||||||
return object : Iterator<Byte> {
|
|
||||||
private var iteratorCount = 0L
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
return iteratorCount < width * height * bytesPerBlock
|
|
||||||
}
|
|
||||||
override fun next(): Byte {
|
|
||||||
iteratorCount += 1
|
|
||||||
return ptr[iteratorCount - 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
val lsb = ptr[offset]
|
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
|
|
||||||
return lsb.toUint() or msb.toUint().shl(8)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0])
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
|
|
||||||
// try {
|
|
||||||
ptr[offset] = lsb
|
|
||||||
ptr[offset + 1] = msb
|
|
||||||
// }
|
|
||||||
// catch (e: IndexOutOfBoundsException) {
|
|
||||||
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
|
||||||
// throw e
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
ptr[offset] = bytes[1]
|
|
||||||
ptr[offset + 1] = bytes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
|
||||||
*/
|
|
||||||
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
|
||||||
val offset = BYTES_PER_BLOCK * blockOffset
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
unsafe.putByte(layerPtr + offset, lsb)
|
|
||||||
unsafe.putByte(layerPtr + offset + 1, msb)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
|
||||||
|
|
||||||
override val disposed: Boolean
|
|
||||||
get() = ptr.destroyed
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
ptr.destroy()
|
|
||||||
printdbg(this, "BlockLayerI16 with ptr ($ptr) successfully freed")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString("BlockLayerI16")
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Transient val BYTES_PER_BLOCK = 2L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
|
||||||
|
|
||||||
import net.torvald.terrarum.App
|
|
||||||
import net.torvald.terrarum.serialise.toUint
|
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
|
||||||
import net.torvald.unsafe.UnsafePtr
|
|
||||||
import net.torvald.util.Float16
|
|
||||||
|
|
||||||
/**
|
|
||||||
* * Memory layout:
|
|
||||||
* * ```
|
|
||||||
* * a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | f7 f6 f5 f4 f3 f2 f1 f0 | fF fE fD fC fB fA f9 f8 ||
|
|
||||||
* * ```
|
|
||||||
* * where a_n is a fluid number, f_n is a fluid fill
|
|
||||||
*
|
|
||||||
* Created by minjaesong on 2023-10-10.
|
|
||||||
*/
|
|
||||||
class BlockLayerInMemoryI16F16(override val width: Int, override val height: Int) : BlockLayer() {
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
|
||||||
|
|
||||||
// for some reason, all the efforts of saving the memory space were futile.
|
|
||||||
|
|
||||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
|
||||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
|
||||||
|
|
||||||
val ptrDestroyed: Boolean
|
|
||||||
get() = ptr.destroyed
|
|
||||||
|
|
||||||
init {
|
|
||||||
ptr.fillWith(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param data Byte array representation of the layer
|
|
||||||
*/
|
|
||||||
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
|
||||||
TODO()
|
|
||||||
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator over stored bytes.
|
|
||||||
*
|
|
||||||
* @return an Iterator.
|
|
||||||
*/
|
|
||||||
fun bytesIterator(): Iterator<Byte> {
|
|
||||||
return object : Iterator<Byte> {
|
|
||||||
private var iteratorCount = 0L
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
return iteratorCount < width * height * bytesPerBlock
|
|
||||||
}
|
|
||||||
override fun next(): Byte {
|
|
||||||
iteratorCount += 1
|
|
||||||
return ptr[iteratorCount - 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
val lsb = ptr[offset]
|
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
|
|
||||||
return lsb.toUint() or msb.toUint().shl(8)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Float> {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
val lsb = ptr[offset]
|
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
val hbits = (ptr[offset + 2].toUint() or ptr[offset + 3].toUint().shl(8)).toShort()
|
|
||||||
val fill = Float16.toFloat(hbits)
|
|
||||||
|
|
||||||
return lsb.toUint() or msb.toUint().shl(8) to fill
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 3], ptr[offset + 2])
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
val hbits = Float16.fromFloat(fill).toInt().and(0xFFFF)
|
|
||||||
|
|
||||||
val tile = if (fill < FLUID_MIN_MASS) 0 else tile0
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
val hlsb = hbits.and(0xff).toByte()
|
|
||||||
val hmsb = hbits.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
ptr[offset] = lsb
|
|
||||||
ptr[offset + 1] = msb
|
|
||||||
ptr[offset + 2] = hlsb
|
|
||||||
ptr[offset + 3] = hmsb
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
ptr[offset] = bytes[1]
|
|
||||||
ptr[offset + 1] = bytes[0]
|
|
||||||
ptr[offset + 2] = bytes[3]
|
|
||||||
ptr[offset + 3] = bytes[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
|
||||||
*/
|
|
||||||
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
|
||||||
val offset = BYTES_PER_BLOCK * blockOffset
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
unsafe.putByte(layerPtr + offset, lsb)
|
|
||||||
unsafe.putByte(layerPtr + offset + 1, msb)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
|
||||||
|
|
||||||
override val disposed: Boolean
|
|
||||||
get() = ptr.destroyed
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
ptr.destroy()
|
|
||||||
App.printdbg(this, "BlockLayerI16F16 with ptr ($ptr) successfully freed")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString("BlockLayerI16F16")
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Transient val BYTES_PER_BLOCK = 4L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
|
||||||
|
|
||||||
import net.torvald.terrarum.App
|
|
||||||
import net.torvald.terrarum.serialise.toUint
|
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
|
||||||
import net.torvald.unsafe.UnsafePtr
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory layout:
|
|
||||||
* ```
|
|
||||||
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | p7 p6 p5 p4 p3 p2 p1 p0 ||
|
|
||||||
* ```
|
|
||||||
* where a_n is a tile number, p_n is a placement index
|
|
||||||
* Created by minjaesong on 2023-10-10.
|
|
||||||
*/
|
|
||||||
class BlockLayerInMemoryI16I8 (override val width: Int, override val height: Int) : BlockLayer() {
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
|
||||||
|
|
||||||
// for some reason, all the efforts of saving the memory space were futile.
|
|
||||||
|
|
||||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
|
||||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
|
||||||
|
|
||||||
val ptrDestroyed: Boolean
|
|
||||||
get() = ptr.destroyed
|
|
||||||
|
|
||||||
init {
|
|
||||||
ptr.fillWith(0) // there is no NOT-GENERATED for ores, keep it as 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param data Byte array representation of the layer
|
|
||||||
*/
|
|
||||||
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
|
||||||
TODO()
|
|
||||||
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator over stored bytes.
|
|
||||||
*
|
|
||||||
* @return an Iterator.
|
|
||||||
*/
|
|
||||||
fun bytesIterator(): Iterator<Byte> {
|
|
||||||
return object : Iterator<Byte> {
|
|
||||||
private var iteratorCount = 0L
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
return iteratorCount < width * height * bytesPerBlock
|
|
||||||
}
|
|
||||||
override fun next(): Byte {
|
|
||||||
iteratorCount += 1
|
|
||||||
return ptr[iteratorCount - 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
val lsb = ptr[offset]
|
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
val placement = ptr[offset + 2]
|
|
||||||
|
|
||||||
return lsb.toUint() + msb.toUint().shl(8)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Int> {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
val lsb = ptr[offset]
|
|
||||||
val msb = ptr[offset + 1]
|
|
||||||
val placement = ptr[offset + 2]
|
|
||||||
|
|
||||||
return lsb.toUint() or msb.toUint().shl(8) to placement.toUint()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 2])
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
|
|
||||||
// try {
|
|
||||||
ptr[offset] = lsb
|
|
||||||
ptr[offset + 1] = msb
|
|
||||||
ptr[offset + 2] = placement.toByte()
|
|
||||||
// }
|
|
||||||
// catch (e: IndexOutOfBoundsException) {
|
|
||||||
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
|
||||||
// throw e
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
ptr[offset] = bytes[1]
|
|
||||||
ptr[offset + 1] = bytes[0]
|
|
||||||
ptr[offset + 2] = bytes[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) {
|
|
||||||
val offset = getOffset(x, y)
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
ptr[offset] = lsb
|
|
||||||
ptr[offset + 1] = msb
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
|
||||||
*/
|
|
||||||
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
|
||||||
val offset = BYTES_PER_BLOCK * blockOffset
|
|
||||||
|
|
||||||
val lsb = tile.and(0xff).toByte()
|
|
||||||
val msb = tile.ushr(8).and(0xff).toByte()
|
|
||||||
|
|
||||||
unsafe.putByte(layerPtr + offset, lsb)
|
|
||||||
unsafe.putByte(layerPtr + offset + 1, msb)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
|
||||||
|
|
||||||
override val disposed: Boolean
|
|
||||||
get() = ptr.destroyed
|
|
||||||
|
|
||||||
override fun dispose() {
|
|
||||||
ptr.destroy()
|
|
||||||
App.printdbg(this, "BlockLayerI16I8 with ptr ($ptr) successfully freed")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = ptr.toString("BlockLayerI16I8")
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Transient val BYTES_PER_BLOCK = 3L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
|
||||||
import net.torvald.terrarum.serialise.toUint
|
import net.torvald.terrarum.serialise.toUint
|
||||||
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
|
import net.torvald.unsafe.UnsafePtr
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memory layout:
|
* Memory layout:
|
||||||
@@ -10,85 +11,105 @@ import net.torvald.terrarum.serialise.toUint
|
|||||||
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | p7 p6 p5 p4 p3 p2 p1 p0 ||
|
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | p7 p6 p5 p4 p3 p2 p1 p0 ||
|
||||||
* ```
|
* ```
|
||||||
* where a_n is a tile number, p_n is a placement index
|
* where a_n is a tile number, p_n is a placement index
|
||||||
*
|
* Created by minjaesong on 2023-10-10.
|
||||||
* Unsafe version Created by minjaesong on 2023-10-10.
|
|
||||||
* Chunkpool version Created by minjaesong on 2024-10-22.
|
|
||||||
*/
|
*/
|
||||||
class BlockLayerOresI16I8 : BlockLayerWithChunkPool {
|
class BlockLayerOresI16I8 (override val width: Int, override val height: Int) : BlockLayer {
|
||||||
|
|
||||||
override val width: Int
|
|
||||||
override val height: Int
|
|
||||||
override val chunkPool: ChunkPool
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
width: Int,
|
|
||||||
height: Int,
|
|
||||||
disk: ClusteredFormatDOM,
|
|
||||||
layerNum: Int,
|
|
||||||
world: TheGameWorld
|
|
||||||
) {
|
|
||||||
this.width = width
|
|
||||||
this.height = height
|
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
width: Int,
|
|
||||||
height: Int,
|
|
||||||
disk: DiskSkimmer,
|
|
||||||
layerNum: Int,
|
|
||||||
world: TheGameWorld
|
|
||||||
) {
|
|
||||||
this.width = width
|
|
||||||
this.height = height
|
|
||||||
|
|
||||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||||
|
|
||||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
// for some reason, all the efforts of saving the memory space were futile.
|
||||||
return unsafeGetTileI16I8(x, y).first
|
|
||||||
|
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||||
|
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
||||||
|
|
||||||
|
val ptrDestroyed: Boolean
|
||||||
|
get() = ptr.destroyed
|
||||||
|
|
||||||
|
init {
|
||||||
|
ptr.fillWith(0) // there is no NOT-GENERATED for ores, keep it as 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeGetTileI16I8(x: Int, y: Int): Pair<Int, Int> {
|
/**
|
||||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
* @param data Byte array representation of the layer
|
||||||
return chunkPool.getTileI16I8(chunk, ox, oy)
|
*/
|
||||||
|
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||||
|
TODO()
|
||||||
|
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over stored bytes.
|
||||||
|
*
|
||||||
|
* @return an Iterator.
|
||||||
|
*/
|
||||||
|
fun bytesIterator(): Iterator<Byte> {
|
||||||
|
return object : Iterator<Byte> {
|
||||||
|
private var iteratorCount = 0L
|
||||||
|
override fun hasNext(): Boolean {
|
||||||
|
return iteratorCount < width * height * bytesPerBlock
|
||||||
|
}
|
||||||
|
override fun next(): Byte {
|
||||||
|
iteratorCount += 1
|
||||||
|
return ptr[iteratorCount - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||||
|
val offset = getOffset(x, y)
|
||||||
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
val placement = ptr[offset + 2]
|
||||||
|
|
||||||
|
return lsb.toUint() + msb.toUint().shl(8)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Int> {
|
||||||
|
val offset = getOffset(x, y)
|
||||||
|
val lsb = ptr[offset]
|
||||||
|
val msb = ptr[offset + 1]
|
||||||
|
val placement = ptr[offset + 2]
|
||||||
|
|
||||||
|
return lsb.toUint() or msb.toUint().shl(8) to placement.toUint()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||||
val (tile, fill) = unsafeGetTileI16I8(x, y)
|
val offset = getOffset(x, y)
|
||||||
return byteArrayOf(
|
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 2])
|
||||||
((tile ushr 8) and 255).toByte(),
|
|
||||||
(tile and 255).toByte(),
|
|
||||||
(fill and 255).toByte()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
internal fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||||
throw UnsupportedOperationException()
|
val offset = getOffset(x, y)
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
val lsb = tile.and(0xff).toByte()
|
||||||
throw UnsupportedOperationException()
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
}
|
|
||||||
|
|
||||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
|
||||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
// try {
|
||||||
chunkPool.setTileRaw(chunk, ox, oy, tile or placement.shl(16))
|
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) {
|
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||||
val tile = bytes[1].toUint().shl(8) or bytes[0].toUint()
|
val offset = getOffset(x, y)
|
||||||
val placement = bytes[2].toUint()
|
ptr[offset] = bytes[1]
|
||||||
unsafeSetTile(x, y, tile, placement)
|
ptr[offset + 1] = bytes[0]
|
||||||
|
ptr[offset + 2] = bytes[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) {
|
internal fun unsafeSetTileKeepPlacement(x: Int, y: Int, tile: Int) {
|
||||||
val oldPlacement = unsafeGetTileI16I8(x, y).second
|
val offset = getOffset(x, y)
|
||||||
unsafeSetTile(x, y, tile, oldPlacement)
|
|
||||||
|
val lsb = tile.and(0xff).toByte()
|
||||||
|
val msb = tile.ushr(8).and(0xff).toByte()
|
||||||
|
|
||||||
|
ptr[offset] = lsb
|
||||||
|
ptr[offset + 1] = msb
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,14 +127,12 @@ class BlockLayerOresI16I8 : BlockLayerWithChunkPool {
|
|||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|
||||||
override var disposed: Boolean = false
|
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
chunkPool.dispose()
|
ptr.destroy()
|
||||||
disposed = true
|
App.printdbg(this, "BlockLayerI16I8 with ptr ($ptr) successfully freed")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "BlockLayerI16I8 (${width}x$height)"
|
override fun toString(): String = ptr.toString("BlockLayerI16I8")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Transient val BYTES_PER_BLOCK = 3L
|
@Transient val BYTES_PER_BLOCK = 3L
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.App.printdbg
|
|
||||||
import net.torvald.terrarum.INGAME
|
import net.torvald.terrarum.INGAME
|
||||||
import net.torvald.terrarum.Point2i
|
import net.torvald.terrarum.Point2i
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||||
@@ -9,7 +8,6 @@ import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.Clustf
|
|||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
||||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
||||||
import net.torvald.terrarum.savegame.ByteArray64
|
|
||||||
import net.torvald.terrarum.savegame.DiskEntry
|
import net.torvald.terrarum.savegame.DiskEntry
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||||
import net.torvald.terrarum.savegame.EntryFile
|
import net.torvald.terrarum.savegame.EntryFile
|
||||||
@@ -37,74 +35,25 @@ enum class ChunkAllocClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WHAT IF instead of reading chunks directly from the savegame, I treat ChunkPool as a mere disk-cache?
|
|
||||||
*
|
|
||||||
* FIXME: loading a chunk from disk will attempt to create a chunk because the chunk-to-be-loaded
|
|
||||||
* is not on the pointers map, and this operation will want to create a new chunk file but the file already exists
|
|
||||||
*
|
|
||||||
* Single layer gets single Chunk Pool.
|
* Single layer gets single Chunk Pool.
|
||||||
*
|
*
|
||||||
* Created by minjaesong on 2024-09-07.
|
* Created by minjaesong on 2024-09-07.
|
||||||
*/
|
*/
|
||||||
open class ChunkPool {
|
open class ChunkPool(
|
||||||
|
|
||||||
private enum class ChunkLoadingStatus {
|
|
||||||
LOADING_REQUESTED, RAW, LOADED_FROM_DISK, NEWLY_GENERATED
|
|
||||||
}
|
|
||||||
|
|
||||||
// `DiskSkimmer` or `ClusteredFormatDOM`
|
// `DiskSkimmer` or `ClusteredFormatDOM`
|
||||||
private val disk: Any
|
val disk: Any,
|
||||||
private val layerIndex: Int
|
val layerIndex: Int,
|
||||||
private val wordSizeInBytes: Long
|
val wordSizeInBytes: Long,
|
||||||
private val world: TheGameWorld
|
val world: GameWorld,
|
||||||
private val initialValue: Int // bytes to fill the new chunk
|
val renumberFun: (Int) -> Int,
|
||||||
private val renumberFun: (Int) -> Int
|
) {
|
||||||
|
|
||||||
private val chunkStatus = HashMap<Long, ChunkLoadingStatus>()
|
|
||||||
private val pointers = TreeMap<Long, Long>()
|
private val pointers = TreeMap<Long, Long>()
|
||||||
private var allocCap = 32
|
private var allocCap = 32
|
||||||
private var allocMap = Array<ChunkAllocation?>(allocCap) { null }
|
private var allocMap = Array<ChunkAllocation?>(allocCap) { null }
|
||||||
private var allocCounter = 0
|
private var allocCounter = 0
|
||||||
private val chunkSize: Long
|
|
||||||
private val pool: UnsafePtr
|
|
||||||
|
|
||||||
constructor(
|
private val chunkSize = (wordSizeInBytes * CHUNK_W * CHUNK_H)
|
||||||
disk: DiskSkimmer,
|
private val pool = UnsafeHelper.allocate(chunkSize * allocCap)
|
||||||
layerIndex: Int,
|
|
||||||
wordSizeInBytes: Long,
|
|
||||||
world: TheGameWorld,
|
|
||||||
initialValue: Int,
|
|
||||||
renumberFun: (Int) -> Int,
|
|
||||||
) {
|
|
||||||
this.disk = disk
|
|
||||||
this.layerIndex = layerIndex
|
|
||||||
this.wordSizeInBytes = wordSizeInBytes
|
|
||||||
this.world = world
|
|
||||||
this.initialValue = initialValue
|
|
||||||
this.renumberFun = renumberFun
|
|
||||||
|
|
||||||
chunkSize = wordSizeInBytes * CHUNK_W * CHUNK_H
|
|
||||||
pool = UnsafeHelper.allocate(chunkSize * allocCap)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
disk: ClusteredFormatDOM,
|
|
||||||
layerIndex: Int,
|
|
||||||
wordSizeInBytes: Long,
|
|
||||||
world: TheGameWorld,
|
|
||||||
initialValue: Int,
|
|
||||||
renumberFun: (Int) -> Int,
|
|
||||||
) {
|
|
||||||
this.disk = disk
|
|
||||||
this.layerIndex = layerIndex
|
|
||||||
this.wordSizeInBytes = wordSizeInBytes
|
|
||||||
this.world = world
|
|
||||||
this.initialValue = initialValue
|
|
||||||
this.renumberFun = renumberFun
|
|
||||||
|
|
||||||
chunkSize = wordSizeInBytes * CHUNK_W * CHUNK_H
|
|
||||||
pool = UnsafeHelper.allocate(chunkSize * allocCap)
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
allocMap.fill(null)
|
allocMap.fill(null)
|
||||||
@@ -115,9 +64,6 @@ open class ChunkPool {
|
|||||||
return UnsafePtr(baseAddr, chunkSize)
|
return UnsafePtr(baseAddr, chunkSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a pointer and the offset from the pointer. The offset is given in bytes, but always word-aligned (if block offset is `(2, 0)`, the returning offset will be `8`, assuming word size of 4)
|
|
||||||
*/
|
|
||||||
private fun createPointerViewOfChunk(chunkNumber: Long, offsetX: Int, offsetY: Int): Pair<UnsafePtr, Long> {
|
private fun createPointerViewOfChunk(chunkNumber: Long, offsetX: Int, offsetY: Int): Pair<UnsafePtr, Long> {
|
||||||
val baseAddr = pointers[chunkNumber]!!
|
val baseAddr = pointers[chunkNumber]!!
|
||||||
return UnsafePtr(baseAddr, chunkSize) to wordSizeInBytes * (offsetY * CHUNK_W + offsetX)
|
return UnsafePtr(baseAddr, chunkSize) to wordSizeInBytes * (offsetY * CHUNK_W + offsetX)
|
||||||
@@ -222,17 +168,12 @@ open class ChunkPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private fun fetchFromDisk(chunkNumber: Long) {
|
||||||
* @return `unit` if IO operation was successful, `null` if failed (e.g. file not exists)
|
val fileName = chunkNumToFileNum(layerIndex, chunkNumber)
|
||||||
*/
|
|
||||||
private fun fetchFromDisk(chunkNumber: Long): Unit? {
|
|
||||||
// read data from the disk
|
// read data from the disk
|
||||||
return if (disk is ClusteredFormatDOM) {
|
if (disk is ClusteredFormatDOM) {
|
||||||
val fileName = chunkNumToFileNumType17(layerIndex, chunkNumber)
|
|
||||||
|
|
||||||
Clustfile(disk, fileName).let {
|
Clustfile(disk, fileName).let {
|
||||||
if (!it.exists()) return@let null
|
|
||||||
|
|
||||||
val bytes = Common.unzip(it.readBytes())
|
val bytes = Common.unzip(it.readBytes())
|
||||||
val ptr = allocate(chunkNumber)
|
val ptr = allocate(chunkNumber)
|
||||||
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
||||||
@@ -240,42 +181,21 @@ open class ChunkPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (disk is DiskSkimmer) {
|
else if (disk is DiskSkimmer) {
|
||||||
val fileID = chunkNumToFileEntryID(layerIndex, chunkNumber)
|
val fileID = fileName.toLong()
|
||||||
|
disk.getFile(fileID)!!.let {
|
||||||
disk.getFile(fileID).let {
|
|
||||||
printdbg(this, "Reading chunk data: Layer $layerIndex Chunk $chunkNumber (fileID: $fileID), file: $it")
|
|
||||||
|
|
||||||
if (it == null) return@let null
|
|
||||||
|
|
||||||
val bytes = Common.unzip(it.bytes)
|
val bytes = Common.unzip(it.bytes)
|
||||||
val ptr = allocate(chunkNumber)
|
val ptr = allocate(chunkNumber)
|
||||||
memcpyFromByteArray64ToPtr(bytes, 0L, ptr, 0L, bytes.size)
|
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
||||||
renumber(ptr)
|
renumber(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
throw IllegalStateException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun memcpyFromByteArray64ToPtr(ba: ByteArray64, srcIndex: Long, destPtr: UnsafePtr, destOffset: Long, copyLen: Long) {
|
|
||||||
// TODO temporary
|
|
||||||
val obj = ba.toByteArray()
|
|
||||||
UnsafeHelper.memcpyFromArrToPtr(obj, srcIndex.toInt(), destPtr.ptr + destOffset, copyLen)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return `unit` if IO operation was successful, `null` if failed (e.g. file not exists)
|
|
||||||
*/
|
|
||||||
private fun createNewChunkFile(chunkNumber: Long): Unit? {
|
|
||||||
TODO()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun storeToDisk(chunkNumber: Long) {
|
private fun storeToDisk(chunkNumber: Long) {
|
||||||
|
val fileName = chunkNumToFileNum(layerIndex, chunkNumber)
|
||||||
|
|
||||||
// write to the disk (the disk must be an autosaving copy of the original)
|
// write to the disk (the disk must be an autosaving copy of the original)
|
||||||
if (disk is ClusteredFormatDOM) {
|
if (disk is ClusteredFormatDOM) {
|
||||||
val fileName = chunkNumToFileNumType17(layerIndex, chunkNumber)
|
|
||||||
|
|
||||||
Clustfile(disk, fileName).let {
|
Clustfile(disk, fileName).let {
|
||||||
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
||||||
it.overwrite(bytes.toByteArray())
|
it.overwrite(bytes.toByteArray())
|
||||||
@@ -283,7 +203,7 @@ open class ChunkPool {
|
|||||||
}
|
}
|
||||||
// append the new entry
|
// append the new entry
|
||||||
else if (disk is DiskSkimmer) {
|
else if (disk is DiskSkimmer) {
|
||||||
val fileID = chunkNumToFileEntryID(layerIndex, chunkNumber)
|
val fileID = fileName.toLong()
|
||||||
|
|
||||||
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
||||||
val oldEntry = disk.getEntry(fileID)
|
val oldEntry = disk.getEntry(fileID)
|
||||||
@@ -294,7 +214,7 @@ open class ChunkPool {
|
|||||||
|
|
||||||
private fun checkForChunk(chunkNumber: Long) {
|
private fun checkForChunk(chunkNumber: Long) {
|
||||||
if (!pointers.containsKey(chunkNumber)) {
|
if (!pointers.containsKey(chunkNumber)) {
|
||||||
fetchFromDisk(chunkNumber) ?: createNewChunkFile(chunkNumber) ?: TODO("handle IO error")
|
fetchFromDisk(chunkNumber)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,19 +225,6 @@ open class ChunkPool {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
fun worldXYChunkNumAndOffset(worldx: Int, worldy: Int): Triple<Long, Int, Int> {
|
|
||||||
val chunkX = worldx / CHUNK_W
|
|
||||||
val chunkY = worldy / CHUNK_H
|
|
||||||
val chunkOx = worldx % CHUNK_W
|
|
||||||
val chunkOy = worldy % CHUNK_H
|
|
||||||
|
|
||||||
val chunkNum = LandUtil.chunkXYtoChunkNum(world, chunkX, chunkY)
|
|
||||||
return Triple(chunkNum, chunkOx, chunkOy)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateAccessTime(chunkNumber: Long) {
|
|
||||||
allocMap.find { it?.chunkNumber == chunkNumber }!!.let { it.lastAccessTime = System.nanoTime() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
||||||
@@ -328,7 +235,7 @@ open class ChunkPool {
|
|||||||
*/
|
*/
|
||||||
fun getTileRaw(chunkNumber: Long, offX: Int, offY: Int): Int {
|
fun getTileRaw(chunkNumber: Long, offX: Int, offY: Int): Int {
|
||||||
checkForChunk(chunkNumber)
|
checkForChunk(chunkNumber)
|
||||||
updateAccessTime(chunkNumber)
|
allocMap.find { it?.chunkNumber == chunkNumber }!!.let { it.lastAccessTime = System.nanoTime() }
|
||||||
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
||||||
val numIn = (0 until wordSizeInBytes.toInt()).fold(0) { acc, off ->
|
val numIn = (0 until wordSizeInBytes.toInt()).fold(0) { acc, off ->
|
||||||
acc or (ptr[ptrOff].toUint().shl(8 * off))
|
acc or (ptr[ptrOff].toUint().shl(8 * off))
|
||||||
@@ -336,23 +243,6 @@ open class ChunkPool {
|
|||||||
return numIn
|
return numIn
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Given the bytes of Int `B3_B2_B1_B0`
|
|
||||||
* Saved as:
|
|
||||||
* - word size is 4: `[B0, B1, B2, B3]`
|
|
||||||
* - word size is 3: `[B0, B1, B2]` (B3 is ignored)
|
|
||||||
* - word size is 2: `[B0, B1]` (B2 and B3 are ignored)
|
|
||||||
*/
|
|
||||||
fun setTileRaw(chunkNumber: Long, offX: Int, offY: Int, bytes: Int) {
|
|
||||||
checkForChunk(chunkNumber)
|
|
||||||
updateAccessTime(chunkNumber)
|
|
||||||
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
|
||||||
for (i in 0 until wordSizeInBytes.toInt()) {
|
|
||||||
val b = bytes.ushr(8*i).and(255)
|
|
||||||
ptr[ptrOff + i] = b.toByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
||||||
* Return format:
|
* Return format:
|
||||||
@@ -390,18 +280,11 @@ open class ChunkPool {
|
|||||||
return ibits to jbits
|
return ibits to jbits
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dispose() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun chunkNumToFileNumType17(layerNum: Int, chunkNum: Long): String {
|
fun chunkNumToFileNum(layerNum: Int, chunkNum: Long): String {
|
||||||
val entryID = Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
val entryID = Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
||||||
return Common.type254EntryIDtoType17Filename(entryID)
|
return Common.type254EntryIDtoType17Filename(entryID)
|
||||||
}
|
}
|
||||||
fun chunkNumToFileEntryID(layerNum: Int, chunkNum: Long): Long {
|
|
||||||
return Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Int.get1SS() = this and 65535
|
private fun Int.get1SS() = this and 65535
|
||||||
private fun Int.get2SS() = (this ushr 16) and 65535
|
private fun Int.get2SS() = (this ushr 16) and 65535
|
||||||
@@ -417,7 +300,7 @@ open class ChunkPool {
|
|||||||
private fun Int.get2LSB() = this.get3MSB()
|
private fun Int.get2LSB() = this.get3MSB()
|
||||||
private fun Int.getLSB() = this.get4MSB()
|
private fun Int.getLSB() = this.get4MSB()
|
||||||
|
|
||||||
fun getRenameFunTerrain(world: TheGameWorld): (Int) -> Int {
|
fun getRenameFunTerrain(world: GameWorld): (Int) -> Int {
|
||||||
// word size: 2
|
// word size: 2
|
||||||
return { oldTileNum ->
|
return { oldTileNum ->
|
||||||
val oldOreName = world.oldTileNumberToNameMap[oldTileNum.toLong()]
|
val oldOreName = world.oldTileNumberToNameMap[oldTileNum.toLong()]
|
||||||
@@ -426,7 +309,7 @@ open class ChunkPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRenameFunOres(world: TheGameWorld): (Int) -> Int {
|
fun getRenameFunOres(world: GameWorld): (Int) -> Int {
|
||||||
// word size: 3
|
// word size: 3
|
||||||
return { oldTileNumRaw ->
|
return { oldTileNumRaw ->
|
||||||
val oldOreNum = oldTileNumRaw and 0x0000FFFF
|
val oldOreNum = oldTileNumRaw and 0x0000FFFF
|
||||||
@@ -437,7 +320,7 @@ open class ChunkPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRenameFunFluids(world: TheGameWorld): (Int) -> Int {
|
fun getRenameFunFluids(world: GameWorld): (Int) -> Int {
|
||||||
// word size: 4
|
// word size: 4
|
||||||
return { oldTileNumRaw ->
|
return { oldTileNumRaw ->
|
||||||
val oldFluidNum = oldTileNumRaw and 0x0000FFFF
|
val oldFluidNum = oldTileNumRaw and 0x0000FFFF
|
||||||
@@ -448,8 +331,7 @@ open class ChunkPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this list does NOT contain `Point2i(0,0)`
|
private val chunkOffsetsNearPlayer = listOf(
|
||||||
val chunkOffsetsNearPlayer = listOf(
|
|
||||||
Point2i(-1,-2), Point2i(0,-2),Point2i(1,-2),
|
Point2i(-1,-2), Point2i(0,-2),Point2i(1,-2),
|
||||||
Point2i(-2,-1),Point2i(-1,-1),Point2i(0,-1),Point2i(1,-1),Point2i(2,-1),
|
Point2i(-2,-1),Point2i(-1,-1),Point2i(0,-1),Point2i(1,-1),Point2i(2,-1),
|
||||||
Point2i(-2,0),Point2i(-1,0),Point2i(1,0),Point2i(2,0),
|
Point2i(-2,0),Point2i(-1,0),Point2i(1,0),Point2i(2,0),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@ package net.torvald.terrarum.modulebasegame
|
|||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.Input.Keys
|
import com.badlogic.gdx.Input.Keys
|
||||||
import com.badlogic.gdx.InputAdapter
|
import com.badlogic.gdx.InputAdapter
|
||||||
import com.badlogic.gdx.files.FileHandle
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
@@ -15,14 +14,14 @@ import net.torvald.terrarum.gameactors.*
|
|||||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.*
|
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
|
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
|
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
|
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIScreenZoom
|
import net.torvald.terrarum.modulebasegame.ui.UIScreenZoom
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
|
||||||
import net.torvald.terrarum.savegame.VDUtil
|
|
||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
import net.torvald.terrarum.serialise.PointOfInterest
|
import net.torvald.terrarum.serialise.PointOfInterest
|
||||||
import net.torvald.terrarum.serialise.POILayer
|
import net.torvald.terrarum.serialise.POILayer
|
||||||
@@ -62,7 +61,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
- Set…
|
- Set…
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
|
||||||
lateinit var gameWorld: TheGameWorld
|
lateinit var gameWorld: GameWorld
|
||||||
|
|
||||||
override val musicStreamer = TerrarumMusicAndAmbientStreamer()
|
override val musicStreamer = TerrarumMusicAndAmbientStreamer()
|
||||||
|
|
||||||
@@ -420,7 +419,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
for (x in for_x_start..for_x_end) {
|
for (x in for_x_start..for_x_end) {
|
||||||
if (wiringCounter >= maxRenderableWires) break
|
if (wiringCounter >= maxRenderableWires) break
|
||||||
|
|
||||||
val (wires, nodes) = gameWorld.getAllWiresFrom(x, y)
|
val (wires, nodes) = world.getAllWiresFrom(x, y)
|
||||||
|
|
||||||
wires?.forEach {
|
wires?.forEach {
|
||||||
val wireActor = wireActorsContainer[wiringCounter]
|
val wireActor = wireActorsContainer[wiringCounter]
|
||||||
@@ -554,7 +553,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
private fun getNearbyOres8(x: Int, y: Int): List<OrePlacement> {
|
private fun getNearbyOres8(x: Int, y: Int): List<OrePlacement> {
|
||||||
return getNearbyTilesPos8(x, y).map { gameWorld.getTileFromOre(it.x, it.y) }
|
return getNearbyTilesPos8(x, y).map { world.getTileFromOre(it.x, it.y) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makePenWork(x: Int, y: Int) {
|
private fun makePenWork(x: Int, y: Int) {
|
||||||
@@ -878,8 +877,8 @@ class YamlCommandToolExportTest : YamlInvokable {
|
|||||||
ui.world.tileNameToNumberMap
|
ui.world.tileNameToNumberMap
|
||||||
)
|
)
|
||||||
val layer = POILayer(name)
|
val layer = POILayer(name)
|
||||||
val terr = BlockLayerInMemoryI16(poi.w, poi.h)
|
val terr = BlockLayerGenericI16(poi.w, poi.h)
|
||||||
val wall = BlockLayerInMemoryI16(poi.w, poi.h)
|
val wall = BlockLayerGenericI16(poi.w, poi.h)
|
||||||
layer.blockLayer = arrayListOf(terr, wall)
|
layer.blockLayer = arrayListOf(terr, wall)
|
||||||
poi.layers.add(layer)
|
poi.layers.add(layer)
|
||||||
|
|
||||||
@@ -935,13 +934,8 @@ class YamlCommandNewFlatTerrain : YamlInvokable {
|
|||||||
|
|
||||||
println("[BuildingMaker] Generating builder world...")
|
println("[BuildingMaker] Generating builder world...")
|
||||||
|
|
||||||
val tempFile = FileHandle.tempFile("terrarumbuildingmaker").file()
|
|
||||||
val tempDisk = VDUtil.createNewDisk(1L shl 30, "buildingmaker", Common.CHARSET)
|
|
||||||
VDUtil.dumpToRealMachine(tempDisk, tempFile)
|
|
||||||
val tempDiskSkimmer = DiskSkimmer(tempFile)
|
|
||||||
|
|
||||||
val timeNow = System.currentTimeMillis() / 1000
|
val timeNow = System.currentTimeMillis() / 1000
|
||||||
ui.gameWorld = TheGameWorld(90*12, 90*4, tempDiskSkimmer, timeNow, timeNow)
|
ui.gameWorld = GameWorld(90*12, 90*4, timeNow, timeNow)
|
||||||
|
|
||||||
// remove null tiles
|
// remove null tiles
|
||||||
for (y in 0 until ui.gameWorld.height) {
|
for (y in 0 until ui.gameWorld.height) {
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import net.torvald.terrarum.BlockCodex
|
|||||||
import net.torvald.terrarum.ItemCodex
|
import net.torvald.terrarum.ItemCodex
|
||||||
import net.torvald.terrarum.OreCodex
|
import net.torvald.terrarum.OreCodex
|
||||||
import net.torvald.terrarum.ceilToInt
|
import net.torvald.terrarum.ceilToInt
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
|
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.getOffset
|
||||||
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
|
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
|
||||||
import net.torvald.unsafe.UnsafeHelper
|
import net.torvald.unsafe.UnsafeHelper
|
||||||
import java.util.concurrent.*
|
import java.util.concurrent.*
|
||||||
@@ -33,7 +34,7 @@ object ExplosionManager {
|
|||||||
val lineMax = world.height - ty + CALC_RADIUS
|
val lineMax = world.height - ty + CALC_RADIUS
|
||||||
|
|
||||||
// create a copy of the tilemap
|
// create a copy of the tilemap
|
||||||
val tilemap = BlockLayerInMemoryI16(CALC_WIDTH, CALC_WIDTH)
|
val tilemap = BlockLayerGenericI16(CALC_WIDTH, CALC_WIDTH)
|
||||||
val breakmap = UnsafeFloatArray(CALC_WIDTH, CALC_WIDTH)
|
val breakmap = UnsafeFloatArray(CALC_WIDTH, CALC_WIDTH)
|
||||||
|
|
||||||
// fill in the tilemap copy
|
// fill in the tilemap copy
|
||||||
@@ -68,9 +69,9 @@ object ExplosionManager {
|
|||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun memcpyFromWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerInMemoryI16) {
|
private fun memcpyFromWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerGenericI16) {
|
||||||
// if the bounding box must wrap around
|
// if the bounding box must wrap around
|
||||||
/*if (xStart > world.width - CALC_RADIUS) {
|
if (xStart > world.width - CALC_RADIUS) {
|
||||||
val lenLeft = world.width - xStart
|
val lenLeft = world.width - xStart
|
||||||
val lenRight = CALC_WIDTH - lenLeft
|
val lenRight = CALC_WIDTH - lenLeft
|
||||||
|
|
||||||
@@ -97,18 +98,12 @@ object ExplosionManager {
|
|||||||
out.getOffset(0, yOff),
|
out.getOffset(0, yOff),
|
||||||
world.layerTerrain.bytesPerBlock * CALC_WIDTH
|
world.layerTerrain.bytesPerBlock * CALC_WIDTH
|
||||||
)
|
)
|
||||||
}*/
|
|
||||||
// temporary: copy one by one
|
|
||||||
for (ox in xStart until xStart + CALC_WIDTH) {
|
|
||||||
val (x, y) = world.coerceXY(ox, yStart + yOff)
|
|
||||||
val tileInWorld = world.layerTerrain.unsafeGetTile(x, y)
|
|
||||||
out.unsafeSetTile(x, y, tileInWorld)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun memcpyToWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerInMemoryI16) {
|
private fun memcpyToWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerGenericI16) {
|
||||||
// if the bounding box must wrap around
|
// if the bounding box must wrap around
|
||||||
/*if (xStart > world.width - CALC_RADIUS) {
|
if (xStart > world.width - CALC_RADIUS) {
|
||||||
val lenLeft = world.width - xStart
|
val lenLeft = world.width - xStart
|
||||||
val lenRight = CALC_WIDTH - lenLeft
|
val lenRight = CALC_WIDTH - lenLeft
|
||||||
|
|
||||||
@@ -135,12 +130,6 @@ object ExplosionManager {
|
|||||||
world.layerTerrain.getOffset(xStart, yStart + yOff),
|
world.layerTerrain.getOffset(xStart, yStart + yOff),
|
||||||
world.layerTerrain.bytesPerBlock * CALC_WIDTH
|
world.layerTerrain.bytesPerBlock * CALC_WIDTH
|
||||||
)
|
)
|
||||||
}*/
|
|
||||||
// temporary: copy one by one
|
|
||||||
for (ox in xStart until xStart + CALC_WIDTH) {
|
|
||||||
val (x, y) = world.coerceXY(ox, yStart + yOff)
|
|
||||||
val tileInWorld = out.unsafeGetTile(x, y)
|
|
||||||
world.layerTerrain.unsafeSetTile(x, y, tileInWorld)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +155,7 @@ object ExplosionManager {
|
|||||||
CALC_RADIUS: Int, CALC_WIDTH: Int,
|
CALC_RADIUS: Int, CALC_WIDTH: Int,
|
||||||
world: GameWorld,
|
world: GameWorld,
|
||||||
breakmap: UnsafeFloatArray,
|
breakmap: UnsafeFloatArray,
|
||||||
tilemap: BlockLayerInMemoryI16,
|
tilemap: BlockLayerGenericI16,
|
||||||
tx: Int, ty: Int,
|
tx: Int, ty: Int,
|
||||||
power: Float,
|
power: Float,
|
||||||
dropProbNonOre: Float,
|
dropProbNonOre: Float,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
|||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
|
import net.torvald.terrarum.blockproperties.FluidCodex
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.METER
|
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.METER
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.PHYS_EPSILON_DIST
|
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.PHYS_EPSILON_DIST
|
||||||
@@ -27,7 +28,6 @@ import net.torvald.terrarum.gameitems.GameItem
|
|||||||
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||||
import net.torvald.terrarum.modulebasegame.gameitems.ItemThrowable
|
import net.torvald.terrarum.modulebasegame.gameitems.ItemThrowable
|
||||||
@@ -44,6 +44,8 @@ import kotlin.math.min
|
|||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will be rendered to a postprocessor FBO.
|
* This will be rendered to a postprocessor FBO.
|
||||||
*
|
*
|
||||||
@@ -129,7 +131,7 @@ object IngameRenderer : Disposable {
|
|||||||
//var renderingParticleCount = 0
|
//var renderingParticleCount = 0
|
||||||
// private set
|
// private set
|
||||||
|
|
||||||
var world: GameWorld = TheGameWorld.makeNullWorld()
|
var world: GameWorld = GameWorld.makeNullWorld()
|
||||||
private set // the grammar "IngameRenderer.world = gameWorld" seemes mundane and this function needs special care!
|
private set // the grammar "IngameRenderer.world = gameWorld" seemes mundane and this function needs special care!
|
||||||
|
|
||||||
private var newWorldLoadedLatch = false
|
private var newWorldLoadedLatch = false
|
||||||
@@ -391,16 +393,11 @@ object IngameRenderer : Disposable {
|
|||||||
|
|
||||||
blendNormalStraightAlpha(batch)
|
blendNormalStraightAlpha(batch)
|
||||||
|
|
||||||
val (vo, vg) = if (world is TheGameWorld) {
|
val (vo, vg) = world.weatherbox.let {
|
||||||
(world as TheGameWorld).weatherbox.let {
|
if (it.currentWeather.identifier == "titlescreen")
|
||||||
if (it.currentWeather.identifier == "titlescreen")
|
1f to 1f
|
||||||
1f to 1f
|
else
|
||||||
else
|
it.currentVibrancy.x to it.currentVibrancy.y
|
||||||
it.currentVibrancy.x to it.currentVibrancy.y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
1f to 1f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mixedOutTex.texture.bind(0)
|
mixedOutTex.texture.bind(0)
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import net.torvald.terrarum.gameitems.GameItem
|
|||||||
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
import net.torvald.terrarum.modulebasegame.gameactors.*
|
||||||
@@ -47,7 +46,6 @@ import net.torvald.terrarum.modulebasegame.worldgenerator.WorldgenParams
|
|||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
||||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
|
||||||
import net.torvald.terrarum.savegame.VDUtil
|
import net.torvald.terrarum.savegame.VDUtil
|
||||||
import net.torvald.terrarum.savegame.VirtualDisk
|
import net.torvald.terrarum.savegame.VirtualDisk
|
||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
@@ -350,7 +348,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
data class Codices(
|
data class Codices(
|
||||||
val disk: VirtualDisk, // WORLD disk
|
val disk: VirtualDisk, // WORLD disk
|
||||||
val world: TheGameWorld,
|
val world: GameWorld,
|
||||||
// val meta: WriteMeta.WorldMeta,
|
// val meta: WriteMeta.WorldMeta,
|
||||||
// val block: BlockCodex,
|
// val block: BlockCodex,
|
||||||
// val item: ItemCodex,
|
// val item: ItemCodex,
|
||||||
@@ -385,8 +383,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
// feed info to the worldgen
|
// feed info to the worldgen
|
||||||
if (world is TheGameWorld)
|
Worldgen.attachMap(world, WorldgenParams.getParamsByVersion(codices.worldGenver, world.generatorSeed))
|
||||||
Worldgen.attachMap(world as TheGameWorld, WorldgenParams.getParamsByVersion(codices.worldGenver, world.generatorSeed))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadCallback = codices.callbackAfterLoad
|
loadCallback = codices.callbackAfterLoad
|
||||||
@@ -446,6 +443,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// try to unstuck the repositioned player
|
// try to unstuck the repositioned player
|
||||||
codices.player.tryUnstuck()
|
codices.player.tryUnstuck()
|
||||||
|
|
||||||
@@ -522,18 +520,13 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
App.getLoadScreen().addMessage("${App.GAME_NAME} ${App.getVERSION_STRING()}")
|
App.getLoadScreen().addMessage("${App.GAME_NAME} ${App.getVERSION_STRING()}")
|
||||||
|
|
||||||
App.getLoadScreen().addMessage("Creating new world")
|
App.getLoadScreen().addMessage("Creating new world")
|
||||||
|
|
||||||
|
|
||||||
val worldFile = getWorldSaveFiledesc(worldSavefileName)
|
|
||||||
VDUtil.dumpToRealMachine(worldDisk, worldFile)
|
|
||||||
val skimmer = DiskSkimmer(worldFile)
|
|
||||||
|
|
||||||
// init map as chosen size
|
// init map as chosen size
|
||||||
val timeNow = App.getTIME_T()
|
val timeNow = App.getTIME_T()
|
||||||
|
world = GameWorld(worldParams.width, worldParams.height, timeNow, timeNow) // new game, so the creation time is right now
|
||||||
world = TheGameWorld(worldParams.width, worldParams.height, skimmer, timeNow, timeNow) // new game, so the creation time is right now
|
|
||||||
|
|
||||||
world.generatorSeed = worldParams.worldGenSeed
|
world.generatorSeed = worldParams.worldGenSeed
|
||||||
//gameworldIndices.add(world.worldIndex)
|
//gameworldIndices.add(world.worldIndex)
|
||||||
world.extraFields["basegame.economy"] = GameEconomy()
|
world.extraFields["basegame.economy"] = GameEconomy()
|
||||||
|
|||||||
@@ -24,15 +24,18 @@ import net.torvald.terrarum.gameactors.ai.ActorAI
|
|||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.*
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
|
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
|
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.serialise.ReadTitlescreenGameWorld
|
import net.torvald.terrarum.serialise.ReadSimpleWorld
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
|
import net.torvald.terrarum.ui.UIItemTextButton
|
||||||
import net.torvald.terrarum.utils.OpenURL
|
import net.torvald.terrarum.utils.OpenURL
|
||||||
import net.torvald.terrarum.weather.WeatherMixer
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
@@ -66,7 +69,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
//private var loadDone = false // not required; draw-while-loading is implemented in the AppLoader
|
//private var loadDone = false // not required; draw-while-loading is implemented in the AppLoader
|
||||||
|
|
||||||
private lateinit var demoWorld: TitlescreenGameWorld
|
private lateinit var demoWorld: GameWorld
|
||||||
private lateinit var cameraNodes: FloatArray // camera Y-pos
|
private lateinit var cameraNodes: FloatArray // camera Y-pos
|
||||||
private val cameraNodeWidth = 15
|
private val cameraNodeWidth = 15
|
||||||
private val lookaheadDist = cameraNodeWidth * TILE_SIZED
|
private val lookaheadDist = cameraNodeWidth * TILE_SIZED
|
||||||
@@ -162,19 +165,19 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
val file = ModMgr.getFile("basegame", "demoworld")
|
val file = ModMgr.getFile("basegame", "demoworld")
|
||||||
val reader = java.io.FileReader(file)
|
val reader = java.io.FileReader(file)
|
||||||
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
||||||
val world = ReadTitlescreenGameWorld(reader, file)
|
val world = ReadSimpleWorld(reader, file)
|
||||||
demoWorld = world
|
demoWorld = world
|
||||||
demoWorld.worldTime.timeDelta = 30
|
demoWorld.worldTime.timeDelta = 30
|
||||||
printdbg(this, "Demo world loaded")
|
printdbg(this, "Demo world loaded")
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
demoWorld = TitlescreenGameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H)
|
demoWorld = GameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H, 0L, 0L)
|
||||||
demoWorld.worldTime.timeDelta = 30
|
demoWorld.worldTime.timeDelta = 30
|
||||||
printdbg(this, "Demo world not found, using empty world")
|
printdbg(this, "Demo world not found, using empty world")
|
||||||
}
|
}
|
||||||
|
|
||||||
this.world = demoWorld
|
|
||||||
demoWorld.renumberTilesAfterLoad()
|
demoWorld.renumberTilesAfterLoad()
|
||||||
|
this.world = demoWorld
|
||||||
|
|
||||||
// set initial time to summer
|
// set initial time to summer
|
||||||
demoWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
demoWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
||||||
@@ -362,7 +365,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
gdxClearAndEnableBlend(.64f, .754f, .84f, 1f)
|
gdxClearAndEnableBlend(.64f, .754f, .84f, 1f)
|
||||||
|
|
||||||
|
|
||||||
if (!demoWorld.disposed) { // FIXME q&d hack to circumvent the dangling pointer issue #26
|
if (!demoWorld.layerTerrain.ptr.destroyed) { // FIXME q&d hack to circumvent the dangling pointer issue #26
|
||||||
WorldCamera.update(demoWorld, cameraPlayer)
|
WorldCamera.update(demoWorld, cameraPlayer)
|
||||||
|
|
||||||
IngameRenderer.invoke(
|
IngameRenderer.invoke(
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import net.torvald.terrarum.gameactors.Controllable
|
|||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame.Companion.inUpdateRange
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame.Companion.inUpdateRange
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
import net.torvald.terrarum.modulebasegame.gameactors.*
|
||||||
import net.torvald.terrarum.modulebasegame.gameitems.AxeCore
|
import net.torvald.terrarum.modulebasegame.gameitems.AxeCore
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import com.badlogic.gdx.graphics.Pixmap
|
|||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@@ -97,7 +96,7 @@ class WorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidt
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// q&d solution for the dangling pointer; i'm doing this only because it's this fucking load screen that's fucking the dead pointer
|
// q&d solution for the dangling pointer; i'm doing this only because it's this fucking load screen that's fucking the dead pointer
|
||||||
if (!world.layerTerrain.disposed) {
|
if (!world.layerTerrain.ptrDestroyed) {
|
||||||
val outCol = if (BlockCodex[world.getTileFromTerrain(wx, wy)].isSolid) COL_TERR
|
val outCol = if (BlockCodex[world.getTileFromTerrain(wx, wy)].isSolid) COL_TERR
|
||||||
else if (BlockCodex[world.getTileFromWall(wx, wy)].isSolid) COL_WALLED
|
else if (BlockCodex[world.getTileFromWall(wx, wy)].isSolid) COL_WALLED
|
||||||
else COL_AIR
|
else COL_AIR
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import net.torvald.terrarum.App
|
|||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.console.ConsoleCommand
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
import net.torvald.terrarum.console.Echo
|
import net.torvald.terrarum.console.Echo
|
||||||
import net.torvald.terrarum.gameworld.TitlescreenGameWorld
|
import net.torvald.terrarum.gameworld.SimpleGameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.serialise.WriteTitlescreenGameWorld
|
import net.torvald.terrarum.serialise.WriteSimpleWorld
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
@@ -21,12 +21,12 @@ object ExportWorld : ConsoleCommand {
|
|||||||
try {
|
try {
|
||||||
val ingame = Terrarum.ingame!! as TerrarumIngame
|
val ingame = Terrarum.ingame!! as TerrarumIngame
|
||||||
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
|
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
|
||||||
val simpleworld = TitlescreenGameWorld(ingame.world.width, ingame.world.height).also {
|
val simpleworld = SimpleGameWorld(ingame.world.width, ingame.world.height).also {
|
||||||
it.layerTerrain = ingame.world.layerTerrain
|
it.layerTerrain = ingame.world.layerTerrain
|
||||||
it.layerWall = ingame.world.layerWall
|
it.layerWall = ingame.world.layerWall
|
||||||
it.tileNumberToNameMap.putAll(ingame.world.tileNumberToNameMap)
|
it.tileNumberToNameMap.putAll(ingame.world.tileNumberToNameMap)
|
||||||
}
|
}
|
||||||
file.writeText(WriteTitlescreenGameWorld(ingame, simpleworld, listOf()))
|
file.writeText(WriteSimpleWorld(ingame, simpleworld, listOf()))
|
||||||
Echo("Exportworld: exported the world as ${args[1]}.json")
|
Echo("Exportworld: exported the world as ${args[1]}.json")
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import net.torvald.terrarum.Terrarum
|
|||||||
import net.torvald.terrarum.console.ConsoleCommand
|
import net.torvald.terrarum.console.ConsoleCommand
|
||||||
import net.torvald.terrarum.console.Echo
|
import net.torvald.terrarum.console.Echo
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.serialise.ReadTitlescreenGameWorld
|
import net.torvald.terrarum.serialise.ReadSimpleWorld
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ object ImportWorld : ConsoleCommand {
|
|||||||
try {
|
try {
|
||||||
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
|
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
|
||||||
val reader = java.io.FileReader(file)
|
val reader = java.io.FileReader(file)
|
||||||
ReadTitlescreenGameWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader, file)
|
ReadSimpleWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader, file)
|
||||||
Echo("Importworld: imported a world from ${args[1]}.json")
|
Echo("Importworld: imported a world from ${args[1]}.json")
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.gameactors
|
package net.torvald.terrarum.modulebasegame.gameactors
|
||||||
|
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.gameactors.ActorID
|
import net.torvald.terrarum.gameactors.ActorID
|
||||||
import net.torvald.terrarum.gameactors.PhysProperties
|
import net.torvald.terrarum.gameactors.PhysProperties
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
@@ -16,7 +17,7 @@ open class Electric : FixtureBase {
|
|||||||
|
|
||||||
protected constructor() : super() {
|
protected constructor() : super() {
|
||||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
// newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,7 +46,7 @@ open class Electric : FixtureBase {
|
|||||||
App.disposables.add(mainUI)
|
App.disposables.add(mainUI)
|
||||||
|
|
||||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
// newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -137,7 +138,7 @@ open class Electric : FixtureBase {
|
|||||||
getWireEmissionAt(offsetX, offsetY).x <= ELECTRIC_THRESHOLD_LOW
|
getWireEmissionAt(offsetX, offsetY).x <= ELECTRIC_THRESHOLD_LOW
|
||||||
|
|
||||||
protected var oldSinkStatus: Array<Vector2>
|
protected var oldSinkStatus: Array<Vector2>
|
||||||
protected var newSinkStatus: Array<Vector2>
|
// protected var newSinkStatus: Array<Vector2>
|
||||||
|
|
||||||
open fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {
|
open fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {
|
||||||
val index = pointToBlockBoxIndex(offsetX, offsetY)
|
val index = pointToBlockBoxIndex(offsetX, offsetY)
|
||||||
@@ -149,9 +150,6 @@ open class Electric : FixtureBase {
|
|||||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
oldSinkStatus[index].set(new2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -167,35 +165,35 @@ open class Electric : FixtureBase {
|
|||||||
for (x in 0 until blockBox.width) {
|
for (x in 0 until blockBox.width) {
|
||||||
// get indices of "rising edges"
|
// get indices of "rising edges"
|
||||||
// get indices of "falling edges"
|
// get indices of "falling edges"
|
||||||
|
|
||||||
val wx = x + worldBlockPos!!.x
|
|
||||||
val wy = y + worldBlockPos!!.y
|
|
||||||
val new = WireCodex.getAllWiresThatAccepts(getWireSinkAt(x, y) ?: "").fold(Vector2()) { acc, (id, _) ->
|
|
||||||
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
|
||||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val index = pointToBlockBoxIndex(x, y)
|
val index = pointToBlockBoxIndex(x, y)
|
||||||
|
val type = getWireSinkAt(index) ?: ""
|
||||||
|
|
||||||
if (new.x - oldSinkStatus[index].x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x >= ELECTRIC_THRESHOLD_HIGH)
|
if (type.isNotBlank()) {
|
||||||
risingEdgeIndices.add(index)
|
val old = oldSinkStatus[index]
|
||||||
else if (oldSinkStatus[index].x - new.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x <= ELECTRIC_THRESHOLD_LOW)
|
val new = getWireStateAt(x, y, type)
|
||||||
fallingEdgeIndices.add(index)
|
|
||||||
|
val wx = x + worldBlockPos!!.x
|
||||||
|
val wy = y + worldBlockPos!!.y
|
||||||
|
|
||||||
|
// println("Wxy($wx,$wy) getWireState($type)=$new, oldState($type)=$old")
|
||||||
|
|
||||||
|
if (new.x - old.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x >= ELECTRIC_THRESHOLD_HIGH)
|
||||||
|
risingEdgeIndices.add(index)
|
||||||
|
else if (old.x - new.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x <= ELECTRIC_THRESHOLD_LOW)
|
||||||
|
fallingEdgeIndices.add(index)
|
||||||
|
|
||||||
|
|
||||||
oldSinkStatus[index].set(new)
|
oldSinkStatus[index].set(new)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (risingEdgeIndices.isNotEmpty()) {
|
||||||
|
// println("risingEdgeIndices=$risingEdgeIndices")
|
||||||
|
// }
|
||||||
|
|
||||||
risingEdgeIndices.forEach { onRisingEdge(it) }
|
risingEdgeIndices.forEach { onRisingEdge(it) }
|
||||||
fallingEdgeIndices.forEach { onFallingEdge(it) }
|
fallingEdgeIndices.forEach { onFallingEdge(it) }
|
||||||
updateSignal()
|
updateSignal()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*oldSinkStatus.indices.forEach { index ->
|
|
||||||
oldSinkStatus[index].set(new)
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ class FixtureTextSignCopper : Electric {
|
|||||||
blockBox = BlockBox(BlockBox.NO_COLLISION, panelCount, 2)
|
blockBox = BlockBox(BlockBox.NO_COLLISION, panelCount, 2)
|
||||||
setHitboxDimension(TILE_SIZE * blockBox.width, TILE_SIZE * blockBox.height, 0, 2)
|
setHitboxDimension(TILE_SIZE * blockBox.width, TILE_SIZE * blockBox.height, 0, 2)
|
||||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
// newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// must be re-spawned on reload to make it visible after load
|
// must be re-spawned on reload to make it visible after load
|
||||||
|
|||||||
@@ -62,10 +62,12 @@ class FixtureWorldPortal : Electric {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onRisingEdge(readFrom: BlockBoxIndex) {
|
override fun onRisingEdge(readFrom: BlockBoxIndex) {
|
||||||
|
// printdbg(this, "readFrom=$readFrom; getWireSinkAt(readFrom)=${getWireSinkAt(readFrom)}")
|
||||||
|
|
||||||
if (getWireSinkAt(readFrom) != "digital_bit") return
|
if (getWireSinkAt(readFrom) != "digital_bit") return
|
||||||
|
|
||||||
|
|
||||||
printdbg(this, "teleport! $teleportRequest")
|
// printdbg(this, "teleport! $teleportRequest")
|
||||||
teleportRequest?.let {
|
teleportRequest?.let {
|
||||||
if (it.worldDiskToLoad != null && it.worldLoadParam != null) {
|
if (it.worldDiskToLoad != null && it.worldLoadParam != null) {
|
||||||
throw InternalError("Contradiction -- worldDiskToLoad and worldLoadParam are both not null: $teleportRequest")
|
throw InternalError("Contradiction -- worldDiskToLoad and worldLoadParam are both not null: $teleportRequest")
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import net.torvald.terrarum.gameitems.ItemID
|
|||||||
import net.torvald.terrarum.gameitems.isWall
|
import net.torvald.terrarum.gameitems.isWall
|
||||||
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.serialise
|
package net.torvald.terrarum.modulebasegame.serialise
|
||||||
|
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
|
||||||
import net.torvald.terrarum.console.Echo
|
import net.torvald.terrarum.console.Echo
|
||||||
import net.torvald.terrarum.gameworld.*
|
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||||
import net.torvald.terrarum.gameworld.ChunkPool.Companion.chunkOffsetsNearPlayer
|
import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
import net.torvald.terrarum.gameworld.BlockLayerOresI16I8
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.ORES
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.FancyWorldReadLoadScreen
|
import net.torvald.terrarum.modulebasegame.FancyWorldReadLoadScreen
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
@@ -16,7 +13,6 @@ import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
|||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.savegame.*
|
import net.torvald.terrarum.savegame.*
|
||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
import org.dyn4j.geometry.Vector2
|
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
import kotlin.experimental.or
|
import kotlin.experimental.or
|
||||||
@@ -64,10 +60,11 @@ object LoadSavegame {
|
|||||||
val worldDiskSavegameInfo = ByteArray64Reader(worldDisk.getFile(VDFileID.SAVEGAMEINFO)!!.bytes, Common.CHARSET)
|
val worldDiskSavegameInfo = ByteArray64Reader(worldDisk.getFile(VDFileID.SAVEGAMEINFO)!!.bytes, Common.CHARSET)
|
||||||
val world = ReadWorld(worldDiskSavegameInfo, worldDisk.diskFile)
|
val world = ReadWorld(worldDiskSavegameInfo, worldDisk.diskFile)
|
||||||
|
|
||||||
world.layerTerrain = BlockLayerGenericI16(world.width, world.height, worldDisk, TERRAIN, world)
|
|
||||||
world.layerWall = BlockLayerGenericI16(world.width, world.height, worldDisk, WALL, world)
|
world.layerTerrain = BlockLayerGenericI16(world.width, world.height)
|
||||||
world.layerOres = BlockLayerOresI16I8(world.width, world.height, worldDisk, ORES, world)
|
world.layerWall = BlockLayerGenericI16(world.width, world.height)
|
||||||
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height, worldDisk, FLUID, world)
|
world.layerOres = BlockLayerOresI16I8(world.width, world.height)
|
||||||
|
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height)
|
||||||
world.chunkFlags = Array(world.height / LandUtil.CHUNK_H) { ByteArray(world.width / LandUtil.CHUNK_W) }
|
world.chunkFlags = Array(world.height / LandUtil.CHUNK_H) { ByteArray(world.width / LandUtil.CHUNK_W) }
|
||||||
|
|
||||||
newIngame.world = world // must be set before the loadscreen, otherwise the loadscreen will try to read from the NullWorld which is already destroyed
|
newIngame.world = world // must be set before the loadscreen, otherwise the loadscreen will try to read from the NullWorld which is already destroyed
|
||||||
@@ -122,24 +119,12 @@ object LoadSavegame {
|
|||||||
val (cx, cy) = LandUtil.chunkNumToChunkXY(world, chunk)
|
val (cx, cy) = LandUtil.chunkNumToChunkXY(world, chunk)
|
||||||
|
|
||||||
ReadWorld.decodeChunkToLayer(chunkFile.getContent(), worldLayer[layer]!!, cx, cy)
|
ReadWorld.decodeChunkToLayer(chunkFile.getContent(), worldLayer[layer]!!, cx, cy)
|
||||||
world.chunkFlags[cy][cx] = world.chunkFlags[cy][cx] or TheGameWorld.CHUNK_LOADED
|
world.chunkFlags[cy][cx] = world.chunkFlags[cy][cx] or GameWorld.CHUNK_LOADED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadscreen.progress.getAndAdd(1)
|
loadscreen.progress.getAndAdd(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val playerChunk = player.hitbox.canonVec.let {
|
|
||||||
(it.x / (cw * TILE_SIZED)).toInt() to (it.y / (ch * TILE_SIZED)).toInt()
|
|
||||||
}.let { Point2i(it.first, it.second) }
|
|
||||||
|
|
||||||
val chunksToLoad = chunkOffsetsNearPlayer.map {
|
|
||||||
playerChunk + it
|
|
||||||
} + playerChunk
|
|
||||||
|
|
||||||
/*for (layer in worldLayer) {
|
|
||||||
(layer as? BlockLayerWithChunkPool)?.chunkPool?.
|
|
||||||
}*/
|
|
||||||
|
|
||||||
loadscreen.addMessage(Lang["MENU_IO_LOAD_UPDATING_BLOCK_MAPPINGS"])
|
loadscreen.addMessage(Lang["MENU_IO_LOAD_UPDATING_BLOCK_MAPPINGS"])
|
||||||
world.renumberTilesAfterLoad()
|
world.renumberTilesAfterLoad()
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import net.torvald.gdx.graphics.PixmapIO2
|
|||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration
|
import net.torvald.terrarum.TerrarumAppConfiguration
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
@@ -119,7 +118,7 @@ class QuickSingleplayerWorldSavingThread(
|
|||||||
|
|
||||||
// println("Chunk xy from number $chunkNumber -> (${chunkXY.x}, ${chunkXY.y})")
|
// println("Chunk xy from number $chunkNumber -> (${chunkXY.x}, ${chunkXY.y})")
|
||||||
|
|
||||||
if (chunkFlag and 0x7F == TheGameWorld.CHUNK_LOADED) {
|
if (chunkFlag and 0x7F == GameWorld.CHUNK_LOADED) {
|
||||||
val chunkBytes = WriteWorld.encodeChunk(layer, cx, cy)
|
val chunkBytes = WriteWorld.encodeChunk(layer, cx, cy)
|
||||||
val entryID = 0x1_0000_0000L or layerNum.toLong().shl(24) or chunkNumber.toLong()
|
val entryID = 0x1_0000_0000L or layerNum.toLong().shl(24) or chunkNumber.toLong()
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package net.torvald.terrarum.modulebasegame.serialise
|
|||||||
|
|
||||||
import net.torvald.gdx.graphics.PixmapIO2
|
import net.torvald.gdx.graphics.PixmapIO2
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.CHUNK_LOADED
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.ORES
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.ORES
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld.Companion.CHUNK_LOADED
|
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import net.torvald.terrarum.gameactors.Actor
|
|||||||
import net.torvald.terrarum.gameactors.NoSerialise
|
import net.torvald.terrarum.gameactors.NoSerialise
|
||||||
import net.torvald.terrarum.gameworld.BlockLayer
|
import net.torvald.terrarum.gameworld.BlockLayer
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
|
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
|
||||||
@@ -96,12 +95,12 @@ object WriteWorld {
|
|||||||
*/
|
*/
|
||||||
object ReadWorld {
|
object ReadWorld {
|
||||||
|
|
||||||
operator fun invoke(worldDataStream: Reader, origin: File?): TheGameWorld =
|
operator fun invoke(worldDataStream: Reader, origin: File?): GameWorld =
|
||||||
Common.jsoner.fromJson(TheGameWorld::class.java, worldDataStream).also {
|
Common.jsoner.fromJson(GameWorld::class.java, worldDataStream).also {
|
||||||
fillInDetails(origin, it)
|
fillInDetails(origin, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fillInDetails(origin: File?, world: TheGameWorld) {
|
private fun fillInDetails(origin: File?, world: GameWorld) {
|
||||||
world.tileNumberToNameMap.forEach { l, s ->
|
world.tileNumberToNameMap.forEach { l, s ->
|
||||||
world.tileNameToNumberMap[s] = l.toInt()
|
world.tileNameToNumberMap[s] = l.toInt()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ class UIWorldPortalSearch(val full: UIWorldPortal) : UICanvas() {
|
|||||||
|
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
|
clearTooltip()
|
||||||
uiItems.forEach { it.show() }
|
uiItems.forEach { it.show() }
|
||||||
seedInput.clearText()
|
seedInput.clearText()
|
||||||
seedInput.refreshPlaceholder()
|
seedInput.refreshPlaceholder()
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import net.torvald.terrarum.serialise.toBig64
|
|||||||
import net.torvald.terrarum.toInt
|
import net.torvald.terrarum.toInt
|
||||||
import net.torvald.terrarum.utils.OrePlacement
|
import net.torvald.terrarum.utils.OrePlacement
|
||||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-10-26.
|
* Created by minjaesong on 2023-10-26.
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import net.torvald.terrarum.blockproperties.Block
|
|||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
@@ -164,14 +163,14 @@ object Worldgen {
|
|||||||
val jobs = getJobs()
|
val jobs = getJobs()
|
||||||
printdbg(this, "Generating chunk on ($cx, $cy)")
|
printdbg(this, "Generating chunk on ($cx, $cy)")
|
||||||
Thread {
|
Thread {
|
||||||
world.chunkFlags[cy][cx] = TheGameWorld.CHUNK_GENERATING
|
world.chunkFlags[cy][cx] = GameWorld.CHUNK_GENERATING
|
||||||
|
|
||||||
for (i in jobs.indices) {
|
for (i in jobs.indices) {
|
||||||
val it = jobs[i]
|
val it = jobs[i]
|
||||||
it.theWork.getChunkDone(cx, cy)
|
it.theWork.getChunkDone(cx, cy)
|
||||||
}
|
}
|
||||||
|
|
||||||
world.chunkFlags[cy][cx] = TheGameWorld.CHUNK_LOADED
|
world.chunkFlags[cy][cx] = GameWorld.CHUNK_LOADED
|
||||||
callback(cx, cy)
|
callback(cx, cy)
|
||||||
}.let {
|
}.let {
|
||||||
it.priority = 2
|
it.priority = 2
|
||||||
@@ -567,7 +566,7 @@ abstract class Gen(val world: GameWorld, val isFinal: Boolean, val seed: Long, v
|
|||||||
draw(chunkX * LandUtil.CHUNK_W, chunkY * CHUNK_H, localJoise, sampleOffset)
|
draw(chunkX * LandUtil.CHUNK_W, chunkY * CHUNK_H, localJoise, sampleOffset)
|
||||||
loadscreen?.progress?.addAndGet(1L)
|
loadscreen?.progress?.addAndGet(1L)
|
||||||
|
|
||||||
world.chunkFlags[chunkY][chunkX] = if (isFinal) TheGameWorld.CHUNK_LOADED else TheGameWorld.CHUNK_GENERATING
|
world.chunkFlags[chunkY][chunkX] = if (isFinal) GameWorld.CHUNK_LOADED else GameWorld.CHUNK_GENERATING
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,8 @@ import io.airlift.compress.zstd.ZstdOutputStream
|
|||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.console.EchoError
|
import net.torvald.terrarum.console.EchoError
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
|
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.gameworld.WorldTime
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
import net.torvald.terrarum.savegame.ByteArray64
|
import net.torvald.terrarum.savegame.ByteArray64
|
||||||
import net.torvald.terrarum.savegame.ByteArray64GrowableOutputStream
|
import net.torvald.terrarum.savegame.ByteArray64GrowableOutputStream
|
||||||
@@ -42,7 +41,7 @@ object Common {
|
|||||||
val CHARSET = Charsets.UTF_8
|
val CHARSET = Charsets.UTF_8
|
||||||
|
|
||||||
/** dispose of the `offendingObject` after rejection! */
|
/** dispose of the `offendingObject` after rejection! */
|
||||||
class BlockLayerHashMismatchError(val oldHash: String, val newHash: String, val offendingObject: BlockLayerInMemoryI16) : Error("Old Hash $oldHash != New Hash $newHash")
|
class BlockLayerHashMismatchError(val oldHash: String, val newHash: String, val offendingObject: BlockLayerGenericI16) : Error("Old Hash $oldHash != New Hash $newHash")
|
||||||
|
|
||||||
private fun Byte.tostr() = this.toInt().and(255).toString(16).padStart(2,'0')
|
private fun Byte.tostr() = this.toInt().and(255).toString(16).padStart(2,'0')
|
||||||
private val digester = DigestUtils.getSha256Digest()
|
private val digester = DigestUtils.getSha256Digest()
|
||||||
@@ -75,8 +74,8 @@ object Common {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
// BlockLayer
|
// BlockLayer
|
||||||
it.setSerializer(BlockLayerInMemoryI16::class.java, object : Json.Serializer<BlockLayerInMemoryI16> {
|
it.setSerializer(BlockLayerGenericI16::class.java, object : Json.Serializer<BlockLayerGenericI16> {
|
||||||
override fun write(json: Json, obj: BlockLayerInMemoryI16, knownType: Class<*>?) {
|
override fun write(json: Json, obj: BlockLayerGenericI16, knownType: Class<*>?) {
|
||||||
digester.reset()
|
digester.reset()
|
||||||
obj.bytesIterator().forEachRemaining { digester.update(it) }
|
obj.bytesIterator().forEachRemaining { digester.update(it) }
|
||||||
val hash = StringBuilder().let { sb -> digester.digest().forEach { sb.append(it.tostr()) }; sb.toString() }
|
val hash = StringBuilder().let { sb -> digester.digest().forEach { sb.append(it.tostr()) }; sb.toString() }
|
||||||
@@ -86,7 +85,7 @@ object Common {
|
|||||||
json.writeValue(layer)
|
json.writeValue(layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun read(json: Json, jsonData: JsonValue, type: Class<*>): BlockLayerInMemoryI16 {
|
override fun read(json: Json, jsonData: JsonValue, type: Class<*>): BlockLayerGenericI16 {
|
||||||
// full manual
|
// full manual
|
||||||
try {
|
try {
|
||||||
return strToBlockLayer(LayerInfo(
|
return strToBlockLayer(LayerInfo(
|
||||||
@@ -436,12 +435,12 @@ object Common {
|
|||||||
* @param b a BlockLayer
|
* @param b a BlockLayer
|
||||||
* @return Bytes in [b] which are GZip'd then Ascii85-encoded
|
* @return Bytes in [b] which are GZip'd then Ascii85-encoded
|
||||||
*/
|
*/
|
||||||
private fun blockLayerToStr(b: BlockLayerInMemoryI16): String {
|
private fun blockLayerToStr(b: BlockLayerGenericI16): String {
|
||||||
return bytesToZipdStr(b.bytesIterator())
|
return bytesToZipdStr(b.bytesIterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayerInMemoryI16 {
|
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayerGenericI16 {
|
||||||
val layer = BlockLayerInMemoryI16(layerInfo.x, layerInfo.y)
|
val layer = BlockLayerGenericI16(layerInfo.x, layerInfo.y)
|
||||||
val unzipdBytes = strToBytes(StringReader(layerInfo.b))
|
val unzipdBytes = strToBytes(StringReader(layerInfo.b))
|
||||||
|
|
||||||
// write to blocklayer and the digester
|
// write to blocklayer and the digester
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import net.torvald.terrarum.TerrarumAppConfiguration
|
|||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
|
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||||
@@ -129,7 +128,7 @@ class POILayer(
|
|||||||
constructor() : this("undefined")
|
constructor() : this("undefined")
|
||||||
|
|
||||||
@Transient var name = name
|
@Transient var name = name
|
||||||
@Transient internal lateinit var blockLayer: ArrayList<BlockLayerInMemoryI16>
|
@Transient internal lateinit var blockLayer: ArrayList<BlockLayerGenericI16>
|
||||||
@Transient internal lateinit var dat: Array<ByteArray>
|
@Transient internal lateinit var dat: Array<ByteArray>
|
||||||
|
|
||||||
@Deprecated("Used for debug print", ReplaceWith("name")) @Transient internal var id = ""
|
@Deprecated("Used for debug print", ReplaceWith("name")) @Transient internal var id = ""
|
||||||
@@ -180,10 +179,10 @@ class POILayer(
|
|||||||
if (::blockLayer.isInitialized) {
|
if (::blockLayer.isInitialized) {
|
||||||
blockLayer.forEach { it.dispose() }
|
blockLayer.forEach { it.dispose() }
|
||||||
}
|
}
|
||||||
blockLayer = ArrayList()
|
blockLayer = ArrayList<BlockLayerGenericI16>()
|
||||||
|
|
||||||
dat.forEachIndexed { layerIndex, layer ->
|
dat.forEachIndexed { layerIndex, layer ->
|
||||||
val currentBlockLayer = BlockLayerInMemoryI16(width, height).also {
|
val currentBlockLayer = BlockLayerGenericI16(width, height).also {
|
||||||
blockLayer.add(it)
|
blockLayer.add(it)
|
||||||
}
|
}
|
||||||
for (w in 0 until layer.size / byteLength) {
|
for (w in 0 until layer.size / byteLength) {
|
||||||
|
|||||||
@@ -4,53 +4,56 @@ import net.torvald.terrarum.App
|
|||||||
import net.torvald.terrarum.IngameInstance
|
import net.torvald.terrarum.IngameInstance
|
||||||
import net.torvald.terrarum.ItemCodex
|
import net.torvald.terrarum.ItemCodex
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameworld.*
|
import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.gameworld.BlockLayerOresI16I8
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.SimpleGameWorld
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2022-09-03.
|
* Created by minjaesong on 2022-09-03.
|
||||||
*/
|
*/
|
||||||
object ReadTitlescreenGameWorld {
|
object ReadSimpleWorld {
|
||||||
|
|
||||||
operator fun invoke(worldDataStream: Reader, origin: File?): TitlescreenGameWorld =
|
operator fun invoke(worldDataStream: Reader, origin: File?): GameWorld =
|
||||||
Common.jsoner.fromJson(TitlescreenGameWorld::class.java, worldDataStream).also {
|
Common.jsoner.fromJson(SimpleGameWorld::class.java, worldDataStream).also {
|
||||||
fillInDetails(origin, it)
|
fillInDetails(origin, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fillInDetails(origin: File?, world: TitlescreenGameWorld) {
|
private fun fillInDetails(origin: File?, world: GameWorld) {
|
||||||
world.tileNumberToNameMap.forEach { l, s ->
|
world.tileNumberToNameMap.forEach { l, s ->
|
||||||
world.tileNameToNumberMap[s] = l.toInt()
|
world.tileNameToNumberMap[s] = l.toInt()
|
||||||
}
|
}
|
||||||
world.layerOres = BlockLayerInMemoryI16I8(world.width, world.height)
|
world.layerOres = BlockLayerOresI16I8(world.width, world.height)
|
||||||
world.layerFluids = BlockLayerInMemoryI16F16(world.width, world.height)
|
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height)
|
||||||
|
|
||||||
ItemCodex.loadFromSave(origin, world.dynamicToStaticTable, world.dynamicItemInventory)
|
ItemCodex.loadFromSave(origin, world.dynamicToStaticTable, world.dynamicItemInventory)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readWorldAndSetNewWorld(ingame: IngameInstance, worldDataStream: Reader, origin: File?): TitlescreenGameWorld {
|
fun readWorldAndSetNewWorld(ingame: IngameInstance, worldDataStream: Reader, origin: File?): GameWorld {
|
||||||
val world = invoke(worldDataStream, origin)
|
val world = invoke(worldDataStream, origin)
|
||||||
ingame.world = world
|
ingame.world = world
|
||||||
|
|
||||||
return world
|
return world
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
object WriteTitlescreenGameWorld {
|
object WriteSimpleWorld {
|
||||||
|
|
||||||
private fun preWrite(ingame: IngameInstance, time_t: Long, world: TitlescreenGameWorld, actorsList: List<Actor>) {
|
private fun preWrite(ingame: IngameInstance, time_t: Long, world: SimpleGameWorld, actorsList: List<Actor>) {
|
||||||
val currentPlayTime_t = time_t - ingame.loadedTime_t
|
val currentPlayTime_t = time_t - ingame.loadedTime_t
|
||||||
|
|
||||||
world.comp = Common.getCompIndex()
|
world.comp = Common.getCompIndex()
|
||||||
|
world.lastPlayTime = time_t
|
||||||
|
world.totalPlayTime += currentPlayTime_t
|
||||||
|
|
||||||
// world.actors.clear()
|
world.actors.clear()
|
||||||
// world.actors.addAll(actorsList.map { it.referenceID }.sorted().distinct())
|
world.actors.addAll(actorsList.map { it.referenceID }.sorted().distinct())
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun invoke(ingame: IngameInstance, world: TitlescreenGameWorld, actorsList: List<Actor>): String {
|
operator fun invoke(ingame: IngameInstance, world: SimpleGameWorld, actorsList: List<Actor>): String {
|
||||||
val time_t = App.getTIME_T()
|
val time_t = App.getTIME_T()
|
||||||
preWrite(ingame, time_t, world, actorsList)
|
preWrite(ingame, time_t, world, actorsList)
|
||||||
val s = Common.jsoner.toJson(world)
|
val s = Common.jsoner.toJson(world)
|
||||||
@@ -18,7 +18,6 @@ import net.torvald.terrarum.audio.AudioMixer.Companion.DS_FLTIDX_PAN
|
|||||||
import net.torvald.terrarum.audio.dsp.*
|
import net.torvald.terrarum.audio.dsp.*
|
||||||
import net.torvald.terrarum.controller.TerrarumController
|
import net.torvald.terrarum.controller.TerrarumController
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.gameworld.fmod
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.imagefont.TinyAlphNum
|
import net.torvald.terrarum.imagefont.TinyAlphNum
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
@@ -316,7 +315,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
val wallNum = it.getTileFromWall(mouseTileX, mouseTileY)
|
val wallNum = it.getTileFromWall(mouseTileX, mouseTileY)
|
||||||
val tileNum = it.getTileFromTerrain(mouseTileX, mouseTileY)
|
val tileNum = it.getTileFromTerrain(mouseTileX, mouseTileY)
|
||||||
val (oreNum, orePlacement) = it.getTileFromOre(mouseTileX, mouseTileY)
|
val (oreNum, orePlacement) = it.getTileFromOre(mouseTileX, mouseTileY)
|
||||||
val wires = if (it is TheGameWorld) it.getAllWiresFrom(mouseTileX, mouseTileY) else null to null
|
val wires = it.getAllWiresFrom(mouseTileX, mouseTileY)
|
||||||
val fluid = it.getFluid(mouseTileX, mouseTileY)
|
val fluid = it.getFluid(mouseTileX, mouseTileY)
|
||||||
val wireCount = wires.first?.size?.toString() ?: "no"
|
val wireCount = wires.first?.size?.toString() ?: "no"
|
||||||
val tdmg = it.getTerrainDamage(mouseTileX, mouseTileY).toIntAndFrac(2,2)
|
val tdmg = it.getTerrainDamage(mouseTileX, mouseTileY).toIntAndFrac(2,2)
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ abstract class UICanvas(
|
|||||||
|
|
||||||
/** A function that is run ONCE when the UI is requested to be opened; will work identical to [endOpening] if [openCloseTime] is zero */
|
/** A function that is run ONCE when the UI is requested to be opened; will work identical to [endOpening] if [openCloseTime] is zero */
|
||||||
open fun show() {
|
open fun show() {
|
||||||
|
clearTooltip()
|
||||||
openingClickLatched = true
|
openingClickLatched = true
|
||||||
uiItems.forEach { it.show() }
|
uiItems.forEach { it.show() }
|
||||||
handler.subUIs.forEach { it.show() }
|
handler.subUIs.forEach { it.show() }
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package net.torvald.terrarum.utils
|
package net.torvald.terrarum.utils
|
||||||
|
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Json
|
||||||
|
import com.badlogic.gdx.utils.JsonValue
|
||||||
import net.torvald.terrarum.gameactors.ActorValue
|
import net.torvald.terrarum.gameactors.ActorValue
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
|||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
import net.torvald.terrarum.gameitems.ItemID
|
import net.torvald.terrarum.gameitems.ItemID
|
||||||
import net.torvald.terrarum.gameworld.*
|
import net.torvald.terrarum.gameworld.FLUID_MIN_MASS
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.shake
|
import net.torvald.terrarum.modulebasegame.worldgenerator.shake
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.serialise.toBig64
|
import net.torvald.terrarum.serialise.toBig64
|
||||||
@@ -41,7 +43,7 @@ import kotlin.math.roundToInt
|
|||||||
internal object BlocksDrawer {
|
internal object BlocksDrawer {
|
||||||
|
|
||||||
/** World change is managed by IngameRenderer.setWorld() */
|
/** World change is managed by IngameRenderer.setWorld() */
|
||||||
internal var world: GameWorld = TheGameWorld.makeNullWorld()
|
internal var world: GameWorld = GameWorld.makeNullWorld()
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -446,10 +448,6 @@ internal object BlocksDrawer {
|
|||||||
*/
|
*/
|
||||||
private fun fillInTileBuffer(mode: Int) {
|
private fun fillInTileBuffer(mode: Int) {
|
||||||
|
|
||||||
// don't render fluid and ores for TitlescreenGameWorld (for now)
|
|
||||||
if (world.layerFluids !is BlockLayerFluidI16F16) return
|
|
||||||
if (world.layerOres !is BlockLayerOresI16I8) return
|
|
||||||
|
|
||||||
// TODO the real fluid rendering must use separate function, but its code should be similar to this.
|
// TODO the real fluid rendering must use separate function, but its code should be similar to this.
|
||||||
// shader's tileAtlas will be fluid.tga, pixels written to the buffer is in accordance with the new
|
// shader's tileAtlas will be fluid.tga, pixels written to the buffer is in accordance with the new
|
||||||
// atlas. IngameRenderer must be modified so that fluid-draw call is separated from drawing tiles.
|
// atlas. IngameRenderer must be modified so that fluid-draw call is separated from drawing tiles.
|
||||||
@@ -469,7 +467,7 @@ internal object BlocksDrawer {
|
|||||||
WALL -> world.layerWall.unsafeGetTile(wx, wy)
|
WALL -> world.layerWall.unsafeGetTile(wx, wy)
|
||||||
TERRAIN -> world.layerTerrain.unsafeGetTile(wx, wy)
|
TERRAIN -> world.layerTerrain.unsafeGetTile(wx, wy)
|
||||||
ORES -> world.layerOres.unsafeGetTile(wx, wy)//.also { println(it) }
|
ORES -> world.layerOres.unsafeGetTile(wx, wy)//.also { println(it) }
|
||||||
FLUID -> world.layerFluids.unsafeGetTileI16F16(wx, wy).let { (number, fill) ->
|
FLUID -> world.layerFluids.unsafeGetTile1(wx, wy).let { (number, fill) ->
|
||||||
if (number == 65535 || fill < 1f/30f) 0
|
if (number == 65535 || fill < 1f/30f) 0
|
||||||
else number
|
else number
|
||||||
}
|
}
|
||||||
@@ -499,7 +497,7 @@ internal object BlocksDrawer {
|
|||||||
val nearbyFluidType = fluids.asSequence().filter { it.amount >= 0.5f / 16f }.map { it.type }.filter { it.startsWith("fluid@") }.sorted().firstOrNull()
|
val nearbyFluidType = fluids.asSequence().filter { it.amount >= 0.5f / 16f }.map { it.type }.filter { it.startsWith("fluid@") }.sorted().firstOrNull()
|
||||||
|
|
||||||
val fillThis =
|
val fillThis =
|
||||||
world.layerFluids.unsafeGetTileI16F16(wx, wy).second.let { if (it.isNaN()) 0f else it.coerceAtMost(1f) }
|
world.layerFluids.unsafeGetTile1(wx, wy).second.let { if (it.isNaN()) 0f else it.coerceAtMost(1f) }
|
||||||
|
|
||||||
val tile = world.getTileFromTerrain(wx, wy)
|
val tile = world.getTileFromTerrain(wx, wy)
|
||||||
|
|
||||||
@@ -673,7 +671,7 @@ internal object BlocksDrawer {
|
|||||||
rawTileNum + nearbyTilesInfo
|
rawTileNum + nearbyTilesInfo
|
||||||
// special case: ores
|
// special case: ores
|
||||||
else if (mode == ORES)
|
else if (mode == ORES)
|
||||||
rawTileNum + world.layerOres.unsafeGetTileI16I8(wx, wy).second
|
rawTileNum + world.layerOres.unsafeGetTile1(wx, wy).second
|
||||||
// rest of the cases: terrain and walls
|
// rest of the cases: terrain and walls
|
||||||
else rawTileNum + when (renderTag.maskType) {
|
else rawTileNum + when (renderTag.maskType) {
|
||||||
CreateTileAtlas.RenderTag.MASK_NA -> 0
|
CreateTileAtlas.RenderTag.MASK_NA -> 0
|
||||||
@@ -1190,7 +1188,7 @@ internal object BlocksDrawer {
|
|||||||
get() {
|
get() {
|
||||||
val rate = (((Gdx.graphics.framesPerSecond / 50f) * TILE_SIZEF) / maxOf(WorldCamera.deltaX.abs(), WorldCamera.deltaY.abs()).coerceAtLeast(1)).roundToInt().coerceIn(1, 4)
|
val rate = (((Gdx.graphics.framesPerSecond / 50f) * TILE_SIZEF) / maxOf(WorldCamera.deltaX.abs(), WorldCamera.deltaY.abs()).coerceAtLeast(1)).roundToInt().coerceIn(1, 4)
|
||||||
App.debugTimers.put("Renderer.tilemapUpdateDivider", rate.toLong())
|
App.debugTimers.put("Renderer.tilemapUpdateDivider", rate.toLong())
|
||||||
return (!world.layerTerrain.disposed && App.GLOBAL_RENDER_TIMER % rate == 0L)
|
return (!world.layerTerrain.ptrDestroyed && App.GLOBAL_RENDER_TIMER % rate == 0L)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var camTransX = 0
|
private var camTransX = 0
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package net.torvald.terrarum.worlddrawer
|
package net.torvald.terrarum.worlddrawer
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.colourutil.ColourTemp
|
import net.torvald.colourutil.ColourTemp
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
||||||
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.blockstats.TileSurvey
|
import net.torvald.terrarum.blockstats.TileSurvey
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@@ -15,7 +17,7 @@ import kotlin.math.roundToInt
|
|||||||
object FeaturesDrawer {
|
object FeaturesDrawer {
|
||||||
|
|
||||||
/** World change is managed by IngameRenderer.setWorld() */
|
/** World change is managed by IngameRenderer.setWorld() */
|
||||||
internal var world: GameWorld = TheGameWorld.makeNullWorld()
|
internal var world: GameWorld = GameWorld.makeNullWorld()
|
||||||
|
|
||||||
//const val TILE_SIZE = TILE_SIZE
|
//const val TILE_SIZE = TILE_SIZE
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import net.torvald.terrarum.gameitems.GameItem
|
|||||||
import net.torvald.terrarum.gameitems.isBlock
|
import net.torvald.terrarum.gameitems.isBlock
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||||
import net.torvald.terrarum.modulebasegame.ui.abs
|
import net.torvald.terrarum.modulebasegame.ui.abs
|
||||||
@@ -44,7 +43,7 @@ import kotlin.math.*
|
|||||||
object LightmapRenderer {
|
object LightmapRenderer {
|
||||||
|
|
||||||
/** World change is managed by IngameRenderer.setWorld() */
|
/** World change is managed by IngameRenderer.setWorld() */
|
||||||
private var world: GameWorld = TheGameWorld.makeNullWorld()
|
private var world: GameWorld = GameWorld.makeNullWorld()
|
||||||
|
|
||||||
//private lateinit var lightCalcShader: ShaderProgram
|
//private lateinit var lightCalcShader: ShaderProgram
|
||||||
//private val SHADER_LIGHTING = AppLoader.getConfigBoolean("gpulightcalc")
|
//private val SHADER_LIGHTING = AppLoader.getConfigBoolean("gpulightcalc")
|
||||||
@@ -142,7 +141,7 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun recalculate(actorContainer: List<ActorWithBody>) {
|
fun recalculate(actorContainer: List<ActorWithBody>) {
|
||||||
if (!world.layerTerrain.disposed) _recalculate(actorContainer, lightmap)
|
if (!world.layerTerrain.ptrDestroyed) _recalculate(actorContainer, lightmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun _recalculate(actorContainer: List<ActorWithBody>, lightmap: UnsafeCvecArray) {
|
private fun _recalculate(actorContainer: List<ActorWithBody>, lightmap: UnsafeCvecArray) {
|
||||||
@@ -154,7 +153,7 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
catch (e: NullPointerException) {
|
catch (e: NullPointerException) {
|
||||||
System.err.println("[LightmapRendererNew.recalculate] Attempted to refer destroyed unsafe array " +
|
System.err.println("[LightmapRendererNew.recalculate] Attempted to refer destroyed unsafe array " +
|
||||||
"(${world.layerTerrain})")
|
"(${world.layerTerrain.ptr})")
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
return // something's wrong but we'll ignore it like a trustful AK
|
return // something's wrong but we'll ignore it like a trustful AK
|
||||||
}
|
}
|
||||||
@@ -657,7 +656,7 @@ object LightmapRenderer {
|
|||||||
|
|
||||||
internal fun draw(): Texture {
|
internal fun draw(): Texture {
|
||||||
|
|
||||||
if (!world.layerTerrain.disposed) {
|
if (!world.layerTerrain.ptrDestroyed) {
|
||||||
// when shader is not used: 0.5 ms on 6700K
|
// when shader is not used: 0.5 ms on 6700K
|
||||||
App.measureDebugTime("Renderer.LightToScreen") {
|
App.measureDebugTime("Renderer.LightToScreen") {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user