new load wip

This commit is contained in:
minjaesong
2021-10-11 17:46:46 +09:00
parent 198237dee2
commit ef603ec5d5
26 changed files with 250 additions and 285 deletions

View File

@@ -7,7 +7,6 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.EMDASH
import net.torvald.terrarum.*
import net.torvald.terrarum.App.*
import net.torvald.terrarum.Terrarum.PLAYER_REF_ID
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.blockproperties.BlockPropUtil
@@ -24,7 +23,6 @@ import net.torvald.terrarum.gameitem.inInteractableRange
import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.WorldSimulator
import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.modulebasegame.gameactors.*
import net.torvald.terrarum.modulebasegame.gameactors.physicssolver.CollisionSolver
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
@@ -34,9 +32,12 @@ import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldgenParams
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.serialise.*
import net.torvald.terrarum.serialise.Common
import net.torvald.terrarum.serialise.LoadSavegame
import net.torvald.terrarum.serialise.ReadActor
import net.torvald.terrarum.serialise.WriteSavegame
import net.torvald.terrarum.tvda.DiskSkimmer
import net.torvald.terrarum.tvda.VDUtil
import net.torvald.terrarum.tvda.VirtualDisk
import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UIAutosaveNotifier
import net.torvald.terrarum.ui.UICanvas
@@ -249,15 +250,17 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
}
data class Codices(
val disk: VirtualDisk,
val meta: WriteMeta.WorldMeta,
val disk: DiskSkimmer, // WORLD disk
val world: GameWorld,
// val meta: WriteMeta.WorldMeta,
// val block: BlockCodex,
val item: ItemCodex,
// val item: ItemCodex,
// val wire: WireCodex,
// val material: MaterialCodex,
// val faction: FactionCodex,
val apocryphas: Map<String, Any>,
val actors: List<ActorID>
// val apocryphas: Map<String, Any>,
val actors: List<ActorID>,
val player: IngamePlayer
)
@@ -272,13 +275,13 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
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)
RoguelikeRandomiser.loadFromSave(codices.world.randSeeds[0], codices.world.randSeeds[1])
WeatherMixer.loadFromSave(codices.world.randSeeds[2], codices.world.randSeeds[3])
Terrarum.itemCodex.loadFromSave(codices.item)
Terrarum.apocryphas = HashMap(codices.apocryphas)
// Terrarum.itemCodex.loadFromSave(codices.item)
// Terrarum.apocryphas = HashMap(codices.apocryphas)
savegameNickname = codices.disk.getDiskNameString(Common.CHARSET)
savegameNickname = codices.disk.getDiskName(Common.CHARSET)
}
}
@@ -287,18 +290,36 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
codices.actors.forEach {
try {
val actor = ReadActor(codices.disk, LoadSavegame.getFileReader(codices.disk, it.toLong()))
addNewActor(actor)
if (actor !is IngamePlayer) { // actor list should not contain IngamePlayers (see WriteWorld.preWrite) but just in case...
addNewActor(actor)
}
}
catch (e: NullPointerException) {
System.err.println("Could not read the actor ${it} from the disk")
e.printStackTrace()
if (it == PLAYER_REF_ID) throw e
// throw e // if not player, don't rethrow -- let players play the corrupted world if it loads, they'll be able to cope with their losses even though there will be buncha lone actorblocks lying around...
}
}
// assign new random referenceID for player
codices.player.referenceID = Terrarum.generateUniqueReferenceID(Actor.RenderOrder.MIDDLE)
addNewActor(codices.player)
// overwrite player's props with world's for multiplayer
// see comments on IngamePlayer.unauthorisedPlayerProps to know why this is necessary.
codices.player.backupPlayerProps(isMultiplayer) // backup first!
world.playersLastStatus[codices.player.uuid]?.let { // if nothing was saved, nothing would happen and we still keep the backup, which WriteActor looks for it
codices.player.setPosition(it.physics.position)
if (isMultiplayer) {
codices.player.actorValue = it.actorValue!!
codices.player.inventory = it.inventory!!
}
}
// by doing this, whatever the "possession" the player had will be broken by the game load
actorNowPlaying = getActorByID(Terrarum.PLAYER_REF_ID) as IngamePlayer
actorNowPlaying = codices.player
actorGamer = codices.player
makeSavegameBackupCopy() // don't put it on the postInit() or render(); postInitForNewGame calls this function on the savegamewriter's callback
}
@@ -332,10 +353,11 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
// 1. lighten the IO burden
// 2. cannot sync up the "counter" to determine whether both are finished
uiAutosaveNotifier.setAsOpen()
WriteSavegame.immediate(WriteSavegame.SaveMode.PLAYER, playerDisk, getPlayerSaveFiledesc(playerSavefileName), this, false, true) {
val saveTime_t = App.getTIME_T()
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.PLAYER, playerDisk, getPlayerSaveFiledesc(playerSavefileName), this, false, true) {
makeSavegameBackupCopy(getPlayerSaveFiledesc(playerSavefileName))
WriteSavegame.immediate(WriteSavegame.SaveMode.WORLD, worldDisk, getWorldSaveFiledesc(worldSavefileName), this, false, true) {
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.WORLD, worldDisk, getWorldSaveFiledesc(worldSavefileName), this, false, true) {
makeSavegameBackupCopy(getWorldSaveFiledesc(worldSavefileName)) // don't put it on the postInit() or render(); must be called using callback
uiAutosaveNotifier.setAsClose()
}

View File

@@ -8,17 +8,16 @@ import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.serialise.WriteActor
import net.torvald.terrarum.serialise.WriteMeta
import net.torvald.terrarum.serialise.WriteWorld
import java.io.IOException
/**
* Created by minjaesong on 2017-07-18.
*/
object ExportMeta : ConsoleCommand {
/*object ExportMeta : ConsoleCommand {
override fun execute(args: Array<String>) {
try {
val str = WriteMeta(ingame!! as TerrarumIngame, App.getTIME_T())
val str = net.torvald.terrarum.serialise.WriteMeta(ingame!! as TerrarumIngame, App.getTIME_T())
val writer = java.io.FileWriter(App.defaultDir + "/Exports/savegame.json", false)
writer.write(str)
writer.close()
@@ -33,7 +32,7 @@ object ExportMeta : ConsoleCommand {
override fun printUsage() {
Echo("Usage: Exportmeta")
}
}
}*/
object ExportWorld : ConsoleCommand {
override fun execute(args: Array<String>) {

View File

@@ -2,13 +2,14 @@ package net.torvald.terrarum.modulebasegame.gameactors
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Texture
import net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.spriteassembler.ADProperties
import net.torvald.spriteassembler.AssembleSheetPixmap
import net.torvald.terrarum.App
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.tvda.SimpleFileSystem
import net.torvald.terrarum.utils.PlayerLastStatus
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import java.util.*
@@ -21,7 +22,11 @@ import java.util.*
class IngamePlayer : ActorHumanoid {
var uuid = UUID.randomUUID(); private set
val creationTime = App.getTIME_T()
var lastPlayTime = App.getTIME_T() // cumulative value for the savegame
var totalPlayTime = 0L // cumulative value for the savegame
val uuid = UUID.randomUUID()
var worldCurrentlyPlaying: UUID = UUID(0L,0L) // only filled up on save and load; DO NOT USE THIS
/** ADL for main sprite. Necessary. */
@@ -50,6 +55,17 @@ class IngamePlayer : ActorHumanoid {
}
/** Copy of some of the player's props before get overwritten by the props saved in the world.
*
* This field is only there for loading multiplayer map on singleplayer instances where the world loader would
* permanently changing player's props into multiplayer world's.
*/
@Transient internal lateinit var unauthorisedPlayerProps: PlayerLastStatus
fun backupPlayerProps(isMultiplayer: Boolean) {
unauthorisedPlayerProps = PlayerLastStatus(this, isMultiplayer)
}
/**

View File

@@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import com.badlogic.gdx.utils.JsonReader
import net.torvald.getKeycapConsole
import net.torvald.getKeycapPC
import net.torvald.terrarum.*
@@ -14,8 +15,6 @@ import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.serialise.Common
import net.torvald.terrarum.serialise.LoadSavegame
import net.torvald.terrarum.serialise.ReadMeta
import net.torvald.terrarum.serialise.WriteMeta
import net.torvald.terrarum.tvda.*
import net.torvald.terrarum.ui.*
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
@@ -26,6 +25,9 @@ import java.util.logging.Level
import java.util.zip.GZIPInputStream
import kotlin.math.roundToInt
val SAVE_CELL_WIDTH = 480
val SAVE_CELL_HEIGHT = 120
/**
* Only works if current screen set by the App is [TitleScreen]
*
@@ -55,13 +57,13 @@ class UILoadDemoSavefiles : UICanvas() {
private val shapeRenderer = ShapeRenderer()
internal val uiWidth = UIItemDemoSaveCells.WIDTH // 480
internal val uiWidth = SAVE_CELL_WIDTH
internal val uiX = (width - uiWidth) / 2
internal val textH = App.fontGame.lineHeight.toInt()
internal val cellGap = 20
internal val cellInterval = cellGap + UIItemDemoSaveCells.HEIGHT
internal val cellInterval = cellGap + SAVE_CELL_HEIGHT
internal val gradAreaHeight = 32
internal val titleTextPosY: Int = App.scr.tvSafeGraphicsHeight + 10
@@ -106,15 +108,15 @@ class UILoadDemoSavefiles : UICanvas() {
Thread {
// read savegames
var savegamesCount = 0
App.savegames.forEach { skimmer ->
App.savegameWorlds.forEach { (uuid, skimmer) ->
val x = uiX + if (App.getConfigBoolean("fx_streamerslayout")) App.scr.chatWidth / 2 else 0
val y = titleTopGradEnd + cellInterval * savegamesCount
try {
addUIitem(UIItemDemoSaveCells(this, x, y, skimmer))
addUIitem(UIItemWorldCells(this, x, y, skimmer))
savegamesCount += 1
}
catch (e: Throwable) {
System.err.println("[UILoadDemoSavefiles] Savefile '${skimmer.diskFile.absolutePath}' cannot be loaded")
System.err.println("[UILoadDemoSavefiles] Error while loading World '${skimmer.diskFile.absolutePath}'")
e.printStackTrace()
}
@@ -290,7 +292,7 @@ class UILoadDemoSavefiles : UICanvas() {
override fun resize(width: Int, height: Int) {
super.resize(width, height)
scrollAreaHeight = height - 2 * App.scr.tvSafeGraphicsHeight - 64
savesVisible = (scrollAreaHeight + cellInterval) / (cellInterval + UIItemDemoSaveCells.HEIGHT)
savesVisible = (scrollAreaHeight + cellInterval) / (cellInterval + SAVE_CELL_HEIGHT)
listScroll = 0
scrollTarget = 0
@@ -311,49 +313,66 @@ class UILoadDemoSavefiles : UICanvas() {
class UIItemDemoSaveCells(
class UIItemPlayerCells(
parent: UILoadDemoSavefiles,
initialX: Int,
initialY: Int,
val skimmer: DiskSkimmer) : UIItem(parent, initialX, initialY) {
companion object {
const val WIDTH = 480
const val HEIGHT = 120
override val width = SAVE_CELL_WIDTH
override val height = SAVE_CELL_HEIGHT
override fun dispose() {
}
private val metaFile: DiskEntry?
}
class UIItemWorldCells(
parent: UILoadDemoSavefiles,
initialX: Int,
initialY: Int,
val skimmer: DiskSkimmer) : UIItem(parent, initialX, initialY) {
private val metaFile: EntryFile?
private val saveName: String
private val saveMode: Int
private val isQuick: Boolean
private val isAuto: Boolean
private val meta: WriteMeta.WorldMeta?
private val saveDamaged: Boolean
private var saveDamaged: Boolean = false
private val lastPlayedTimestamp: String
init {
printdbg(this, "Rebuilding skimmer for savefile ${skimmer.diskFile.absolutePath}")
skimmer.rebuild()
metaFile = skimmer.requestFile(-1)
metaFile = skimmer.getFile(-1)
if (metaFile == null) saveDamaged = true
saveName = skimmer.getDiskName(Common.CHARSET)
saveMode = skimmer.getSaveMode()
isQuick = (saveMode % 2 == 1)
isAuto = (saveMode.ushr(1) != 0)
meta = if (metaFile != null) ReadMeta.fromDiskEntry(metaFile) else null
saveDamaged = checkForSavegameDamage(skimmer)
saveDamaged = saveDamaged or checkForSavegameDamage(skimmer)
lastPlayedTimestamp = if (meta != null)
Instant.ofEpochSecond(meta.lastplay_t)
.atZone(TimeZone.getDefault().toZoneId())
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) +
"/${parseDuration(meta.playtime_t)}"
else "--:--:--/--h--m--s"
if (metaFile != null) {
val worldJson = JsonReader().parse(ByteArray64Reader(metaFile.bytes, Common.CHARSET))
val lastplay_t = worldJson["lastPlayTime"].asLong()
val playtime_t = worldJson["totalPlayTime"].asLong()
lastPlayedTimestamp =
Instant.ofEpochSecond(lastplay_t)
.atZone(TimeZone.getDefault().toZoneId())
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) +
"/${parseDuration(playtime_t)}"
}
else {
lastPlayedTimestamp = "--:--:--/--h--m--s"
}
}
private fun parseDuration(seconds: Long): String {
@@ -367,8 +386,8 @@ class UIItemDemoSaveCells(
"${d}d${h.toString().padStart(2,'0')}h${m.toString().padStart(2,'0')}m${s.toString().padStart(2,'0')}s"
}
override val width: Int = WIDTH
override val height: Int = HEIGHT
override val width: Int = SAVE_CELL_WIDTH
override val height: Int = SAVE_CELL_HEIGHT
private var thumbPixmap: Pixmap? = null
private var thumb: TextureRegion? = null

View File

@@ -2,12 +2,8 @@ package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.Second
import net.torvald.terrarum.serialise.LoadSavegame
import net.torvald.terrarum.tvda.VDUtil
import net.torvald.terrarum.ui.UICanvas
import java.util.logging.Level
/**
* Created by minjaesong on 2021-09-13.
@@ -31,11 +27,11 @@ class UIProxyLoadLatestSave : UICanvas() {
}
override fun endOpening(delta: Float) {
if (App.savegames.size > 0) {
LoadSavegame(VDUtil.readDiskArchive(App.savegames[0].diskFile, Level.INFO) {
System.err.println("Possibly damaged savefile ${App.savegames[0].diskFile.absolutePath}:\n$it")
})
}
// do something!
}
override fun endClosing(delta: Float) {

View File

@@ -12,6 +12,7 @@ object UITitleRemoConYaml {
* The class must be the UICanvas
*/
private val menuBase = """
- MENU_LABEL_NEW_GAME : net.torvald.terrarum.modulebasegame.ui.UIProxyNewRandomGame
- MENU_OPTIONS
- MENU_LABEL_GRAPHICS : net.torvald.terrarum.modulebasegame.ui.GraphicsControlPanel
- MENU_OPTIONS_CONTROLS : net.torvald.terrarum.modulebasegame.ui.UIKeyboardControlPanel
@@ -27,17 +28,15 @@ object UITitleRemoConYaml {
private val menuWithSavefile = """
- MENU_LABEL_CONTINUE : net.torvald.terrarum.modulebasegame.ui.UIProxyLoadLatestSave
- MENU_LABEL_NEW_GAME : net.torvald.terrarum.modulebasegame.ui.UIProxyNewRandomGame
- MENU_IO_LOAD : net.torvald.terrarum.modulebasegame.ui.UILoadDemoSavefiles
- MENU_LABEL_RETURN
"""
- MENU_LABEL_NEW_WORLD
- MENU_LABEL_RETURN"""
private val menuNewGame = """
- MENU_LABEL_NEW_GAME : net.torvald.terrarum.modulebasegame.ui.UIProxyNewRandomGame
"""
operator fun invoke(hasSave: Boolean) =
Yaml((if (hasSave) menuWithSavefile else menuNewGame) + menuBase).parse()
Yaml((if (!hasSave) menuWithSavefile else menuNewGame) + menuBase).parse()
}