still working on the new savegame scheme

main game works fine, saving/loading will not be possible
This commit is contained in:
minjaesong
2021-10-07 17:43:23 +09:00
parent 6d8a7520ac
commit 3f9b41fd29
23 changed files with 200 additions and 86 deletions

View File

@@ -7,12 +7,14 @@ The main game directory is composed of following directories:
```
.Terrarum
+ Players
- <Player Name Here>, TVDA { (-1) player JSON, (-2) optional spritedef, (-3) optional spritedef-glow, (-1025) sprite-bodypart-name-to-entry-number-map.properties, (1+) optional textures and sprite defs }
- <Player Name Here>, TVDA { (-1) player JSON, (-2) spritedef, (-3) optional spritedef-glow, (-1025) sprite-bodypart-name-to-entry-number-map.properties, (1+) optional bodyparts tga.gz }
if file -1025 is not there, read bodyparts from assets directory
optionally encrypt the files other than -1
+ Shared
- <e.g. Disk GUID>, TEVD { * }
- <this directory can have anything>
+ Worlds
- <World Name Here>, TVDA { WriteWorld, actors (mainly fixtures) JSON, chunk data, screenshot.tga.gz taken by the last player }
- <World Name Here>, TVDA { (-1) WriteWorld, (actorID) actors (mainly fixtures) JSON, (0x1_0000_0000 + (layerNumber << 24) + chunkNumber) chunk data, (-2) screenshot.tga.gz taken by the last player }
```
(TEVD stands for Terrarum Virtual Disk spec version 3, TVDA stands for spec version 254; both have MAGIC header of `TEVd`)

File diff suppressed because one or more lines are too long

View File

@@ -37,25 +37,41 @@ interface HasAssembledSprite {
_rebuild(animGlow, spriteGlow)
}
/*fun rebuild(animDescPath: String, spriteAnimation: SpriteAnimation) {
_rebuild(ADProperties(StringReader(animDescPath)), spriteAnimation)
fun reassembleSprite(disk: SimpleFileSystem, sprite: SpriteAnimation?, anim: ADProperties?, spriteGlow: SpriteAnimation? = null, animGlow: ADProperties? = null) {
if (anim != null && sprite != null)
_rebuild(disk, anim, sprite)
if (animGlow != null && spriteGlow != null)
_rebuild(disk, animGlow, spriteGlow)
}
fun rebuild(animDesc: FileHandle, spriteAnimation: SpriteAnimation) {
_rebuild(ADProperties(animDesc.read()), spriteAnimation)
}
fun rebuild(javaProp: Properties, spriteAnimation: SpriteAnimation) {
_rebuild(ADProperties(javaProp), spriteAnimation)
}*/
private fun _rebuild(ad: ADProperties, sprite: SpriteAnimation) {
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
// TODO resolve bodyparts (must read ID-to-bodypartmap.properties first)
val pixmap = AssembleSheetPixmap.fromAssetsDir(ad)
val texture = Texture(pixmap)
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
pixmap.dispose()
val regionPack = TextureRegionPack(texture, ad.frameWidth, ad.frameHeight)
val pixmap = AssembleSheetPixmap(ad)
val newAnimDelays = FloatArray(ad.animations.size)
val newAnimFrames = IntArray(ad.animations.size)
ad.animations.forEach { t, u ->
val index = u.row - 1
newAnimDelays[index] = u.delay
newAnimFrames[index] = u.frames
}
sprite.setSpriteImage(regionPack)
sprite.delays = newAnimDelays
sprite.nFrames = newAnimFrames
sprite.nRows = newAnimDelays.size
}
private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) {
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
val pixmap = AssembleSheetPixmap.fromVirtualDisk(disk, ad)
val texture = Texture(pixmap)
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
pixmap.dispose()

View File

@@ -4,7 +4,14 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.terrarum.linearSearch
import net.torvald.terrarum.serialise.Common
import net.torvald.terrarum.tvda.ByteArray64InputStream
import net.torvald.terrarum.tvda.ByteArray64Reader
import net.torvald.terrarum.tvda.SimpleFileSystem
import java.io.InputStream
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
/**
* Assembles the single frame of the animation, outputs GDX Pixmap.
@@ -15,14 +22,10 @@ import java.io.InputStream
*/
object AssembleSheetPixmap {
operator fun invoke(properties: ADProperties): Pixmap {
private fun drawAndGetCanvas(properties: ADProperties, fileGetter: (String) -> InputStream): Pixmap {
val canvas = Pixmap(properties.cols * properties.frameWidth, properties.rows * properties.frameHeight, Pixmap.Format.RGBA8888)
canvas.blending = Pixmap.Blending.SourceOver
val fileGetter = { path: String ->
Gdx.files.internal(path).read()
}
// actually draw
properties.transforms.forEach { t, _ ->
drawThisFrame(t, canvas, properties, fileGetter)
@@ -31,6 +34,21 @@ object AssembleSheetPixmap {
return canvas
}
fun fromAssetsDir(properties: ADProperties) = drawAndGetCanvas(properties) { partName: String ->
Gdx.files.internal("assets/${properties.toFilename(partName)}").read()
}
fun fromVirtualDisk(disk: SimpleFileSystem, properties: ADProperties): Pixmap {
val bodypartMapping = Properties()
bodypartMapping.load(ByteArray64Reader(disk.getFile(-1025L)!!.bytes, Common.CHARSET))
val fileGetter = { partName: String ->
ByteArray64InputStream(disk.getFile(bodypartMapping[partName] as Long)!!.bytes)
}
return drawAndGetCanvas(properties, fileGetter)
}
private fun drawThisFrame(frameName: String,
canvas: Pixmap,
properties: ADProperties,
@@ -42,7 +60,7 @@ object AssembleSheetPixmap {
val bodypartOrigins = properties.bodyparts
val bodypartImages = properties.bodyparts.keys.map {
try {
val bytes = fileGetter("assets/${properties.toFilename(it)}").readAllBytes()
val bytes = fileGetter(it).readAllBytes()
it to Pixmap(bytes, 0, bytes.size)
}
catch (e: GdxRuntimeException) {

View File

@@ -298,7 +298,7 @@ class SpriteAssemblerPreview: Game() {
}
private fun assembleImage(prop: ADProperties) {
image = AssembleSheetPixmap(prop)
image = AssembleSheetPixmap.fromAssetsDir(prop)
}
// TODO rename to requestAssembly

View File

@@ -92,7 +92,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
oldWorld.dispose()
}
/** how many different planets/stages/etc. are thenre. Whole stages must be manually managed by YOU. */
var gameworldIndices = ArrayList<Int>()
//var gameworldIndices = ArrayList<Int>()
/** The actor the game is currently allowing you to control.
*

View File

@@ -702,7 +702,7 @@ fun AppUpdateListOfSavegames() {
fun checkForSavegameDamage(skimmer: DiskSkimmer): Boolean {
try {
// # check for meta
val metaFile = skimmer.requestFile(-1) ?: return true
/*val metaFile = skimmer.requestFile(-1) ?: return true
// # check if The Player is there
val player = skimmer.requestFile(PLAYER_REF_ID.toLong().and(0xFFFFFFFFL))?.contents ?: return true
// # check if:
@@ -723,7 +723,7 @@ fun checkForSavegameDamage(skimmer: DiskSkimmer): Boolean {
System.err.println("Nonexisting actor $it for savegame ${skimmer.diskFile.absolutePath}")
hasMissingActor = true
}
}; if (hasMissingActor) return true
}; if (hasMissingActor) return true*/
return false

View File

@@ -140,7 +140,7 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
printdbg(this, "Demo world loaded")
}
catch (e: IOException) {
demoWorld = GameWorld(1, LandUtil.CHUNK_W, LandUtil.CHUNK_H, 0L, 0L)
demoWorld = GameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H, 0L, 0L)
printdbg(this, "Demo world not found, using empty world")
}
@@ -230,9 +230,8 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
// load list of savegames
println("[TitleScreen] update list of savegames")
App.updateListOfSavegames()
// App.savegames.forEach { println(it.diskFile.absolutePath) }
// TODO to show "Continue" and "Load" on the titlescreen, uncomment this line
// App.updateListOfSavegames()
loadThingsWhileIntroIsVisible()

View File

@@ -14,6 +14,10 @@ import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.utils.*
import net.torvald.util.SortedArrayList
import org.dyn4j.geometry.Vector2
import java.util.*
import kotlin.NoSuchElementException
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.math.absoluteValue
typealias BlockAddress = Long
@@ -29,17 +33,8 @@ class GameWorldTitleScreen : GameWorld() {
open class GameWorld() : Disposable {
var worldName: String = "New World"
/** Index start at 1 */
var worldIndex: Int = 1234567890
set(value) {
if (value <= 0)
throw Error("World index start at 1; you've entered $value")
printdbg(this, "Creation of new world with index $value, called by:")
printStackTrace(this)
field = value
}
var worldIndex: UUID = UUID.randomUUID() // should not be immutable as JSON loader will want to overwrite it
var worldCreator: UUID = UUID(0L,0L) // TODO record a value to this
var width: Int = 999; private set
var height: Int = 999; private set
@@ -120,10 +115,9 @@ open class GameWorld() : Disposable {
/**
* Create new world
*/
constructor(worldIndex: Int, width: Int, height: Int, creationTIME_T: Long, lastPlayTIME_T: Long): this() {
constructor(width: Int, height: Int, creationTIME_T: Long, lastPlayTIME_T: Long): this() {
if (width <= 0 || height <= 0) throw IllegalArgumentException("Non-positive width/height: ($width, $height)")
this.worldIndex = worldIndex
this.width = width
this.height = height
@@ -675,7 +669,7 @@ open class GameWorld() : Disposable {
fun makeNullWorld(): GameWorld {
if (nullWorldInstance == null)
nullWorldInstance = GameWorld(1, 1, 1, 0, 0)
nullWorldInstance = GameWorld(1, 1, 0, 0)
return nullWorldInstance!!
}

View File

@@ -65,7 +65,7 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
private val timeNow = System.currentTimeMillis() / 1000
val gameWorld = GameWorld(1, 1024, 256, timeNow, timeNow)
val gameWorld = GameWorld(90*12, 90*4, timeNow, timeNow)
init {
// ghetto world for building

View File

@@ -348,9 +348,9 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
// init map as chosen size
val timeNow = App.getTIME_T()
world = GameWorld(1, worldParams.width, worldParams.height, timeNow, timeNow) // new game, so the creation time is right now
world = GameWorld(worldParams.width, worldParams.height, timeNow, timeNow) // new game, so the creation time is right now
world.generatorSeed = worldParams.worldGenSeed
gameworldIndices.add(world.worldIndex)
//gameworldIndices.add(world.worldIndex)
world.extraFields["basegame.economy"] = GameEconomy()
// generate terrain for the map

View File

@@ -5,6 +5,7 @@ import net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.spriteassembler.ADProperties
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.AVKey
import java.util.*
/**
@@ -15,9 +16,10 @@ import net.torvald.terrarum.gameactors.AVKey
class IngamePlayer : ActorHumanoid, HasAssembledSprite {
var UUID = UUID(0L,0L); private set
internal var worldCurrentlyPlaying: UUID = UUID(0L,0L) // only filled up on save and load; DO NOT USE THIS
override var animDesc: ADProperties? = null
override var animDescGlow: ADProperties? = null
internal var worldCurrentlyPlaying = 0 // only filled up on save and load; DO NOT USE THIS
private constructor()
@@ -33,10 +35,10 @@ class IngamePlayer : ActorHumanoid, HasAssembledSprite {
* **Use PlayerFactory to build player!**
*/
init {
referenceID = Terrarum.PLAYER_REF_ID // forcibly set ID
referenceID = Terrarum.PLAYER_REF_ID // TODO assign random ID
density = BASE_DENSITY
collisionType = COLLISION_KINEMATIC
worldCurrentlyPlaying = Terrarum.ingame?.world?.worldIndex ?: 0
worldCurrentlyPlaying = Terrarum.ingame?.world?.worldIndex ?: UUID(0L,0L)
}
}

View File

@@ -17,6 +17,7 @@ import java.io.InputStream
import java.io.Reader
import java.io.StringReader
import java.math.BigInteger
import java.util.*
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
@@ -172,6 +173,16 @@ object Common {
return hashMap
}
})
// UUID
jsoner.setSerializer(UUID::class.java, object : Json.Serializer<UUID> {
override fun write(json: Json, obj: UUID, knownType: Class<*>?) {
json.writeValue(obj.toString())
}
override fun read(json: Json, jsonData: JsonValue, type: Class<*>?): UUID {
return UUID.fromString(jsonData.asString())
}
})
}
private data class LayerInfo(val h: String, val b: String, val x: Int, val y: Int)

View File

@@ -29,6 +29,11 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
private val actorProgressMultiplier = 1f
override fun run() {
callback()
return
// TODO //
disk.saveMode = 2 * isAuto.toInt() // no quick
if (hasThumbnail) {
@@ -81,9 +86,9 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
// Commented out; nothing to write
// Write ItemCodex//
val itemCodexContent = EntryFile(Common.zip(ByteArray64.fromByteArray(Common.jsoner.toJson(ItemCodex).toByteArray(Common.CHARSET))))
val items = DiskEntry(-17, 0, creation_t, time_t, itemCodexContent)
addFile(disk, items)
// val itemCodexContent = EntryFile(Common.zip(ByteArray64.fromByteArray(Common.jsoner.toJson(ItemCodex).toByteArray(Common.CHARSET))))
// val items = DiskEntry(-17, 0, creation_t, time_t, itemCodexContent)
// addFile(disk, items)
// Gotta save dynamicIDs
// Write WireCodex//
@@ -104,15 +109,15 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
// addFile(disk, factions)
// Write Apocryphas//
val apocryphasContent = EntryFile(Common.zip(ByteArray64.fromByteArray(Common.jsoner.toJson(Apocryphas).toByteArray(Common.CHARSET))))
val apocryphas = DiskEntry(-1024, 0, creation_t, time_t, apocryphasContent)
addFile(disk, apocryphas)
// val apocryphasContent = EntryFile(Common.zip(ByteArray64.fromByteArray(Common.jsoner.toJson(Apocryphas).toByteArray(Common.CHARSET))))
// val apocryphas = DiskEntry(-1024, 0, creation_t, time_t, apocryphasContent)
// addFile(disk, apocryphas)
// Write World //
val worldNum = ingame.world.worldIndex
val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t))
val world = DiskEntry(worldNum.toLong(), 0, creation_t, time_t, worldMeta)
addFile(disk, world)
// val worldNum = ingame.world.worldIndex
// val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t))
// val world = DiskEntry(worldNum.toLong(), 0, creation_t, time_t, worldMeta)
// addFile(disk, world)
WriteSavegame.saveProgress += 1f
@@ -125,7 +130,7 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
Echo("Writing chunks... ${(cw*ch*layer) + chunkNumber + 1}/${cw*ch*layers.size}")
val chunkBytes = WriteWorld.encodeChunk(layers[layer]!!, cx, cy)
val entryID = worldNum.toLong().shl(32) or layer.toLong().shl(24) or chunkNumber
val entryID = 0x1_0000_0000L or layer.toLong().shl(24) or chunkNumber
val entryContent = EntryFile(chunkBytes)
val entry = DiskEntry(entryID, 0, creation_t, time_t, entryContent)

View File

@@ -34,6 +34,11 @@ class QuickSaveThread(val disk: VirtualDisk, val file: File, val ingame: Terraru
override fun run() {
callback()
return
// TODO //
val skimmer = DiskSkimmer(file, Common.CHARSET)
if (hasThumbnail) {
@@ -82,7 +87,7 @@ class QuickSaveThread(val disk: VirtualDisk, val file: File, val ingame: Terraru
// Write World //
val worldNum = ingame.world.worldIndex
val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t))
val world = DiskEntry(worldNum.toLong(), 0, creation_t, time_t, worldMeta)
val world = DiskEntry(-1-1-1-1-1-1-1, 0, creation_t, time_t, worldMeta)
addFile(disk, world); skimmer.appendEntryOnly(world)
WriteSavegame.saveProgress += 1f
@@ -101,7 +106,7 @@ class QuickSaveThread(val disk: VirtualDisk, val file: File, val ingame: Terraru
// println("Chunk xy from number $chunkNumber -> (${chunkXY.x}, ${chunkXY.y})")
val chunkBytes = WriteWorld.encodeChunk(layer, chunkXY.x, chunkXY.y)
val entryID = worldNum.toLong().shl(32) or layerNum.toLong().shl(24) or chunkNumber.toLong()
val entryID = 0x1_0000_0000L or layerNum.toLong().shl(24) or chunkNumber.toLong()
val entryContent = EntryFile(chunkBytes)
val entry = DiskEntry(entryID, 0, creation_t, time_t, entryContent)

View File

@@ -3,6 +3,8 @@ package net.torvald.terrarum.serialise
import net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.spriteassembler.ADProperties
import net.torvald.terrarum.App
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.NoSuchActorWithIDException
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorWithBody
@@ -49,17 +51,53 @@ object WriteActor {
* Created by minjaesong on 2021-10-07.
*/
object WritePlayer {
operator fun invoke(player: IngamePlayer, disk: VirtualDisk) {
/**
* Will happily overwrite existing entry
*/
private fun addFile(disk: VirtualDisk, file: DiskEntry) {
disk.entries[file.entryID] = file
file.parentEntryID = 0
val dir = VDUtil.getAsDirectory(disk, 0)
if (!dir.contains(file.entryID)) dir.add(file.entryID)
}
operator fun invoke(player: IngamePlayer, playerDisk: VirtualDisk) {
val time_t = App.getTIME_T()
val actorJson = WriteActor.encodeToByteArray64(player)
val adl = player.animDesc?.getRawADL() // NULLABLE!
val adl = player.animDesc!!.getRawADL()
val adlGlow = player.animDescGlow?.getRawADL() // NULLABLE!
}
operator fun invoke(player: IngamePlayer, skimmer: DiskSkimmer) {
val jsonContents = EntryFile(actorJson)
val jsonCreationDate = playerDisk.getEntry(-1)?.creationDate ?: time_t
addFile(playerDisk, DiskEntry(-1L, 0L, jsonCreationDate, time_t, jsonContents))
val adlContents = EntryFile(ByteArray64.fromByteArray(adl.toByteArray(Common.CHARSET)))
val adlCreationDate = playerDisk.getEntry(-2)?.creationDate ?: time_t
addFile(playerDisk, DiskEntry(-1L, 0L, adlCreationDate, time_t, adlContents))
if (adlGlow != null) {
val adlGlowContents = EntryFile(ByteArray64.fromByteArray(adlGlow.toByteArray(Common.CHARSET)))
val adlGlowCreationDate = playerDisk.getEntry(-3)?.creationDate ?: time_t
addFile(playerDisk, DiskEntry(-1L, 0L, adlGlowCreationDate, time_t, adlGlowContents))
}
}
}
/**
* Player-specific [ReadActor].
*
* Created by minjaesong on 2021-10-07.
*/
object ReadPlayer {
operator fun invoke(disk: SimpleFileSystem, dataStream: Reader): IngamePlayer =
ReadActor(disk, dataStream) as IngamePlayer
}
/**
* Actor's JSON representation is expected to have "class" property on the root object, such as:
@@ -71,8 +109,8 @@ object WritePlayer {
*/
object ReadActor {
operator fun invoke(disk: SimpleFileSystem, worldDataStream: Reader): Actor =
fillInDetails(disk, Common.jsoner.fromJson(null, worldDataStream))
operator fun invoke(disk: SimpleFileSystem, dataStream: Reader): Actor =
fillInDetails(disk, Common.jsoner.fromJson(null, dataStream))
fun readActorBare(worldDataStream: Reader): Actor =
Common.jsoner.fromJson(null, worldDataStream)
@@ -89,19 +127,30 @@ object ReadActor {
actor.sprite = SpriteAnimation(actor)
if (animFileGlow != null) actor.spriteGlow = SpriteAnimation(actor)
actor.reassembleSprite(
actor.sprite!!,
ADProperties(ByteArray64Reader(animFile!!.bytes, Common.CHARSET)),
actor.spriteGlow,
if (animFileGlow == null) null else ADProperties(ByteArray64Reader(animFileGlow.bytes, Common.CHARSET))
)
val bodypartsFile = disk.getFile(-1025)
if (bodypartsFile != null)
actor.reassembleSprite(
disk,
actor.sprite!!,
ADProperties(ByteArray64Reader(animFile!!.bytes, Common.CHARSET)),
actor.spriteGlow,
if (animFileGlow == null) null else ADProperties(ByteArray64Reader(animFileGlow.bytes, Common.CHARSET))
)
else
actor.reassembleSprite(
actor.sprite!!,
ADProperties(ByteArray64Reader(animFile!!.bytes, Common.CHARSET)),
actor.spriteGlow,
if (animFileGlow == null) null else ADProperties(ByteArray64Reader(animFileGlow.bytes, Common.CHARSET))
)
}
return actor
}
fun readActorAndAddToWorld(ingame: TerrarumIngame, disk: SimpleFileSystem, worldDataStream: Reader): Actor {
val actor = invoke(disk, worldDataStream)
fun readActorAndAddToWorld(ingame: TerrarumIngame, disk: SimpleFileSystem, dataStream: Reader): Actor {
val actor = invoke(disk, dataStream)
// replace existing player
val oldPlayerID = ingame.actorNowPlaying?.referenceID

View File

@@ -24,12 +24,11 @@ object WriteMeta {
randseed1 = RoguelikeRandomiser.RNG.state1,
weatseed0 = WeatherMixer.RNG.state0,
weatseed1 = WeatherMixer.RNG.state1,
playerid = ingame.actorGamer.referenceID,
creation_t = ingame.creationTime,
lastplay_t = time_t,
playtime_t = ingame.totalPlayTime + currentPlayTime_t,
loadorder = ModMgr.loadOrder.toTypedArray(),
worlds = ingame.gameworldIndices.toTypedArray()
//worlds = ingame.gameworldIndices.toTypedArray()
)
return Common.jsoner.toJson(meta)
@@ -52,8 +51,8 @@ object WriteMeta {
val creation_t: Long = 0,
val lastplay_t: Long = 0,
val playtime_t: Long = 0,
val loadorder: Array<String> = arrayOf(), // do not use list; Could not instantiate instance of class: java.util.Collections$SingletonList
val worlds: Array<Int> = arrayOf() // do not use list; Could not instantiate instance of class: java.util.Collections$SingletonList
val loadorder: Array<String> = arrayOf() // do not use list; Could not instantiate instance of class: java.util.Collections$SingletonList
//val worlds: Array<Int> = arrayOf() // do not use list; Could not instantiate instance of class: java.util.Collections$SingletonList
) {
override fun equals(other: Any?): Boolean {

View File

@@ -56,6 +56,10 @@ object WriteSavegame {
fun immediate(disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, callback: () -> Unit = {}) {
return
// TODO //
savingStatus = 0
Echo("Immediate save fired")
@@ -68,6 +72,10 @@ object WriteSavegame {
}
fun quick(disk: VirtualDisk, file: File, ingame: TerrarumIngame, isAuto: Boolean, callback: () -> Unit = {}) {
return
// TODO //
savingStatus = 0
Echo("Quicksave queued")
@@ -111,6 +119,8 @@ object LoadSavegame {
fun getFileReader(disk: VirtualDisk, id: Long): Reader = ByteArray64Reader(getFileBytes(disk, id), Common.CHARSET)
operator fun invoke(disk: VirtualDisk) {
TODO()
val newIngame = TerrarumIngame(App.batch)
val meta = ReadMeta(disk)
@@ -118,7 +128,7 @@ object LoadSavegame {
// NOTE: do NOT set ingame.actorNowPlaying as one read directly from the disk;
// you'll inevitably read the player actor twice, and they're separate instances of the player!
val currentWorld = (ReadActor.readActorBare(getFileReader(disk, Terrarum.PLAYER_REF_ID.toLong())) as IngamePlayer).worldCurrentlyPlaying
val world = ReadWorld(getFileReader(disk, currentWorld.toLong()))
val world = ReadWorld(getFileReader(disk, -1-1-1-1-1-1))
// set lateinit vars on the gameworld FIRST
world.layerTerrain = BlockLayer(world.width, world.height)
@@ -153,7 +163,6 @@ object LoadSavegame {
// load all the world blocklayer chunks
val worldnum = world.worldIndex.toLong()
val cw = LandUtil.CHUNK_W
val ch = LandUtil.CHUNK_H
val chunkCount = world.width * world.height / (cw * ch)
@@ -162,7 +171,7 @@ object LoadSavegame {
for (layer in worldLayer.indices) {
loadscreen.addMessage("${Lang["MENU_IO_LOADING"]} ${chunk*worldLayer.size+layer+1}/${chunkCount*2}")
val chunkFile = VDUtil.getAsNormalFile(disk, worldnum.shl(32) or layer.toLong().shl(24) or chunk)
val chunkFile = VDUtil.getAsNormalFile(disk, 0x1_0000_0000L or layer.toLong().shl(24) or chunk)
val chunkXY = LandUtil.chunkNumToChunkXY(world, chunk.toInt())
ReadWorld.decodeChunkToLayer(chunkFile.getContent(), worldLayer[layer]!!, chunkXY.x, chunkXY.y)

View File

@@ -11,7 +11,7 @@ class SpriteAssemblerTest {
operator fun invoke() {
val properties = ADProperties(StringReader(ADLParsingTest().TEST_STR))
AssembleSheetPixmap.invoke(properties)
AssembleSheetPixmap.fromAssetsDir(properties)
}
}

View File

@@ -250,6 +250,7 @@ removefile:
}
}
override fun getEntry(id: EntryID) = requestFile(id)
override fun getFile(id: EntryID) = requestFile(id)?.contents as? EntryFile
/**

View File

@@ -4,5 +4,6 @@ package net.torvald.terrarum.tvda
* Created by minjaesong on 2021-10-07.
*/
interface SimpleFileSystem {
fun getEntry(id: EntryID): DiskEntry?
fun getFile(id: EntryID): EntryFile?
}

View File

@@ -143,6 +143,7 @@ class VirtualDisk(
extraInfoBytes = footer.toByteArray()
}
override fun getEntry(id: EntryID) = entries[id]
override fun getFile(id: EntryID) = try { VDUtil.getAsNormalFile(this, id) } catch (e: NullPointerException) { null }
private fun serializeEntriesOnly(): ByteArray64 {

View File

@@ -18,6 +18,8 @@ import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.terrarum.modulebasegame.ui.abs
import net.torvald.terrarum.realestate.LandUtil
import java.util.*
import kotlin.collections.HashMap
import kotlin.math.roundToInt
import kotlin.system.exitProcess
@@ -154,7 +156,7 @@ object LightmapRenderer {
return // something's wrong but we'll ignore it like a trustful AK
}
if (world.worldIndex == -1) return
if (world.worldIndex == UUID(0L,0L)) return
for_x_start = WorldCamera.zoomedX / TILE_SIZE // fix for premature lightmap rendering