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) { public static void printdbg(Object obj, Object message) {
if (IS_DEVELOPMENT_BUILD) { if (IS_DEVELOPMENT_BUILD) {
String out = (obj instanceof String) ? (String) obj : obj.getClass().getSimpleName(); String out = (obj instanceof String) ? (String) obj : obj.getClass().getSimpleName();
@@ -1153,9 +1156,9 @@ public class AppLoader implements ApplicationListener {
if (IS_DEVELOPMENT_BUILD) { if (IS_DEVELOPMENT_BUILD) {
String out = (obj instanceof String) ? (String) obj : obj.getClass().getSimpleName(); String out = (obj instanceof String) ? (String) obj : obj.getClass().getSimpleName();
if (message == null) if (message == null)
System.err.println("[" + out + "] null"); System.out.println(csiR + "[" + out + "] null" + csi0);
else 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 class LoadScreenBase : ScreenAdapter(), Disposable {
open var preLoadJob: (LoadScreenBase) -> Unit = {}
open var screenToLoad: IngameInstance? = null open var screenToLoad: IngameInstance? = null
open lateinit var screenLoadingThread: Thread open lateinit var screenLoadingThread: Thread
@@ -33,6 +34,7 @@ open class LoadScreenBase : ScreenAdapter(), Disposable {
else { else {
val runnable = { val runnable = {
try { try {
preLoadJob(this)
screenToLoad!!.show() screenToLoad!!.show()
} }
catch (e: Exception) { catch (e: Exception) {

View File

@@ -123,7 +123,7 @@ object ModMgr {
} }
newClass?.let { newClass?.let {
val newClassConstructor = newClass.getConstructor(/* no args defined */) val newClassConstructor = newClass!!.getConstructor(/* no args defined */)
val newClassInstance = newClassConstructor.newInstance(/* no args defined */) val newClassInstance = newClassConstructor.newInstance(/* no args defined */)
entryPointClasses.add(newClassInstance as ModuleEntryPoint) entryPointClasses.add(newClassInstance as ModuleEntryPoint)
@@ -141,29 +141,63 @@ object ModMgr {
catch (e: Throwable) { catch (e: Throwable) {
printdbgerr(this, "There was an error while loading module $moduleName") printdbgerr(this, "There was an error while loading module $moduleName")
printdbgerr(this, "\t$e") printdbgerr(this, "\t$e")
e.printStackTrace(System.err) print(AppLoader.csiR); e.printStackTrace(System.out); print(AppLoader.csi0)
moduleInfo.remove(moduleName) 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() { } 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) { private fun checkExistence(module: String) {
if (!moduleInfo.containsKey(module)) if (!moduleInfo.containsKey(module))
throw FileNotFoundException("No such module: $module") throw FileNotFoundException("No such module: $module")

View File

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

View File

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

View File

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

View File

@@ -15,7 +15,7 @@ import java.io.IOException
*/ */
class WireCodex { class WireCodex {
val wireProps = HashMap<ItemID, WireProp>() @Transient val wireProps = HashMap<ItemID, WireProp>()
@Transient private val nullProp = 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.Input
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 net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.spriteanimation.SpriteAnimation import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg 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_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
@@ -40,7 +42,7 @@ open class ActorWithBody : Actor {
var physProp = PhysProperties.HUMANOID_DEFAULT var physProp = PhysProperties.HUMANOID_DEFAULT
protected constructor() protected constructor() : super()
constructor(renderOrder: RenderOrder, physProp: PhysProperties, id: ActorID? = null) : super(renderOrder, id) { constructor(renderOrder: RenderOrder, physProp: PhysProperties, id: ActorID? = null) : super(renderOrder, id) {
this.physProp = physProp this.physProp = physProp
@@ -1644,11 +1646,19 @@ open class ActorWithBody : Actor {
) )
} }
else { else {
sprite.render(batch, try {
(hitbox.startX - offsetX).toFloat(), sprite.render(batch,
(hitbox.startY - offsetY).toFloat(), (hitbox.startX - offsetX).toFloat(),
(scale).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 package net.torvald.terrarum.gameactors
data class PhysProperties( data class PhysProperties(
val immobileBody: Boolean, val immobileBody: Boolean = false,
var usePhysics: Boolean, var usePhysics: Boolean = true,
val useStairs: Boolean val useStairs: Boolean = false
) { ) {
companion object { companion object {
val HUMANOID_DEFAULT = PhysProperties( val HUMANOID_DEFAULT = PhysProperties(

View File

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

View File

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

View File

@@ -26,9 +26,9 @@ class ItemCodex {
* <ItemID or RefID for Actor, TheItem> * <ItemID or RefID for Actor, TheItem>
* Will return corresponding Actor if ID >= ACTORID_MIN * Will return corresponding Actor if ID >= ACTORID_MIN
*/ */
val itemCodex = HashMap<ItemID, GameItem>() @Transient val itemCodex = HashMap<ItemID, GameItem>()
val dynamicItemDescription = HashMap<ItemID, GameItem>() @Transient var dynamicItemDescription = HashMap<ItemID, GameItem>(); private set
val dynamicToStaticTable = HashMap<ItemID, ItemID>() var dynamicToStaticTable = HashMap<ItemID, ItemID>(); private set
@Transient val ACTORID_MIN = ReferencingRanges.ACTORS.first @Transient val ACTORID_MIN = ReferencingRanges.ACTORS.first
@@ -40,6 +40,17 @@ class ItemCodex {
dynamicToStaticTable.clear() 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 private val itemImagePlaceholder: TextureRegion
get() = CommonResourcePool.getAsTextureRegion("itemplaceholder_24") // copper pickaxe get() = CommonResourcePool.getAsTextureRegion("itemplaceholder_24") // copper pickaxe
@@ -62,7 +73,7 @@ class ItemCodex {
if (code == null) return null if (code == null) return null
if (code.startsWith("$PREFIX_DYNAMICITEM:")) if (code.startsWith("$PREFIX_DYNAMICITEM:"))
return dynamicItemDescription[code]!! return dynamicItemDescription[code] ?: throw NullPointerException("No ItemProp with id $code")
else if (code.startsWith("$PREFIX_ACTORITEM:")) { else if (code.startsWith("$PREFIX_ACTORITEM:")) {
val a = (Terrarum.ingame!! as TerrarumIngame).getActorByID(code.substring(6).toInt()) // actor item val a = (Terrarum.ingame!! as TerrarumIngame).getActorByID(code.substring(6).toInt()) // actor item
if (a is CanBeAnItem) return a.itemData if (a is CanBeAnItem) return a.itemData

View File

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

View File

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

View File

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

View File

@@ -18,7 +18,7 @@ object ImportWorld : ConsoleCommand {
if (args.size == 2) { if (args.size == 2) {
try { try {
val reader = java.io.FileReader(AppLoader.defaultDir + "/Exports/${args[1]}.json") 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") Echo("Importworld: imported a world from ${args[1]}.json")
} }
catch (e: IOException) { catch (e: IOException) {
@@ -41,7 +41,7 @@ object ImportActor : ConsoleCommand {
if (args.size == 2) { if (args.size == 2) {
try { try {
val reader = java.io.FileReader(AppLoader.defaultDir + "/Exports/${args[1]}.json") 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") Echo("Importactor: imported an actor from ${args[1]}.json")
} }
catch (e: IOException) { catch (e: IOException) {

View File

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

View File

@@ -13,7 +13,7 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureTikiTorch
@ConsoleNoExport @ConsoleNoExport
internal object SpawnTikiTorch : ConsoleCommand { internal object SpawnTikiTorch : ConsoleCommand {
override fun execute(args: Array<String>) { override fun execute(args: Array<String>) {
val torch = FixtureTikiTorch { "Tiki Torch" } val torch = FixtureTikiTorch()
torch.setPosition(Terrarum.mouseX, Terrarum.mouseY) torch.setPosition(Terrarum.mouseX, Terrarum.mouseY)
Terrarum.ingame!!.addNewActor(torch) 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. * Created by minjaesong on 2016-06-17.
*/ */
open class FixtureBase : ActorWithBody, CuedByTerrainChange { open class FixtureBase : ActorWithBody, CuedByTerrainChange {
@@ -37,7 +39,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
var mainUI: UICanvas? = null var mainUI: UICanvas? = null
var inventory: FixtureInventory? = null var inventory: FixtureInventory? = null
protected constructor() protected constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null)
constructor(blockBox0: BlockBox, constructor(blockBox0: BlockBox,
blockBoxProps: BlockBoxProps = BlockBoxProps(0), blockBoxProps: BlockBoxProps = BlockBoxProps(0),
@@ -45,7 +47,8 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
nameFun: () -> String, nameFun: () -> String,
mainUI: UICanvas? = null, mainUI: UICanvas? = null,
inventory: FixtureInventory? = null, inventory: FixtureInventory? = null,
id: ActorID? = null) : super(renderOrder, PhysProperties.IMMOBILE, id) { id: ActorID? = null
) : super(renderOrder, PhysProperties.IMMOBILE, id) {
blockBox = blockBox0 blockBox = blockBox0
this.blockBoxProps = blockBoxProps this.blockBoxProps = blockBoxProps
this.renderOrder = renderOrder this.renderOrder = renderOrder
@@ -223,7 +226,10 @@ inline class BlockBoxProps(val flags: Int) {
* @param width Width of the block box, tile-wise * @param width Width of the block box, tile-wise
* @param height Height 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) { /*fun redefine(collisionType: Int, width: Int, height: Int) {
redefine(collisionType) 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_RIGHT = Block.ACTORBLOCK_NO_PASS_RIGHT
const val NO_PASS_LEFT = Block.ACTORBLOCK_NO_PASS_LEFT 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.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.blockproperties.WireCodex import net.torvald.terrarum.blockproperties.WireCodex
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2 import org.dyn4j.geometry.Vector2
@@ -13,13 +14,15 @@ class FixtureLogicSignalEmitter : FixtureBase, Electric {
override val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap() override val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
override val wireConsumption: 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), BlockBox(BlockBox.NO_COLLISION, 1, 1),
nameFun = nameFun) nameFun = { Lang["ITEM_LOGIC_SIGNAL_EMITTER"] }
)
init { init {
println("INIT AGAIN FixtureLogicSignalEmitter")
density = 1400.0 density = 1400.0
setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, -1) setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, -1)

View File

@@ -32,13 +32,11 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
*/ */
internal class FixtureStorageChest : FixtureBase { internal class FixtureStorageChest : FixtureBase {
private constructor() constructor() : super(
constructor(nameFun: () -> String) : super(
BlockBox(BlockBox.ALLOW_MOVE_DOWN, 1, 1), BlockBox(BlockBox.ALLOW_MOVE_DOWN, 1, 1),
mainUI = UIStorageChest(), mainUI = UIStorageChest(),
inventory = FixtureInventory(40, CAPACITY_MODE_COUNT), inventory = FixtureInventory(40, CAPACITY_MODE_COUNT),
nameFun = nameFun nameFun = { Lang["ITEM_STORAGE_CHEST"] }
) { ) {
(mainUI as UIStorageChest).chestInventory = this.inventory!! (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.gameactors.Luminous
import net.torvald.terrarum.gameparticles.ParticleVanishingSprite import net.torvald.terrarum.gameparticles.ParticleVanishingSprite
import net.torvald.terrarum.gameparticles.ParticleVanishingText import net.torvald.terrarum.gameparticles.ParticleVanishingText
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import java.util.* import java.util.*
@@ -34,11 +35,9 @@ internal class FixtureTikiTorch : FixtureBase, Luminous {
override val lightBoxList: ArrayList<Hitbox> = ArrayList(1) override val lightBoxList: ArrayList<Hitbox> = ArrayList(1)
private constructor() constructor() : super(
constructor(nameFun: () -> String) : super(
BlockBox(BlockBox.NO_COLLISION, 1, 2), BlockBox(BlockBox.NO_COLLISION, 1, 2),
nameFun = nameFun nameFun = { Lang["ITEM_TIKI_TORCH"] }
) { ) {
// loading textures // loading textures

View File

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

View File

@@ -15,7 +15,7 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter
class ItemLogicSignalEmitter(originalID: ItemID) : GameItem(originalID) { class ItemLogicSignalEmitter(originalID: ItemID) : GameItem(originalID) {
override var dynamicID: ItemID = 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 baseMass = FixtureLogicSignalEmitter.MASS
override var stackable = true override var stackable = true
override var inventoryCategory = Category.FIXTURE override var inventoryCategory = Category.FIXTURE
@@ -38,7 +38,7 @@ class ItemLogicSignalEmitter(originalID: ItemID) : GameItem(originalID) {
} }
override fun startPrimaryUse(delta: Float): Boolean { override fun startPrimaryUse(delta: Float): Boolean {
val item = FixtureLogicSignalEmitter { Lang[originalName] } val item = FixtureLogicSignalEmitter()
return item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY) return item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY)
// return true when placed, false when cannot be placed // 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 { 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 item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY - item.blockBox.height + 1)
// return true when placed, false when cannot be placed // 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 { 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 item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY - item.blockBox.height + 1)
// return true when placed, false when cannot be placed // 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.HasAssembledSprite
import net.torvald.spriteanimation.SpriteAnimation import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.AppLoader.printdbgerr
import net.torvald.terrarum.NoSuchActorWithIDException import net.torvald.terrarum.NoSuchActorWithIDException
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameactors.ActorWithBody
@@ -25,10 +26,19 @@ object WriteActor {
fun encodeToByteArray64(actor: Actor): ByteArray64 { fun encodeToByteArray64(actor: Actor): ByteArray64 {
val baw = ByteArray64Writer(Common.CHARSET) val baw = ByteArray64Writer(Common.CHARSET)
val classDef = """{"class":"${actor.javaClass.canonicalName}""""
baw.write(classDef)
Common.jsoner.toJson(actor, actor.javaClass, baw) Common.jsoner.toJson(actor, actor.javaClass, baw)
baw.flush(); baw.close() 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 { object ReadActor {
fun readActorOnly(worldDataStream: Reader): Actor = operator fun invoke(worldDataStream: Reader): Actor =
Common.jsoner.fromJson(null, worldDataStream) 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 { private fun fillInDetails(actor: Actor): Actor {
// filling in Transients
actor.actorValue.actor = actor actor.actorValue.actor = actor
if (actor is Pocketed) if (actor is Pocketed)
@@ -66,6 +73,13 @@ object ReadActor {
actor.reassembleSprite(actor.sprite!!, actor.spriteGlow) actor.reassembleSprite(actor.sprite!!, actor.spriteGlow)
} }
} }
return actor
}
fun readActorAndAddToWorld(ingame: TerrarumIngame, worldDataStream: Reader): Actor {
val actor = invoke(worldDataStream)
// replace existing player // replace existing player
val oldPlayerID = ingame.actorNowPlaying?.referenceID val oldPlayerID = ingame.actorNowPlaying?.referenceID
try { try {

View File

@@ -1,6 +1,10 @@
package net.torvald.terrarum.serialise package net.torvald.terrarum.serialise
import net.torvald.ELLIPSIS
import net.torvald.terrarum.* 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.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.* import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.*
@@ -39,29 +43,33 @@ object WriteSavegame {
addFile(disk, meta) addFile(disk, meta)
// Write BlockCodex// // Write BlockCodex//
val blockCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(BlockCodex).toByteArray(Common.CHARSET)))) // 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) // val blocks = DiskEntry(-16, 0, "blocks".toByteArray(), creation_t, time_t, blockCodexContent)
addFile(disk, blocks) // addFile(disk, blocks)
// Commented out; nothing to write
// Write ItemCodex// // Write ItemCodex//
val itemCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(ItemCodex).toByteArray(Common.CHARSET)))) 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) val items = DiskEntry(-17, 0, "items".toByteArray(), creation_t, time_t, itemCodexContent)
addFile(disk, items) addFile(disk, items)
// Gotta save dynamicIDs
// Write WireCodex// // Write WireCodex//
val wireCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(WireCodex).toByteArray(Common.CHARSET)))) // 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) // val wires = DiskEntry(-18, 0, "wires".toByteArray(), creation_t, time_t, wireCodexContent)
addFile(disk, wires) // addFile(disk, wires)
// Commented out; nothing to write
// Write MaterialCodex// // Write MaterialCodex//
val materialCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(MaterialCodex).toByteArray(Common.CHARSET)))) // 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) // val materials = DiskEntry(-19, 0, "materials".toByteArray(), creation_t, time_t, materialCodexContent)
addFile(disk, materials) // addFile(disk, materials)
// Commented out; nothing to write
// Write FactionCodex// // Write FactionCodex//
val factionCodexContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(FactionCodex).toByteArray(Common.CHARSET)))) // 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) // val factions = DiskEntry(-20, 0, "factions".toByteArray(), creation_t, time_t, factionCodexContent)
addFile(disk, factions) // addFile(disk, factions)
// Write Apocryphas// // Write Apocryphas//
val apocryphasContent = EntryFile(zip(ByteArray64.fromByteArray(Common.jsoner.toJson(Apocryphas).toByteArray(Common.CHARSET)))) 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) private fun getFileReader(disk: VirtualDisk, id: Int): Reader = ByteArray64Reader(getFileBytes(disk, id), Common.CHARSET)
operator fun invoke(disk: VirtualDisk) { 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 meta = ReadMeta(disk)
val player = ReadActor.readActorOnly(getFileReader(disk, 9545698)) as IngamePlayer val currentWorld = (ReadActor(getFileReader(disk, Terrarum.PLAYER_REF_ID)) as IngamePlayer).worldCurrentlyPlaying
val world = ReadWorld.readWorldOnly(getFileReader(disk, player.worldCurrentlyPlaying)) val world = ReadWorld(getFileReader(disk, currentWorld))
val actors = world.actors.map { ReadActor.readActorOnly(getFileReader(disk, it)) } val actors = world.actors.map { ReadActor(getFileReader(disk, it)) }
val block = Common.jsoner.fromJson(BlockCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -16))) // val block = Common.jsoner.fromJson(BlockCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -16)))
val item = Common.jsoner.fromJson(ItemCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -17))) val item = Common.jsoner.fromJson(ItemCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -17)))
val wire = Common.jsoner.fromJson(WireCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -18))) // val wire = Common.jsoner.fromJson(WireCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -18)))
val material = Common.jsoner.fromJson(MaterialCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -19))) // val material = Common.jsoner.fromJson(MaterialCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -19)))
val faction = Common.jsoner.fromJson(FactionCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -20))) // val faction = Common.jsoner.fromJson(FactionCodex.javaClass, getUnzipInputStream(getFileBytes(disk, -20)))
val apocryphas = Common.jsoner.fromJson(Apocryphas.javaClass, getUnzipInputStream(getFileBytes(disk, -1024))) val apocryphas = Common.jsoner.fromJson(Apocryphas.javaClass, getUnzipInputStream(getFileBytes(disk, -1024)))
val ingame = TerrarumIngame(AppLoader.batch) val worldParam = TerrarumIngame.Codices(meta, item, apocryphas)
val worldParam = TerrarumIngame.Codices(meta, block, item, wire, material, faction, apocryphas)
ingame.world = world ingame.world = world
ingame.gameLoadInfoPayload = worldParam ingame.gameLoadInfoPayload = worldParam
ingame.gameLoadMode = TerrarumIngame.GameLoadMode.LOAD_FROM ingame.gameLoadMode = TerrarumIngame.GameLoadMode.LOAD_FROM
ingame.savegameArchive = disk ingame.savegameArchive = disk
actors.forEach { ingame.addNewActor(it) } 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) Terrarum.setCurrentIngameInstance(ingame)
val loadScreen = SanicLoadScreen AppLoader.setScreen(ingame)
AppLoader.setLoadScreen(loadScreen)
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 { object ReadWorld {
fun readWorldOnly(worldDataStream: Reader): GameWorld = operator fun invoke(worldDataStream: Reader): GameWorld =
Common.jsoner.fromJson(GameWorld::class.java, worldDataStream) fillInDetails(Common.jsoner.fromJson(GameWorld::class.java, worldDataStream))
operator fun invoke(ingame: TerrarumIngame, worldDataStream: Reader): GameWorld = private fun fillInDetails(world: GameWorld): GameWorld {
postRead(ingame, readWorldOnly(worldDataStream)) world.tileNumberToNameMap.forEach { l, s ->
world.tileNameToNumberMap[s] = l.toInt()
private fun postRead(ingame: TerrarumIngame, world: GameWorld): GameWorld { }
world.postLoad()
ingame.world = world
return world return world
} }
fun readWorldAndSetNewWorld(ingame: TerrarumIngame, worldDataStream: Reader): GameWorld {
val world = invoke(worldDataStream)
ingame.world = world
return world
}
} }