fixed a bug where a dynamic item would not get saved/loaded at all

This commit is contained in:
minjaesong
2022-02-22 17:12:49 +09:00
parent 1787ad7cdd
commit df6950c0b8
30 changed files with 206 additions and 89 deletions

View File

@@ -329,4 +329,4 @@ object Common {
}
class SaveLoadError(file: File, cause: Throwable) : RuntimeException("An error occured while loading save file '${file.absolutePath}'", cause)
class SaveLoadError(file: File?, cause: Throwable) : RuntimeException("An error occured while loading save file '${file?.absolutePath}'", cause)

View File

@@ -2,13 +2,20 @@ package net.torvald.terrarum.serialise
import net.torvald.gdx.graphics.PixmapIO2
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.ItemCodex
import net.torvald.terrarum.ReferencingRanges.PREFIX_DYNAMICITEM
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.itemproperties.ItemRemapTable
import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.toInt
import net.torvald.terrarum.savegame.*
import java.io.File
import java.util.HashMap
import java.util.zip.GZIPOutputStream
/**
@@ -61,14 +68,14 @@ class WorldSavingThread(
val allTheActors = ingame.actorContainerActive.cloneToList() + ingame.actorContainerInactive.cloneToList()
val playersList: List<IngamePlayer> = allTheActors.filter{ it is IngamePlayer } as List<IngamePlayer>
val playersList: List<IngamePlayer> = allTheActors.filterIsInstance<IngamePlayer>()
val actorsList = allTheActors.filter { WriteWorld.actorAcceptable(it) }
val layers = intArrayOf(0,1).map { ingame.world.getLayer(it) }
val cw = ingame.world.width / LandUtil.CHUNK_W
val ch = ingame.world.height / LandUtil.CHUNK_H
WriteSavegame.saveProgress = 0f
WriteSavegame.saveProgressMax = 2f + (cw * ch * layers.size) + actorsList.size
WriteSavegame.saveProgressMax = 3f + (cw * ch * layers.size) + actorsList.size
val tgaout = ByteArray64GrowableOutputStream()
@@ -79,6 +86,39 @@ class WorldSavingThread(
val creation_t = ingame.world.creationTime
// Write subset of Ingame.ItemCodex
// The existing ItemCodex must be rewritten to clear out obsolete records
// We're assuming the dynamic item generated by players does exist in the world, and it's recorded
// into the world's dynamicToStaticTable, therefore every item recorded into the world's dynamicToStaticTable
// can be found in this world without need to look up the players
ingame.world.dynamicToStaticTable.clear()
ingame.world.dynamicItemInventory.clear()
actorsList.filterIsInstance<Pocketed>().forEach { actor ->
actor.inventory.forEach { (itemid, _) ->
printdbg(this, "World side dynamicitem: $itemid contained in $actor")
if (itemid.startsWith("$PREFIX_DYNAMICITEM:")) {
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
}
}
}
actorsList.filterIsInstance<FixtureBase>().forEach { fixture ->
fixture.inventory?.forEach { (itemid, _) ->
printdbg(this, "World side dynamicitem: $itemid contained in $fixture")
if (itemid.startsWith("$PREFIX_DYNAMICITEM:")) {
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
}
}
}
if (hasThumbnail) {
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
IngameRenderer.fboRGBexport.dispose()

View File

@@ -4,9 +4,12 @@ import net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.terrarum.spriteassembler.ADProperties
import net.torvald.terrarum.ItemCodex
import net.torvald.terrarum.ReferencingRanges.PREFIX_DYNAMICITEM
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.itemproperties.ItemRemapTable
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.savegame.*
@@ -74,6 +77,17 @@ object WritePlayer {
player.worldCurrentlyPlaying = ingame?.world?.worldIndex ?: UUID(0L,0L)
// Write subset of Ingame.ItemCodex
// The existing ItemCodex must be rewritten to clear out obsolete records
player.dynamicToStaticTable.clear()
player.dynamicItemInventory.clear()
player.inventory.forEach { (itemid, _) ->
if (itemid.startsWith("$PREFIX_DYNAMICITEM:")) {
player.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
player.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
}
}
val actorJson = WriteActor.encodeToByteArray64(player)
val adl = player.animDesc!!.getRawADL()
@@ -142,6 +156,8 @@ object ReadActor {
actor.animDescGlow = ADProperties(ByteArray64Reader(animFileGlow.bytes, Common.CHARSET))
}
ItemCodex.loadFromSave(disk.getBackingFile(), actor.dynamicToStaticTable, actor.dynamicItemInventory)
val heldItem = ItemCodex[actor.inventory.itemEquipped[GameItem.EquipPosition.HAND_GRIP]]
if (bodypartsFile != null)

View File

@@ -125,7 +125,7 @@ object LoadSavegame {
val currentWorldId = player.worldCurrentlyPlaying
val worldDisk = worldDisk0 ?: App.savegameWorlds[currentWorldId]!!
val world = ReadWorld(ByteArray64Reader(worldDisk.getFile(-1L)!!.bytes, Common.CHARSET))
val world = ReadWorld(ByteArray64Reader(worldDisk.getFile(-1L)!!.bytes, Common.CHARSET), worldDisk.diskFile)
world.layerTerrain = BlockLayer(world.width, world.height)
world.layerWall = BlockLayer(world.width, world.height)

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.serialise
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.ItemCodex
import net.torvald.terrarum.ReferencingRanges
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.BlockMarkerActor
@@ -15,6 +16,7 @@ import net.torvald.terrarum.savegame.ByteArray64
import net.torvald.terrarum.savegame.ByteArray64Writer
import net.torvald.terrarum.utils.PlayerLastStatus
import net.torvald.terrarum.weather.WeatherMixer
import java.io.File
import java.io.Reader
/**
@@ -90,22 +92,24 @@ object WriteWorld {
*/
object ReadWorld {
fun readLayerFormat(worldDataStream: Reader): GameWorld =
fillInDetails(Common.jsoner.fromJson(GameWorldTitleScreen::class.java, worldDataStream))
fun readLayerFormat(worldDataStream: Reader, origin: File?): GameWorld =
fillInDetails(Common.jsoner.fromJson(GameWorldTitleScreen::class.java, worldDataStream), origin)
operator fun invoke(worldDataStream: Reader): GameWorld =
fillInDetails(Common.jsoner.fromJson(GameWorld::class.java, worldDataStream))
operator fun invoke(worldDataStream: Reader, origin: File?): GameWorld =
fillInDetails(Common.jsoner.fromJson(GameWorld::class.java, worldDataStream), origin)
private fun fillInDetails(world: GameWorld): GameWorld {
private fun fillInDetails(world: GameWorld, origin: File?): GameWorld {
world.tileNumberToNameMap.forEach { l, s ->
world.tileNameToNumberMap[s] = l.toInt()
}
ItemCodex.loadFromSave(origin, world.dynamicToStaticTable, world.dynamicItemInventory)
return world
}
fun readWorldAndSetNewWorld(ingame: TerrarumIngame, worldDataStream: Reader): GameWorld {
val world = readLayerFormat(worldDataStream)
fun readWorldAndSetNewWorld(ingame: TerrarumIngame, worldDataStream: Reader, origin: File?): GameWorld {
val world = readLayerFormat(worldDataStream, origin)
ingame.world = world
return world
}