save/load kinda mostly working but fixtures are not getting their sprites back

This commit is contained in:
minjaesong
2021-09-06 17:31:37 +09:00
parent ec08f8d07e
commit 1accf985e7
29 changed files with 230 additions and 126 deletions

View File

@@ -1139,6 +1139,9 @@ public class AppLoader implements ApplicationListener {
// //
public static String csiR = "\u001B[31m";
public static String csi0 = "\u001B[m";
public static void printdbg(Object obj, Object message) {
if (IS_DEVELOPMENT_BUILD) {
String out = (obj instanceof String) ? (String) obj : obj.getClass().getSimpleName();
@@ -1153,9 +1156,9 @@ public class AppLoader implements ApplicationListener {
if (IS_DEVELOPMENT_BUILD) {
String out = (obj instanceof String) ? (String) obj : obj.getClass().getSimpleName();
if (message == null)
System.err.println("[" + out + "] null");
System.out.println(csiR + "[" + out + "] null" + csi0);
else
System.err.println("[" + out + "] " + message.toString());
System.out.println(csiR + "[" + out + "] " + message.toString() + csi0);
}
}

View File

@@ -9,6 +9,7 @@ import net.torvald.util.CircularArray
open class LoadScreenBase : ScreenAdapter(), Disposable {
open var preLoadJob: (LoadScreenBase) -> Unit = {}
open var screenToLoad: IngameInstance? = null
open lateinit var screenLoadingThread: Thread
@@ -33,6 +34,7 @@ open class LoadScreenBase : ScreenAdapter(), Disposable {
else {
val runnable = {
try {
preLoadJob(this)
screenToLoad!!.show()
}
catch (e: Exception) {

View File

@@ -123,7 +123,7 @@ object ModMgr {
}
newClass?.let {
val newClassConstructor = newClass.getConstructor(/* no args defined */)
val newClassConstructor = newClass!!.getConstructor(/* no args defined */)
val newClassInstance = newClassConstructor.newInstance(/* no args defined */)
entryPointClasses.add(newClassInstance as ModuleEntryPoint)
@@ -141,29 +141,63 @@ object ModMgr {
catch (e: Throwable) {
printdbgerr(this, "There was an error while loading module $moduleName")
printdbgerr(this, "\t$e")
e.printStackTrace(System.err)
print(AppLoader.csiR); e.printStackTrace(System.out); print(AppLoader.csi0)
moduleInfo.remove(moduleName)
}
}
// lists available engines
/*val manager = ScriptEngineManager()
val factories = manager.engineFactories
for (f in factories) {
println("engine name:" + f.engineName)
println("engine version:" + f.engineVersion)
println("language name:" + f.languageName)
println("language version:" + f.languageVersion)
println("names:" + f.names)
println("mime:" + f.mimeTypes)
println("extension:" + f.extensions)
println("-----------------------------------------------")
}*/
}
operator fun invoke() { }
fun reloadModules() {
loadOrder.forEach {
val moduleName = it
printmsg(this, "Reloading module $moduleName")
try {
checkExistence(moduleName)
val modMetadata = moduleInfo[it]!!
val entryPoint = modMetadata.entryPoint
// run entry script in entry point
if (entryPoint.isNotBlank()) {
var newClass: Class<*>? = null
try {
newClass = Class.forName(entryPoint)
}
catch (e: ClassNotFoundException) {
printdbgerr(this, "$moduleName has nonexisting entry point, skipping...")
printdbgerr(this, "\t$e")
moduleInfo.remove(moduleName)
}
newClass?.let {
val newClassConstructor = newClass!!.getConstructor(/* no args defined */)
val newClassInstance = newClassConstructor.newInstance(/* no args defined */)
entryPointClasses.add(newClassInstance as ModuleEntryPoint)
(newClassInstance as ModuleEntryPoint).invoke()
}
}
printdbg(this, "$moduleName reloaded successfully")
}
catch (noSuchModule: FileNotFoundException) {
printdbgerr(this, "No such module: $moduleName, skipping...")
moduleInfo.remove(moduleName)
}
catch (e: Throwable) {
printdbgerr(this, "There was an error while loading module $moduleName")
printdbgerr(this, "\t$e")
print(AppLoader.csiR); e.printStackTrace(System.out); print(AppLoader.csi0)
moduleInfo.remove(moduleName)
}
}
}
private fun checkExistence(module: String) {
if (!moduleInfo.containsKey(module))
throw FileNotFoundException("No such module: $module")

View File

@@ -36,7 +36,7 @@ object PostProcessor : Disposable {
private val defaultResCol = Color(0x66ffff66)
private val safeAreaCol = Color(0xffffff66.toInt())
private val safeAreaCol2 = Color(0xffffff44.toInt())
private val currentResCol = Color(0xff00ff44.toInt())
private val currentResCol = Color(0xffffee44.toInt())
private val debugUI = BasicDebugInfoWindow()

View File

@@ -188,7 +188,7 @@ object SanicLoadScreen : LoadScreenBase() {
// log messages
it.color = messageForegroundColour
messages.forEachIndexed { i, s ->
messages.reversed().forEachIndexed { i, s ->
AppLoader.fontGame.draw(it,
s,
AppLoader.screenSize.tvSafeGraphicsWidth + 16f,
@@ -213,7 +213,7 @@ object SanicLoadScreen : LoadScreenBase() {
// log messages
it.color = messageForegroundColour
messages.forEachIndexed { i, s ->
messages.reversed().forEachIndexed { i, s ->
AppLoader.fontGame.draw(it,
s,
AppLoader.screenSize.tvSafeGraphicsWidth + 16f,

View File

@@ -20,31 +20,31 @@ import java.io.IOException
*/
class BlockCodex {
val blockProps = HashMap<ItemID, BlockProp>()
@Transient val blockProps = HashMap<ItemID, BlockProp>()
val dynamicLights = SortedArrayList<ItemID>() // does not include virtual ones
@Transient val dynamicLights = SortedArrayList<ItemID>() // does not include virtual ones
/** 65536 */
//val MAX_TERRAIN_TILES = GameWorld.TILES_SUPPORTED
@Transient private val nullProp = BlockProp()
var highestNumber = -1 // does not include virtual ones
@Transient var highestNumber = -1 // does not include virtual ones
private set
// fake props for "randomised" dynamic lights
@Transient val DYNAMIC_RANDOM_CASES = 64
private var virtualTileCursor = 1
@Transient private var virtualTileCursor = 1
/**
* One-to-Many
*/
val tileToVirtual = HashMap<ItemID, List<ItemID>>()
@Transient val tileToVirtual = HashMap<ItemID, List<ItemID>>()
/**
* Many-to-One
*/
val virtualToTile = HashMap<ItemID, ItemID>()
@Transient val virtualToTile = HashMap<ItemID, ItemID>()
fun clear() {
blockProps.clear()

View File

@@ -15,7 +15,7 @@ import java.io.IOException
*/
class WireCodex {
val wireProps = HashMap<ItemID, WireProp>()
@Transient val wireProps = HashMap<ItemID, WireProp>()
@Transient private val nullProp = WireProp()

View File

@@ -3,9 +3,11 @@ package net.torvald.terrarum.gameactors
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.AppLoader.printdbgerr
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
@@ -40,7 +42,7 @@ open class ActorWithBody : Actor {
var physProp = PhysProperties.HUMANOID_DEFAULT
protected constructor()
protected constructor() : super()
constructor(renderOrder: RenderOrder, physProp: PhysProperties, id: ActorID? = null) : super(renderOrder, id) {
this.physProp = physProp
@@ -1644,11 +1646,19 @@ open class ActorWithBody : Actor {
)
}
else {
sprite.render(batch,
(hitbox.startX - offsetX).toFloat(),
(hitbox.startY - offsetY).toFloat(),
(scale).toFloat()
)
try {
sprite.render(batch,
(hitbox.startX - offsetX).toFloat(),
(hitbox.startY - offsetY).toFloat(),
(scale).toFloat()
)
}
catch (e: UninitializedPropertyAccessException) {
printdbgerr(this, this.javaClass.simpleName)
printdbgerr(this, actorValue.getAsString(AVKey.NAME))
printdbgerr(this, if (this is HasAssembledSprite) this.animDescPath else "(not HasAssembledSprite)")
printdbgerr(this, e)
}
}
}

View File

@@ -1,9 +1,9 @@
package net.torvald.terrarum.gameactors
data class PhysProperties(
val immobileBody: Boolean,
var usePhysics: Boolean,
val useStairs: Boolean
val immobileBody: Boolean = false,
var usePhysics: Boolean = true,
val useStairs: Boolean = false
) {
companion object {
val HUMANOID_DEFAULT = PhysProperties(

View File

@@ -6,7 +6,7 @@ import java.util.*
* Created by minjaesong on 2016-05-09.
*/
class FactionCodex {
val factionContainer = ArrayList<Faction>()
@Transient val factionContainer = ArrayList<Faction>()
fun clear() = factionContainer.clear()

View File

@@ -133,10 +133,7 @@ class GameWorld() : Disposable {
lastPlayTime = lastPlayTIME_T
this.totalPlayTime = totalPlayTime
postLoad()
}
fun postLoad() {
AppLoader.tileMaker.tags.forEach {
printdbg(this, "tileNumber ${it.value.tileNumber} <-> tileName ${it.key}")
@@ -148,6 +145,8 @@ class GameWorld() : Disposable {
tileNumberToNameMap[0] = Block.AIR
}
/**
* Load existing world
*/
@@ -271,7 +270,7 @@ class GameWorld() : Disposable {
*/
fun setTileTerrain(x: Int, y: Int, itemID: ItemID, bypassEvent: Boolean) {
val (x, y) = coerceXY(x, y)
val tilenum = tileNameToNumberMap[itemID]!!
val tilenum = tileNameToNumberMap[itemID] ?: throw NullPointerException("Unknown tile name $itemID")
val oldTerrain = getTileFromTerrain(x, y)
layerTerrain.unsafeSetTile(x, y, tilenum)

View File

@@ -26,9 +26,9 @@ class ItemCodex {
* <ItemID or RefID for Actor, TheItem>
* Will return corresponding Actor if ID >= ACTORID_MIN
*/
val itemCodex = HashMap<ItemID, GameItem>()
val dynamicItemDescription = HashMap<ItemID, GameItem>()
val dynamicToStaticTable = HashMap<ItemID, ItemID>()
@Transient val itemCodex = HashMap<ItemID, GameItem>()
@Transient var dynamicItemDescription = HashMap<ItemID, GameItem>(); private set
var dynamicToStaticTable = HashMap<ItemID, ItemID>(); private set
@Transient val ACTORID_MIN = ReferencingRanges.ACTORS.first
@@ -40,6 +40,17 @@ class ItemCodex {
dynamicToStaticTable.clear()
}
/**
* This method does not alter already-been-loaded itemCodex; only filles up dynamicitem-related fields
*/
fun loadFromSave(other: ItemCodex) {
this.dynamicToStaticTable = other.dynamicToStaticTable
dynamicToStaticTable.forEach { dynid, itemid ->
printdbg(this, "Loadfromsave dynid $dynid ->> $itemid")
dynamicItemDescription[dynid] = itemCodex[itemid]!!
}
}
private val itemImagePlaceholder: TextureRegion
get() = CommonResourcePool.getAsTextureRegion("itemplaceholder_24") // copper pickaxe
@@ -62,7 +73,7 @@ class ItemCodex {
if (code == null) return null
if (code.startsWith("$PREFIX_DYNAMICITEM:"))
return dynamicItemDescription[code]!!
return dynamicItemDescription[code] ?: throw NullPointerException("No ItemProp with id $code")
else if (code.startsWith("$PREFIX_ACTORITEM:")) {
val a = (Terrarum.ingame!! as TerrarumIngame).getActorByID(code.substring(6).toInt()) // actor item
if (a is CanBeAnItem) return a.itemData

View File

@@ -34,7 +34,7 @@ class Material {
class MaterialCodex {
val materialProps = HashMap<String, Material>()
@Transient val materialProps = HashMap<String, Material>()
@Transient private val nullMaterial = Material()
internal constructor()

View File

@@ -177,6 +177,7 @@ object IngameRenderer : Disposable {
operator fun invoke(
gamePaused: Boolean,
zoom: Float = 1f,
actorsRenderBehind : List<ActorWithBody>? = null,
actorsRenderMiddle : List<ActorWithBody>? = null,
actorsRenderMidTop : List<ActorWithBody>? = null,
@@ -194,7 +195,6 @@ object IngameRenderer : Disposable {
//renderingParticleCount = particlesContainer?.size ?: 0
//renderingParticleCount = (particlesContainer?.buffer?.map { (!it.flagDespawn).toInt() } ?: listOf(0)).sum()
renderingUIsCount = uiContainer?.countVisible() ?: 0
val zoom = Terrarum.ingame?.screenZoom ?: 1f
invokeInit()

View File

@@ -233,7 +233,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
IngameRenderer.setRenderedWorld(world)
super.show() // gameInitialised = true
super.show() // this function sets gameInitialised = true
}
data class NewWorldParameters(
@@ -245,11 +245,11 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
data class Codices(
val meta: WriteMeta.WorldMeta,
val block: BlockCodex,
// val block: BlockCodex,
val item: ItemCodex,
val wire: WireCodex,
val material: MaterialCodex,
val faction: FactionCodex,
// val wire: WireCodex,
// val material: MaterialCodex,
// val faction: FactionCodex,
val apocryphas: Map<String, Any>
)
@@ -270,18 +270,13 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
printdbg(this, "loaded successfully.")
}
else {
printdbg(this, "Ingame setting things up from the savegame")
RoguelikeRandomiser.loadFromSave(codices.meta.randseed0, codices.meta.randseed1)
WeatherMixer.loadFromSave(codices.meta.weatseed0, codices.meta.weatseed1)
// Load BlockCodex //
// Load WireCodex //
// Load ItemCodex //
Terrarum.itemCodex = codices.item
// Load MaterialCodex //
Terrarum.itemCodex.loadFromSave(codices.item)
Terrarum.apocryphas = HashMap(codices.apocryphas)
}
}
@@ -683,6 +678,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
IngameRenderer.invoke(
paused,
screenZoom,
visibleActorsRenderBehind,
visibleActorsRenderMiddle,
visibleActorsRenderMidTop,

View File

@@ -18,7 +18,7 @@ object ImportWorld : ConsoleCommand {
if (args.size == 2) {
try {
val reader = java.io.FileReader(AppLoader.defaultDir + "/Exports/${args[1]}.json")
ReadWorld(Terrarum.ingame!! as TerrarumIngame, reader)
ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
Echo("Importworld: imported a world from ${args[1]}.json")
}
catch (e: IOException) {
@@ -41,7 +41,7 @@ object ImportActor : ConsoleCommand {
if (args.size == 2) {
try {
val reader = java.io.FileReader(AppLoader.defaultDir + "/Exports/${args[1]}.json")
ReadActor(Terrarum.ingame!! as TerrarumIngame, reader)
ReadActor.readActorAndAddToWorld(Terrarum.ingame!! as TerrarumIngame, reader)
Echo("Importactor: imported an actor from ${args[1]}.json")
}
catch (e: IOException) {

View File

@@ -1,6 +1,10 @@
package net.torvald.terrarum.modulebasegame.console
import net.torvald.ELLIPSIS
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.ccC
import net.torvald.terrarum.ccG
import net.torvald.terrarum.ccR
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64Reader
@@ -20,12 +24,13 @@ object Load : ConsoleCommand {
override fun execute(args: Array<String>) {
if (args.size == 2) {
try {
Echo("${ccC}Changing context, ${ccR}do not touch the controller$ccC and ${ccG}wait$ccC$ELLIPSIS")
val charset = Common.CHARSET
val file = File(AppLoader.defaultDir + "/Exports/${args[1]}")
val disk = VDUtil.readDiskArchive(file, charset = charset)
val meta = ReadMeta(disk)
println(meta.loadorder.joinToString())
LoadSavegame(disk)
}
catch (e: IOException) {
Echo("Load: IOException raised.")

View File

@@ -13,7 +13,7 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureTikiTorch
@ConsoleNoExport
internal object SpawnTikiTorch : ConsoleCommand {
override fun execute(args: Array<String>) {
val torch = FixtureTikiTorch { "Tiki Torch" }
val torch = FixtureTikiTorch()
torch.setPosition(Terrarum.mouseX, Terrarum.mouseY)
Terrarum.ingame!!.addNewActor(torch)

View File

@@ -26,6 +26,8 @@ interface Electric {
}
/**
* Protip: do not make child classes take any argument, especially no function (function "classes" have no zero-arg constructor)
*
* Created by minjaesong on 2016-06-17.
*/
open class FixtureBase : ActorWithBody, CuedByTerrainChange {
@@ -37,7 +39,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
var mainUI: UICanvas? = null
var inventory: FixtureInventory? = null
protected constructor()
protected constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null)
constructor(blockBox0: BlockBox,
blockBoxProps: BlockBoxProps = BlockBoxProps(0),
@@ -45,7 +47,8 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
nameFun: () -> String,
mainUI: UICanvas? = null,
inventory: FixtureInventory? = null,
id: ActorID? = null) : super(renderOrder, PhysProperties.IMMOBILE, id) {
id: ActorID? = null
) : super(renderOrder, PhysProperties.IMMOBILE, id) {
blockBox = blockBox0
this.blockBoxProps = blockBoxProps
this.renderOrder = renderOrder
@@ -223,7 +226,10 @@ inline class BlockBoxProps(val flags: Int) {
* @param width Width of the block box, tile-wise
* @param height Height of the block box, tile-wise
*/
data class BlockBox(val collisionType: ItemID, val width: Int, val height: Int) {
data class BlockBox(
val collisionType: ItemID = NO_COLLISION,
val width: Int = 0,
val height: Int = 0) {
/*fun redefine(collisionType: Int, width: Int, height: Int) {
redefine(collisionType)
@@ -246,6 +252,6 @@ data class BlockBox(val collisionType: ItemID, val width: Int, val height: Int)
const val NO_PASS_RIGHT = Block.ACTORBLOCK_NO_PASS_RIGHT
const val NO_PASS_LEFT = Block.ACTORBLOCK_NO_PASS_LEFT
val NULL = BlockBox(NO_COLLISION, 0, 0)
val NULL = BlockBox()
}
}

View File

@@ -4,6 +4,7 @@ import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.blockproperties.WireCodex
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2
@@ -13,13 +14,15 @@ class FixtureLogicSignalEmitter : FixtureBase, Electric {
override val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
override val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
protected constructor()
constructor(nameFun: () -> String) : super(
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 1),
nameFun = nameFun)
nameFun = { Lang["ITEM_LOGIC_SIGNAL_EMITTER"] }
)
init {
println("INIT AGAIN FixtureLogicSignalEmitter")
density = 1400.0
setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, -1)

View File

@@ -32,13 +32,11 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
*/
internal class FixtureStorageChest : FixtureBase {
private constructor()
constructor(nameFun: () -> String) : super(
constructor() : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 1, 1),
mainUI = UIStorageChest(),
inventory = FixtureInventory(40, CAPACITY_MODE_COUNT),
nameFun = nameFun
nameFun = { Lang["ITEM_STORAGE_CHEST"] }
) {
(mainUI as UIStorageChest).chestInventory = this.inventory!!

View File

@@ -12,6 +12,7 @@ import net.torvald.terrarum.gameactors.Hitbox
import net.torvald.terrarum.gameactors.Luminous
import net.torvald.terrarum.gameparticles.ParticleVanishingSprite
import net.torvald.terrarum.gameparticles.ParticleVanishingText
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import java.util.*
@@ -34,11 +35,9 @@ internal class FixtureTikiTorch : FixtureBase, Luminous {
override val lightBoxList: ArrayList<Hitbox> = ArrayList(1)
private constructor()
constructor(nameFun: () -> String) : super(
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 2),
nameFun = nameFun
nameFun = { Lang["ITEM_TIKI_TORCH"] }
) {
// loading textures

View File

@@ -19,7 +19,7 @@ class TapestryObject : FixtureBase {
var artName = ""; private set
var artAuthor = ""; private set
private constructor()
private constructor() : super()
constructor(pixmap: Pixmap, artName: String, artAuthor: String, nameFun: () -> String) : super() {
this.artName = artName

View File

@@ -15,7 +15,7 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter
class ItemLogicSignalEmitter(originalID: ItemID) : GameItem(originalID) {
override var dynamicID: ItemID = originalID
override val originalName = "ITEM_TIKI_TORCH"
override val originalName = "ITEM_LOGIC_SIGNAL_EMITTER"
override var baseMass = FixtureLogicSignalEmitter.MASS
override var stackable = true
override var inventoryCategory = Category.FIXTURE
@@ -38,7 +38,7 @@ class ItemLogicSignalEmitter(originalID: ItemID) : GameItem(originalID) {
}
override fun startPrimaryUse(delta: Float): Boolean {
val item = FixtureLogicSignalEmitter { Lang[originalName] }
val item = FixtureLogicSignalEmitter()
return item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY)
// return true when placed, false when cannot be placed

View File

@@ -32,7 +32,7 @@ class ItemStorageChest(originalID: ItemID) : GameItem(originalID) {
}
override fun startPrimaryUse(delta: Float): Boolean {
val item = FixtureStorageChest { Lang[originalName] }
val item = FixtureStorageChest()
return item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY - item.blockBox.height + 1)
// return true when placed, false when cannot be placed

View File

@@ -31,7 +31,7 @@ class TikiTorchTester(originalID: ItemID) : GameItem(originalID) {
}
override fun startPrimaryUse(delta: Float): Boolean {
val item = FixtureTikiTorch { Lang[originalName] }
val item = FixtureTikiTorch()
return item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY - item.blockBox.height + 1)
// return true when placed, false when cannot be placed

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.serialise
import net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.AppLoader.printdbgerr
import net.torvald.terrarum.NoSuchActorWithIDException
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorWithBody
@@ -25,10 +26,19 @@ object WriteActor {
fun encodeToByteArray64(actor: Actor): ByteArray64 {
val baw = ByteArray64Writer(Common.CHARSET)
val classDef = """{"class":"${actor.javaClass.canonicalName}""""
baw.write(classDef)
Common.jsoner.toJson(actor, actor.javaClass, baw)
baw.flush(); baw.close()
// by this moment, contents of the baw will be:
// {"class":"some.class.Name"{"actorValue":{},......}
// (note that first bracket is not closed, and another open bracket after "class" property)
// and we want to turn it into this:
// {"class":"some.class.Name","actorValue":{},......}
val ba = baw.toByteArray64()
ba[classDef.toByteArray(Common.CHARSET).size.toLong()] = ','.code.toByte()
return baw.toByteArray64()
return ba
}
}
@@ -45,14 +55,11 @@ object WriteActor {
*/
object ReadActor {
fun readActorOnly(worldDataStream: Reader): Actor =
Common.jsoner.fromJson(null, worldDataStream)
operator fun invoke(worldDataStream: Reader): Actor =
fillInDetails(Common.jsoner.fromJson(null, worldDataStream))
operator fun invoke(ingame: TerrarumIngame, worldDataStream: Reader): Actor =
postRead(ingame, readActorOnly(worldDataStream))
private fun postRead(ingame: TerrarumIngame, actor: Actor): Actor {
// filling in Transients
private fun fillInDetails(actor: Actor): Actor {
actor.actorValue.actor = actor
if (actor is Pocketed)
@@ -66,6 +73,13 @@ object ReadActor {
actor.reassembleSprite(actor.sprite!!, actor.spriteGlow)
}
}
return actor
}
fun readActorAndAddToWorld(ingame: TerrarumIngame, worldDataStream: Reader): Actor {
val actor = invoke(worldDataStream)
// replace existing player
val oldPlayerID = ingame.actorNowPlaying?.referenceID
try {

View File

@@ -1,6 +1,10 @@
package net.torvald.terrarum.serialise
import net.torvald.ELLIPSIS
import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.*
@@ -39,29 +43,33 @@ object WriteSavegame {
addFile(disk, meta)
// Write BlockCodex//
val blockCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(BlockCodex).toByteArray(Common.CHARSET))))
val blocks = DiskEntry(-16, 0, "blocks".toByteArray(), creation_t, time_t, blockCodexContent)
addFile(disk, blocks)
// val blockCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(BlockCodex).toByteArray(Common.CHARSET))))
// val blocks = DiskEntry(-16, 0, "blocks".toByteArray(), creation_t, time_t, blockCodexContent)
// addFile(disk, blocks)
// Commented out; nothing to write
// Write ItemCodex//
val itemCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(ItemCodex).toByteArray(Common.CHARSET))))
val items = DiskEntry(-17, 0, "items".toByteArray(), creation_t, time_t, itemCodexContent)
addFile(disk, items)
// Gotta save dynamicIDs
// Write WireCodex//
val wireCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(WireCodex).toByteArray(Common.CHARSET))))
val wires = DiskEntry(-18, 0, "wires".toByteArray(), creation_t, time_t, wireCodexContent)
addFile(disk, wires)
// val wireCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(WireCodex).toByteArray(Common.CHARSET))))
// val wires = DiskEntry(-18, 0, "wires".toByteArray(), creation_t, time_t, wireCodexContent)
// addFile(disk, wires)
// Commented out; nothing to write
// Write MaterialCodex//
val materialCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(MaterialCodex).toByteArray(Common.CHARSET))))
val materials = DiskEntry(-19, 0, "materials".toByteArray(), creation_t, time_t, materialCodexContent)
addFile(disk, materials)
// val materialCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(MaterialCodex).toByteArray(Common.CHARSET))))
// val materials = DiskEntry(-19, 0, "materials".toByteArray(), creation_t, time_t, materialCodexContent)
// addFile(disk, materials)
// Commented out; nothing to write
// Write FactionCodex//
val factionCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(FactionCodex).toByteArray(Common.CHARSET))))
val factions = DiskEntry(-20, 0, "factions".toByteArray(), creation_t, time_t, factionCodexContent)
addFile(disk, factions)
// val factionCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(FactionCodex).toByteArray(Common.CHARSET))))
// val factions = DiskEntry(-20, 0, "factions".toByteArray(), creation_t, time_t, factionCodexContent)
// addFile(disk, factions)
// Write Apocryphas//
val apocryphasContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(Apocryphas).toByteArray(Common.CHARSET))))
@@ -105,29 +113,41 @@ object LoadSavegame {
private fun getFileReader(disk: VirtualDisk, id: Int): Reader = ByteArray64Reader(getFileBytes(disk, id), Common.CHARSET)
operator fun invoke(disk: VirtualDisk) {
val ingame = TerrarumIngame(AppLoader.batch)
// 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 meta = ReadMeta(disk)
val player = ReadActor.readActorOnly(getFileReader(disk, 9545698)) as IngamePlayer
val world = ReadWorld.readWorldOnly(getFileReader(disk, player.worldCurrentlyPlaying))
val actors = world.actors.map { ReadActor.readActorOnly(getFileReader(disk, it)) }
val block = Common.jsoner.fromJson(BlockCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -16)))
val currentWorld = (ReadActor(getFileReader(disk, Terrarum.PLAYER_REF_ID)) as IngamePlayer).worldCurrentlyPlaying
val world = ReadWorld(getFileReader(disk, currentWorld))
val actors = world.actors.map { ReadActor(getFileReader(disk, it)) }
// val block = Common.jsoner.fromJson(BlockCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -16)))
val item = Common.jsoner.fromJson(ItemCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -17)))
val wire = Common.jsoner.fromJson(WireCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -18)))
val material = Common.jsoner.fromJson(MaterialCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -19)))
val faction = Common.jsoner.fromJson(FactionCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -20)))
// val wire = Common.jsoner.fromJson(WireCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -18)))
// val material = Common.jsoner.fromJson(MaterialCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -19)))
// val faction = Common.jsoner.fromJson(FactionCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -20)))
val apocryphas = Common.jsoner.fromJson(Apocryphas.javaClass, getUnzipInputStream(getFileBytes(disk, -1024)))
val ingame = TerrarumIngame(AppLoader.batch)
val worldParam = TerrarumIngame.Codices(meta, block, item, wire, material, faction, apocryphas)
val worldParam = TerrarumIngame.Codices(meta, item, apocryphas)
ingame.world = world
ingame.gameLoadInfoPayload = worldParam
ingame.gameLoadMode = TerrarumIngame.GameLoadMode.LOAD_FROM
ingame.savegameArchive = disk
actors.forEach { ingame.addNewActor(it) }
ingame.actorNowPlaying = player
// by doing this, whatever the "possession" the player had will be broken by the game load
ingame.actorNowPlaying = ingame.getActorByID(Terrarum.PLAYER_REF_ID) as IngamePlayer
// ModMgr.reloadModules()
Terrarum.setCurrentIngameInstance(ingame)
val loadScreen = SanicLoadScreen
AppLoader.setLoadScreen(loadScreen)
AppLoader.setScreen(ingame)
Echo("${ccW}Savegame loaded from $ccY${disk.getDiskNameString(Common.CHARSET)}")
printdbg(this, "Savegame loaded from ${disk.getDiskNameString(Common.CHARSET)}")
Terrarum.ingame!!.consoleHandler.setAsOpen()
}
}

View File

@@ -53,17 +53,21 @@ object WriteWorld {
*/
object ReadWorld {
fun readWorldOnly(worldDataStream: Reader): GameWorld =
Common.jsoner.fromJson(GameWorld::class.java, worldDataStream)
operator fun invoke(worldDataStream: Reader): GameWorld =
fillInDetails(Common.jsoner.fromJson(GameWorld::class.java, worldDataStream))
operator fun invoke(ingame: TerrarumIngame, worldDataStream: Reader): GameWorld =
postRead(ingame, readWorldOnly(worldDataStream))
private fun postRead(ingame: TerrarumIngame, world: GameWorld): GameWorld {
world.postLoad()
ingame.world = world
private fun fillInDetails(world: GameWorld): GameWorld {
world.tileNumberToNameMap.forEach { l, s ->
world.tileNameToNumberMap[s] = l.toInt()
}
return world
}
fun readWorldAndSetNewWorld(ingame: TerrarumIngame, worldDataStream: Reader): GameWorld {
val world = invoke(worldDataStream)
ingame.world = world
return world
}
}