mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-12 14:51:51 +09:00
new player save format writing
This commit is contained in:
@@ -14,7 +14,7 @@ The main game directory is composed of following directories:
|
|||||||
- <e.g. Disk GUID>, TEVD { * }
|
- <e.g. Disk GUID>, TEVD { * }
|
||||||
- <this directory can have anything>
|
- <this directory can have anything>
|
||||||
+ Worlds
|
+ Worlds
|
||||||
- <World Name Here>, TVDA { (-1) WriteWorld, (actorID) actors (mainly fixtures) JSON, (0x1_0000_0000 + (layerNumber << 24) + chunkNumber) chunk data, (-2) screenshot.tga.gz taken by the last player }
|
- <World Name Here>, TVDA { (-1) WriteWorld, (actorID) actors (mainly fixtures) JSON, (0x1_0000_0000L or (layerNumber shl 24) or chunkNumber) chunk data, (-2) screenshot.tga.gz taken by the last player }
|
||||||
```
|
```
|
||||||
|
|
||||||
(TEVD stands for Terrarum Virtual Disk spec version 3, TVDA stands for spec version 254; both have MAGIC header of `TEVd`)
|
(TEVD stands for Terrarum Virtual Disk spec version 3, TVDA stands for spec version 254; both have MAGIC header of `TEVd`)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
"strengthmult": [90,95,98,100,102,105,110],
|
"strengthmult": [90,95,98,100,102,105,110],
|
||||||
|
|
||||||
"accel": 0.67,
|
"accel": 0.67,
|
||||||
"accelbuff": 1.0,
|
|
||||||
|
|
||||||
"speed": 3.0,
|
"speed": 3.0,
|
||||||
"speedmult": [100,100,100,100,100,100,100],
|
"speedmult": [100,100,100,100,100,100,100],
|
||||||
@@ -22,8 +21,8 @@
|
|||||||
"scalemult": [100,100,100,100,100,100,100],
|
"scalemult": [100,100,100,100,100,100,100],
|
||||||
|
|
||||||
"encumbrance": 1000,
|
"encumbrance": 1000,
|
||||||
"basedefence": 100,
|
"defence": 100,
|
||||||
"basereach": 84,
|
"reach": 84,
|
||||||
|
|
||||||
"toolsize": 15,
|
"toolsize": 15,
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
"strengthmult": [90,95,98,100,102,105,110],
|
"strengthmult": [90,95,98,100,102,105,110],
|
||||||
|
|
||||||
"accel": 0.67,
|
"accel": 0.67,
|
||||||
"accelbuff": 1.0,
|
|
||||||
|
|
||||||
"speed": 6.0,
|
"speed": 6.0,
|
||||||
"speedmult": [100,100,100,100,100,100,100],
|
"speedmult": [100,100,100,100,100,100,100],
|
||||||
@@ -22,8 +21,8 @@
|
|||||||
"scalemult": [100,100,100,100,100,100,100],
|
"scalemult": [100,100,100,100,100,100,100],
|
||||||
|
|
||||||
"encumbrance": 10000,
|
"encumbrance": 10000,
|
||||||
"basedefence": 100,
|
"defence": 100,
|
||||||
"basereach": 180,
|
"reach": 180,
|
||||||
|
|
||||||
"toolsize": 40,
|
"toolsize": 40,
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
|||||||
*/
|
*/
|
||||||
interface HasAssembledSprite {
|
interface HasAssembledSprite {
|
||||||
|
|
||||||
/** ADL path for main sprite. Necessary. */
|
/** ADL for main sprite. Necessary. */
|
||||||
var animDesc: ADProperties?
|
var animDesc: ADProperties?
|
||||||
/** ADL path for glow sprite. Optional. */
|
/** ADL for glow sprite. Optional. */
|
||||||
var animDescGlow: ADProperties?
|
var animDescGlow: ADProperties?
|
||||||
|
|
||||||
// FIXME sometimes the animmation is invisible (row and nFrames mismatch -- row is changed to 1 but it's drawing 3rd frame?)
|
// FIXME sometimes the animmation is invisible (row and nFrames mismatch -- row is changed to 1 but it's drawing 3rd frame?)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ internal data class Transform(val joint: Joint, val translate: ADPropertyObject.
|
|||||||
|
|
||||||
class ADProperties {
|
class ADProperties {
|
||||||
private var fileFrom = ""
|
private var fileFrom = ""
|
||||||
private var adlString = ""
|
@Transient private var adlString = ""
|
||||||
private val javaProp = Properties()
|
private val javaProp = Properties()
|
||||||
|
|
||||||
/** Every key is CAPITALISED */
|
/** Every key is CAPITALISED */
|
||||||
@@ -52,8 +52,8 @@ class ADProperties {
|
|||||||
/** an "animation frame" property (ANIM_RUN_1, ANIM_RUN_2) */
|
/** an "animation frame" property (ANIM_RUN_1, ANIM_RUN_2) */
|
||||||
internal lateinit var transforms: HashMap<String, List<Transform>>; private set
|
internal lateinit var transforms: HashMap<String, List<Transform>>; private set
|
||||||
|
|
||||||
private val reservedProps = listOf("SPRITESHEET", "EXTENSION", "CONFIG", "BODYPARTS")
|
@Transient private val reservedProps = listOf("SPRITESHEET", "EXTENSION", "CONFIG", "BODYPARTS")
|
||||||
private val animMustContain = listOf("DELAY", "ROW", "SKELETON")
|
@Transient private val animMustContain = listOf("DELAY", "ROW", "SKELETON")
|
||||||
|
|
||||||
lateinit var baseFilename: String; private set
|
lateinit var baseFilename: String; private set
|
||||||
lateinit var extension: String; private set
|
lateinit var extension: String; private set
|
||||||
@@ -63,9 +63,9 @@ class ADProperties {
|
|||||||
internal val origin: ADPropertyObject.Vector2i
|
internal val origin: ADPropertyObject.Vector2i
|
||||||
get() = ADPropertyObject.Vector2i(originX, 0)
|
get() = ADPropertyObject.Vector2i(originX, 0)
|
||||||
|
|
||||||
private val animFrameSuffixRegex = Regex("""_[0-9]+""")
|
@Transient private val animFrameSuffixRegex = Regex("""_[0-9]+""")
|
||||||
|
|
||||||
private val ALL_JOINT = Joint(ALL_JOINT_SELECT_KEY, ADPropertyObject.Vector2i(0, 0))
|
@Transient private val ALL_JOINT = Joint(ALL_JOINT_SELECT_KEY, ADPropertyObject.Vector2i(0, 0))
|
||||||
|
|
||||||
var rows = -1; private set
|
var rows = -1; private set
|
||||||
var cols = -1; private set
|
var cols = -1; private set
|
||||||
|
|||||||
@@ -979,7 +979,7 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void createDirs() {
|
private static void createDirs() {
|
||||||
File[] dirs = {new File(saveDir)};
|
File[] dirs = {new File(saveDir), new File(saveSharedDir), new File(playersDir), new File(worldsDir)};
|
||||||
|
|
||||||
for (File it : dirs) {
|
for (File it : dirs) {
|
||||||
if (!it.exists())
|
if (!it.exists())
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import net.torvald.terrarum.gameitem.ItemID
|
|||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
import net.torvald.terrarum.modulebasegame.ui.Notification
|
import net.torvald.terrarum.modulebasegame.ui.Notification
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UITooltip
|
import net.torvald.terrarum.modulebasegame.ui.UITooltip
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
@@ -48,8 +49,8 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var savegameArchive: VirtualDisk
|
lateinit var worldDisk: VirtualDisk; internal set
|
||||||
internal set
|
lateinit var playerDisk: VirtualDisk; internal set
|
||||||
var savegameNickname: String = "SplinesReticulated"
|
var savegameNickname: String = "SplinesReticulated"
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
@@ -106,8 +107,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
/**
|
/**
|
||||||
* The actual gamer
|
* The actual gamer
|
||||||
*/
|
*/
|
||||||
val actorGamer: ActorHumanoid
|
open lateinit var actorGamer: IngamePlayer
|
||||||
get() = getActorByID(Terrarum.PLAYER_REF_ID) as ActorHumanoid
|
|
||||||
|
|
||||||
open var gameInitialised = false
|
open var gameInitialised = false
|
||||||
internal set
|
internal set
|
||||||
@@ -362,29 +362,34 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun makeSavegameBackupCopy() {
|
||||||
|
System.err.println("This function is deleteh")
|
||||||
|
printStackTrace(this)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies most recent `save` to `save.1`, leaving `save` for overwriting, previous `save.1` will be copied to `save.2`
|
* Copies most recent `save` to `save.1`, leaving `save` for overwriting, previous `save.1` will be copied to `save.2`
|
||||||
*/
|
*/
|
||||||
fun makeSavegameBackupCopy() {
|
fun makeSavegameBackupCopy(file: File) {
|
||||||
try {
|
try {
|
||||||
// do not overwrite clean .2 with dirty .1
|
// do not overwrite clean .2 with dirty .1
|
||||||
val file2 = File(App.saveDir, INGAME.savegameNickname + ".3")
|
val file2 = File("${file.absolutePath}.3")
|
||||||
val file1 = File(App.saveDir, INGAME.savegameNickname + ".2")
|
val file1 = File("${file.absolutePath}.2")
|
||||||
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
val flags1 = FileInputStream(file1).let { it.skip(49L); val r = it.read(); it.close(); r }
|
val flags1 = FileInputStream(file1).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) file1.copyTo(file2, true)
|
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) file1.copyTo(file2, true)
|
||||||
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
||||||
try {
|
try {
|
||||||
// do not overwrite clean .2 with dirty .1
|
// do not overwrite clean .2 with dirty .1
|
||||||
val file2 = File(App.saveDir, INGAME.savegameNickname + ".2")
|
val file2 = File("${file.absolutePath}.2")
|
||||||
val file1 = File(App.saveDir, INGAME.savegameNickname + ".1")
|
val file1 = File("${file.absolutePath}.1")
|
||||||
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
val flags1 = FileInputStream(file1).let { it.skip(49L); val r = it.read(); it.close(); r }
|
val flags1 = FileInputStream(file1).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) file1.copyTo(file2, true)
|
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) file1.copyTo(file2, true)
|
||||||
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
||||||
try {
|
try {
|
||||||
File(App.saveDir, INGAME.savegameNickname).copyTo(
|
file.copyTo(
|
||||||
File(App.saveDir, INGAME.savegameNickname + ".1"), // don't use .bak as it's used by the savecracker
|
File("${file.absolutePath}.1"), // don't use .bak as it's used by the savecracker
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
} catch (e: NoSuchFileException) {}
|
} catch (e: NoSuchFileException) {}
|
||||||
@@ -392,8 +397,10 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun getSaveFileMain() = File(App.saveDir, savegameNickname)
|
// fun getSaveFileMain() = File(App.saveDir, savegameNickname)
|
||||||
|
fun getWorldSaveFiledesc(filename: String) = File(App.worldsDir, filename)
|
||||||
|
fun getPlayerSaveFiledesc(filename: String) = File(App.playersDir, filename)
|
||||||
|
fun getSharedSaveFiledesc(filename: String) = File(App.saveSharedDir, filename)
|
||||||
|
|
||||||
|
|
||||||
// simple euclidean norm, squared
|
// simple euclidean norm, squared
|
||||||
|
|||||||
@@ -88,12 +88,14 @@ object AVKey {
|
|||||||
/** (unit TBA)
|
/** (unit TBA)
|
||||||
* base defence point of the species
|
* base defence point of the species
|
||||||
*/
|
*/
|
||||||
const val BASEDEFENCE = "basedefence"
|
const val DEFENCE = "defence"
|
||||||
|
const val DEFENCEBUFF = "$DEFENCE$BUFF"
|
||||||
|
|
||||||
/** Pixels
|
/** Pixels
|
||||||
* base hand reach of the species (only affects the gameplay as the player)
|
* base hand reach of the species (only affects the gameplay as the player)
|
||||||
*/
|
*/
|
||||||
const val BASEREACH = "basereach"
|
const val REACH = "reach"
|
||||||
|
const val REACHBUFF = "$REACH$BUFF"
|
||||||
|
|
||||||
/** (unit TBA)
|
/** (unit TBA)
|
||||||
* current defence point of worn armour(s)
|
* current defence point of worn armour(s)
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ fun inInteractableRange(actor: ActorWithBody, action: () -> Boolean): Boolean {
|
|||||||
val mousePos3 = Vector2(Terrarum.mouseX - INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
val mousePos3 = Vector2(Terrarum.mouseX - INGAME.world.width * TILE_SIZED, Terrarum.mouseY)
|
||||||
val actorPos = actor.centrePosVector
|
val actorPos = actor.centrePosVector
|
||||||
val dist = minOf(actorPos.distanceSquared(mousePos1), actorPos.distanceSquared(mousePos2), actorPos.distanceSquared(mousePos3))
|
val dist = minOf(actorPos.distanceSquared(mousePos1), actorPos.distanceSquared(mousePos2), actorPos.distanceSquared(mousePos3))
|
||||||
val distMax = actor.actorValue.getAsInt(AVKey.BASEREACH)!! * actor.scale // perform some error checking here
|
val distMax = actor.actorValue.getAsDouble(AVKey.REACH)!! * (actor.actorValue.getAsDouble(AVKey.REACHBUFF) ?: 1.0) * actor.scale // perform some error checking here
|
||||||
if (dist <= distMax.sqr()) return action() else return false
|
if (dist <= distMax.sqr()) return action() else return false
|
||||||
}
|
}
|
||||||
fun IntRange.pickRandom() = HQRNG().nextInt(this.endInclusive - this.start + 1) + this.start // count() on 200 million entries? Se on vitun hyvää idea
|
fun IntRange.pickRandom() = HQRNG().nextInt(this.endInclusive - this.start + 1) + this.start // count() on 200 million entries? Se on vitun hyvää idea
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import net.torvald.terrarum.blockproperties.Fluid
|
|||||||
import net.torvald.terrarum.gameactors.ActorID
|
import net.torvald.terrarum.gameactors.ActorID
|
||||||
import net.torvald.terrarum.gameactors.WireActor
|
import net.torvald.terrarum.gameactors.WireActor
|
||||||
import net.torvald.terrarum.gameitem.ItemID
|
import net.torvald.terrarum.gameitem.ItemID
|
||||||
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.utils.*
|
import net.torvald.terrarum.utils.*
|
||||||
import net.torvald.util.SortedArrayList
|
import net.torvald.util.SortedArrayList
|
||||||
@@ -22,6 +23,18 @@ import kotlin.math.absoluteValue
|
|||||||
|
|
||||||
typealias BlockAddress = Long
|
typealias BlockAddress = Long
|
||||||
|
|
||||||
|
class PhysicalStatus() {
|
||||||
|
// bottom-center point
|
||||||
|
var position = Point2d()
|
||||||
|
// some actorvalues
|
||||||
|
var scale = 1.0
|
||||||
|
|
||||||
|
constructor(player: IngamePlayer) : this() {
|
||||||
|
this.position = Point2d(player.hitbox.canonicalX, player.hitbox.canonicalY)
|
||||||
|
this.scale = player.avBaseScale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special version of GameWorld where layer data are not transient
|
* Special version of GameWorld where layer data are not transient
|
||||||
*/
|
*/
|
||||||
@@ -38,6 +51,8 @@ open class GameWorld() : Disposable {
|
|||||||
var width: Int = 999; private set
|
var width: Int = 999; private set
|
||||||
var height: Int = 999; private set
|
var height: Int = 999; private set
|
||||||
|
|
||||||
|
var playersLastStatus = PlayersLastPhysics() // only gets used when the game saves and loads
|
||||||
|
|
||||||
/** Creation time for this world, NOT the entire savegame */
|
/** Creation time for this world, NOT the entire savegame */
|
||||||
internal var creationTime: Long = App.getTIME_T()
|
internal var creationTime: Long = App.getTIME_T()
|
||||||
internal set
|
internal set
|
||||||
@@ -106,8 +121,8 @@ open class GameWorld() : Disposable {
|
|||||||
|
|
||||||
val extraFields = HashMap<String, Any?>()
|
val extraFields = HashMap<String, Any?>()
|
||||||
|
|
||||||
internal var genver = -1
|
internal var genver = -1 // only gets used when the game saves and loads
|
||||||
internal var comp = -1
|
internal var comp = -1 // only gets used when the game saves and loads
|
||||||
|
|
||||||
@Deprecated("This value is only used for savegames; DO NOT USE THIS", ReplaceWith("INGAME.actorContainerActive", "net.torvald.terrarum.INGAME"))
|
@Deprecated("This value is only used for savegames; DO NOT USE THIS", ReplaceWith("INGAME.actorContainerActive", "net.torvald.terrarum.INGAME"))
|
||||||
internal val actors = ArrayList<ActorID>() // only filled up on save and load; DO NOT USE THIS
|
internal val actors = ArrayList<ActorID>() // only filled up on save and load; DO NOT USE THIS
|
||||||
|
|||||||
@@ -46,7 +46,11 @@ import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
|||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
import net.torvald.util.CircularArray
|
import net.torvald.util.CircularArray
|
||||||
import org.khelekore.prtree.PRTree
|
import org.khelekore.prtree.PRTree
|
||||||
|
import java.util.*
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.collections.HashSet
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,7 +222,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
// gameLoadMode and gameLoadInfoPayload must be set beforehand!!
|
// gameLoadMode and gameLoadInfoPayload must be set beforehand!!
|
||||||
|
|
||||||
when (gameLoadMode) {
|
when (gameLoadMode) {
|
||||||
GameLoadMode.CREATE_NEW -> enterCreateNewWorld(gameLoadInfoPayload as NewWorldParameters)
|
GameLoadMode.CREATE_NEW -> enterCreateNewWorld(gameLoadInfoPayload as NewGameParams)
|
||||||
GameLoadMode.LOAD_FROM -> enterLoadFromSave(gameLoadInfoPayload as Codices)
|
GameLoadMode.LOAD_FROM -> enterLoadFromSave(gameLoadInfoPayload as Codices)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +232,11 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
super.show() // this function sets gameInitialised = true
|
super.show() // this function sets gameInitialised = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class NewGameParams(
|
||||||
|
val player: IngamePlayer,
|
||||||
|
val newWorldParams: NewWorldParameters
|
||||||
|
)
|
||||||
|
|
||||||
data class NewWorldParameters(
|
data class NewWorldParameters(
|
||||||
val width: Int,
|
val width: Int,
|
||||||
val height: Int,
|
val height: Int,
|
||||||
@@ -254,14 +263,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
val actors: List<ActorID>
|
val actors: List<ActorID>
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun setTheRealGamerFirstTime(actor: IngamePlayer) {
|
|
||||||
if (actor.referenceID != Terrarum.PLAYER_REF_ID) {
|
|
||||||
throw Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
actorNowPlaying = actor
|
|
||||||
addNewActor(actorNowPlaying)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init instance by loading saved world
|
* Init instance by loading saved world
|
||||||
@@ -308,33 +310,49 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
// go to spawn position
|
// go to spawn position
|
||||||
printdbg(this, "World Spawn position: (${world.spawnX}, ${world.spawnY})")
|
printdbg(this, "World Spawn position: (${world.spawnX}, ${world.spawnY})")
|
||||||
|
|
||||||
// setTheRealGamerFirstTime(PlayerBuilderSigrid())
|
val worldSavefileName = savegameNickname
|
||||||
setTheRealGamerFirstTime(PlayerBuilderTestSubject1())
|
val playerSavefileName = actorGamer.actorValue.getAsString(AVKey.NAME) ?: "Player-${actorGamer.uuid}"
|
||||||
// setTheRealGamerFirstTime(PlayerBuilderWerebeastTest())
|
|
||||||
|
|
||||||
savegameArchive = VDUtil.createNewDisk(
|
worldDisk = VDUtil.createNewDisk(
|
||||||
1L shl 60,
|
1L shl 60,
|
||||||
savegameNickname,
|
worldSavefileName,
|
||||||
Common.CHARSET
|
Common.CHARSET
|
||||||
)
|
)
|
||||||
|
|
||||||
actorNowPlaying!!.setPosition(
|
playerDisk = VDUtil.createNewDisk(
|
||||||
|
1L shl 60,
|
||||||
|
playerSavefileName,
|
||||||
|
Common.CHARSET
|
||||||
|
)
|
||||||
|
|
||||||
|
actorGamer.setPosition(
|
||||||
world.spawnX * TILE_SIZED,
|
world.spawnX * TILE_SIZED,
|
||||||
world.spawnY * TILE_SIZED
|
world.spawnY * TILE_SIZED
|
||||||
)
|
)
|
||||||
|
|
||||||
// make initial savefile
|
// make initial savefile
|
||||||
|
// we're not writing multiple files at one go because:
|
||||||
|
// 1. lighten the IO burden
|
||||||
|
// 2. cannot sync up the "counter" to determine whether both are finished
|
||||||
uiAutosaveNotifier.setAsOpen()
|
uiAutosaveNotifier.setAsOpen()
|
||||||
WriteSavegame.immediate(savegameArchive, getSaveFileMain(), this, true) {
|
WriteSavegame.immediate(WriteSavegame.SaveMode.PLAYER, playerDisk, getPlayerSaveFiledesc(playerSavefileName), this, false, true) {
|
||||||
makeSavegameBackupCopy() // don't put it on the postInit() or render(); must be called using callback
|
makeSavegameBackupCopy(getPlayerSaveFiledesc(playerSavefileName))
|
||||||
uiAutosaveNotifier.setAsClose()
|
|
||||||
|
WriteSavegame.immediate(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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init instance by creating new world
|
* Init instance by creating new world
|
||||||
*/
|
*/
|
||||||
private fun enterCreateNewWorld(worldParams: NewWorldParameters) {
|
private fun enterCreateNewWorld(newGameParams: NewGameParams) {
|
||||||
|
|
||||||
|
val player = newGameParams.player
|
||||||
|
val worldParams = newGameParams.newWorldParams
|
||||||
|
|
||||||
printdbg(this, "Ingame called")
|
printdbg(this, "Ingame called")
|
||||||
printStackTrace(this)
|
printStackTrace(this)
|
||||||
|
|
||||||
@@ -343,6 +361,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
App.getLoadScreen().addMessage("${App.GAME_NAME} version ${App.getVERSION_STRING()}")
|
App.getLoadScreen().addMessage("${App.GAME_NAME} version ${App.getVERSION_STRING()}")
|
||||||
|
|
||||||
App.getLoadScreen().addMessage("Creating new world")
|
App.getLoadScreen().addMessage("Creating new world")
|
||||||
|
|
||||||
|
|
||||||
@@ -364,6 +383,19 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
historicalFigureIDBucket = ArrayList<Int>()
|
historicalFigureIDBucket = ArrayList<Int>()
|
||||||
|
|
||||||
savegameNickname = worldParams.savegameName
|
savegameNickname = worldParams.savegameName
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
player.worldCurrentlyPlaying = UUID.fromString(world.worldIndex.toString())
|
||||||
|
world.worldCreator = UUID.fromString(player.uuid.toString())
|
||||||
|
|
||||||
|
printdbg(this, "new woridIndex: ${world.worldIndex}")
|
||||||
|
printdbg(this, "worldCurrentlyPlaying: ${player.worldCurrentlyPlaying}")
|
||||||
|
|
||||||
|
actorNowPlaying = player
|
||||||
|
actorGamer = player
|
||||||
|
addNewActor(player)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyToggler.forceSet(Input.Keys.Q, false)
|
KeyToggler.forceSet(Input.Keys.Q, false)
|
||||||
@@ -978,13 +1010,13 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
fun queueAutosave() {
|
fun queueAutosave() {
|
||||||
val start = System.nanoTime()
|
val start = System.nanoTime()
|
||||||
|
|
||||||
uiAutosaveNotifier.setAsOpen()
|
/*uiAutosaveNotifier.setAsOpen()
|
||||||
makeSavegameBackupCopy()
|
makeSavegameBackupCopy()
|
||||||
WriteSavegame.quick(savegameArchive, getSaveFileMain(), this, true) {
|
WriteSavegame.quick(savegameArchive, getSaveFileMain(), this, true) {
|
||||||
uiAutosaveNotifier.setAsClose()
|
uiAutosaveNotifier.setAsClose()
|
||||||
|
|
||||||
debugTimers.put("Last Autosave Duration", System.nanoTime() - start)
|
debugTimers.put("Last Autosave Duration", System.nanoTime() - start)
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1022,8 +1054,8 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
override fun removeActor(actor: Actor?) {
|
override fun removeActor(actor: Actor?) {
|
||||||
if (actor == null) return
|
if (actor == null) return
|
||||||
|
|
||||||
if (actor.referenceID == actorGamer.referenceID || actor.referenceID == 0x51621D) // do not delete this magic
|
// if (actor.referenceID == actorGamer.referenceID || actor.referenceID == 0x51621D) // do not delete this magic
|
||||||
throw ProtectedActorRemovalException("Player")
|
// throw ProtectedActorRemovalException("Player")
|
||||||
|
|
||||||
forceRemoveActor(actor)
|
forceRemoveActor(actor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ object Save : ConsoleCommand {
|
|||||||
val disk = VDUtil.createNewDisk(1L shl 60, savename, Common.CHARSET)
|
val disk = VDUtil.createNewDisk(1L shl 60, savename, Common.CHARSET)
|
||||||
val file = File(App.saveDir + "/${args[1]}")
|
val file = File(App.saveDir + "/${args[1]}")
|
||||||
|
|
||||||
WriteSavegame(disk, file, ingame, false)
|
// WriteSavegame(disk, file, ingame, false)
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
@@ -47,9 +47,7 @@ object Quicksave : ConsoleCommand {
|
|||||||
override fun execute(args: Array<String>) {
|
override fun execute(args: Array<String>) {
|
||||||
val ingame = Terrarum.ingame!! as TerrarumIngame
|
val ingame = Terrarum.ingame!! as TerrarumIngame
|
||||||
|
|
||||||
WriteSavegame.quick(ingame.savegameArchive, ingame.getSaveFileMain(), ingame, false) {
|
// WriteSavegame.quick(ingame.savegameArchive, ingame.getSaveFileMain(), ingame, false) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun printUsage() {
|
override fun printUsage() {
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.gameactors
|
package net.torvald.terrarum.modulebasegame.gameactors
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import net.torvald.spriteanimation.HasAssembledSprite
|
import net.torvald.spriteanimation.HasAssembledSprite
|
||||||
|
import net.torvald.spriteanimation.SpriteAnimation
|
||||||
import net.torvald.spriteassembler.ADProperties
|
import net.torvald.spriteassembler.ADProperties
|
||||||
|
import net.torvald.spriteassembler.AssembleSheetPixmap
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
|
import net.torvald.terrarum.tvda.SimpleFileSystem
|
||||||
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@@ -14,12 +19,16 @@ import java.util.*
|
|||||||
* Created by minjaesong on 2015-12-31.
|
* Created by minjaesong on 2015-12-31.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class IngamePlayer : ActorHumanoid, HasAssembledSprite {
|
class IngamePlayer : ActorHumanoid {
|
||||||
|
|
||||||
|
var uuid = UUID.randomUUID(); private set
|
||||||
|
var worldCurrentlyPlaying: UUID = UUID(0L,0L) // only filled up on save and load; DO NOT USE THIS
|
||||||
|
|
||||||
|
/** ADL for main sprite. Necessary. */
|
||||||
|
@Transient var animDesc: ADProperties? = null
|
||||||
|
/** ADL for glow sprite. Optional. */
|
||||||
|
@Transient var animDescGlow: ADProperties? = null
|
||||||
|
|
||||||
var UUID = UUID(0L,0L); private set
|
|
||||||
internal var worldCurrentlyPlaying: UUID = UUID(0L,0L) // only filled up on save and load; DO NOT USE THIS
|
|
||||||
override var animDesc: ADProperties? = null
|
|
||||||
override var animDescGlow: ADProperties? = null
|
|
||||||
|
|
||||||
private constructor()
|
private constructor()
|
||||||
|
|
||||||
@@ -38,7 +47,82 @@ class IngamePlayer : ActorHumanoid, HasAssembledSprite {
|
|||||||
referenceID = Terrarum.PLAYER_REF_ID // TODO assign random ID
|
referenceID = Terrarum.PLAYER_REF_ID // TODO assign random ID
|
||||||
density = BASE_DENSITY
|
density = BASE_DENSITY
|
||||||
collisionType = COLLISION_KINEMATIC
|
collisionType = COLLISION_KINEMATIC
|
||||||
worldCurrentlyPlaying = Terrarum.ingame?.world?.worldIndex ?: UUID(0L,0L)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example usage:
|
||||||
|
* ```
|
||||||
|
* this.animDescPath = "..."
|
||||||
|
* this.animDescPathGlow = "..."
|
||||||
|
* this.sprite = SpriteAnimation(actor)
|
||||||
|
* this.spriteGlow = SpriteAnimation(actor)
|
||||||
|
* reassembleSprite(this.sprite, this.spriteGlow)
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
fun reassembleSprite(sprite: SpriteAnimation?, anim: ADProperties?, spriteGlow: SpriteAnimation? = null, animGlow: ADProperties? = null) {
|
||||||
|
if (anim != null && sprite != null)
|
||||||
|
_rebuild(anim, sprite)
|
||||||
|
if (animGlow != null && spriteGlow != null)
|
||||||
|
_rebuild(animGlow, spriteGlow)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reassembleSprite(disk: SimpleFileSystem, sprite: SpriteAnimation?, anim: ADProperties?, spriteGlow: SpriteAnimation? = null, animGlow: ADProperties? = null) {
|
||||||
|
if (anim != null && sprite != null)
|
||||||
|
_rebuild(disk, anim, sprite)
|
||||||
|
if (animGlow != null && spriteGlow != null)
|
||||||
|
_rebuild(disk, animGlow, spriteGlow)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun _rebuild(ad: ADProperties, sprite: SpriteAnimation) {
|
||||||
|
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
|
||||||
|
|
||||||
|
val pixmap = AssembleSheetPixmap.fromAssetsDir(ad)
|
||||||
|
val texture = Texture(pixmap)
|
||||||
|
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
|
||||||
|
pixmap.dispose()
|
||||||
|
val regionPack = TextureRegionPack(texture, ad.frameWidth, ad.frameHeight)
|
||||||
|
|
||||||
|
val newAnimDelays = FloatArray(ad.animations.size)
|
||||||
|
val newAnimFrames = IntArray(ad.animations.size)
|
||||||
|
|
||||||
|
ad.animations.forEach { t, u ->
|
||||||
|
val index = u.row - 1
|
||||||
|
newAnimDelays[index] = u.delay
|
||||||
|
newAnimFrames[index] = u.frames
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite.setSpriteImage(regionPack)
|
||||||
|
sprite.delays = newAnimDelays
|
||||||
|
sprite.nFrames = newAnimFrames
|
||||||
|
sprite.nRows = newAnimDelays.size
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) {
|
||||||
|
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
|
||||||
|
|
||||||
|
val pixmap = AssembleSheetPixmap.fromVirtualDisk(disk, ad)
|
||||||
|
val texture = Texture(pixmap)
|
||||||
|
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
|
||||||
|
pixmap.dispose()
|
||||||
|
val regionPack = TextureRegionPack(texture, ad.frameWidth, ad.frameHeight)
|
||||||
|
|
||||||
|
val newAnimDelays = FloatArray(ad.animations.size)
|
||||||
|
val newAnimFrames = IntArray(ad.animations.size)
|
||||||
|
|
||||||
|
ad.animations.forEach { t, u ->
|
||||||
|
val index = u.row - 1
|
||||||
|
newAnimDelays[index] = u.delay
|
||||||
|
newAnimFrames[index] = u.frames
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite.setSpriteImage(regionPack)
|
||||||
|
sprite.delays = newAnimDelays
|
||||||
|
sprite.nFrames = newAnimFrames
|
||||||
|
sprite.nRows = newAnimDelays.size
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -90,13 +90,13 @@ class UIInventoryEscMenu(val full: UIInventoryFull) : UICanvas() {
|
|||||||
INGAME.makeSavegameBackupCopy()
|
INGAME.makeSavegameBackupCopy()
|
||||||
|
|
||||||
// save the game
|
// save the game
|
||||||
WriteSavegame(INGAME.savegameArchive, File(App.saveDir, INGAME.savegameNickname), Terrarum.ingame!! as TerrarumIngame, false) {
|
/*WriteSavegame(INGAME.savegameArchive, File(App.saveDir, INGAME.savegameNickname), Terrarum.ingame!! as TerrarumIngame, false) {
|
||||||
// callback:
|
// callback:
|
||||||
System.gc()
|
System.gc()
|
||||||
screen = 0
|
screen = 0
|
||||||
full.handler.unlockToggle()
|
full.handler.unlockToggle()
|
||||||
full.unlockTransition()
|
full.unlockTransition()
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
2 -> {
|
2 -> {
|
||||||
screen = 4; gameMenuButtons.deselect()
|
screen = 4; gameMenuButtons.deselect()
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.torvald.terrarum.Second
|
|||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.WorldgenLoadScreen
|
import net.torvald.terrarum.modulebasegame.WorldgenLoadScreen
|
||||||
|
import net.torvald.terrarum.modulebasegame.gameactors.PlayerBuilderTestSubject1
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import net.torvald.terrarum.utils.RandomWordsName
|
import net.torvald.terrarum.utils.RandomWordsName
|
||||||
|
|
||||||
@@ -36,9 +37,11 @@ class UIProxyNewRandomGame : UICanvas() {
|
|||||||
override fun endOpening(delta: Float) {
|
override fun endOpening(delta: Float) {
|
||||||
printdbg(this, "endOpening")
|
printdbg(this, "endOpening")
|
||||||
|
|
||||||
|
|
||||||
val ingame = TerrarumIngame(App.batch)
|
val ingame = TerrarumIngame(App.batch)
|
||||||
val worldParam = TerrarumIngame.NewWorldParameters(2880, 1350, HQRNG().nextLong(), RandomWordsName(4))
|
val worldParam = TerrarumIngame.NewGameParams(
|
||||||
|
PlayerBuilderTestSubject1(),
|
||||||
|
TerrarumIngame.NewWorldParameters(2880, 1350, HQRNG().nextLong(), RandomWordsName(4))
|
||||||
|
)
|
||||||
// val worldParam = TerrarumIngame.NewWorldParameters(2880, 1350, 0x51621D)
|
// val worldParam = TerrarumIngame.NewWorldParameters(2880, 1350, 0x51621D)
|
||||||
|
|
||||||
// val worldParam = TerrarumIngame.NewWorldParameters(6030, 1800, HQRNG().nextLong()) // small
|
// val worldParam = TerrarumIngame.NewWorldParameters(6030, 1800, HQRNG().nextLong()) // small
|
||||||
@@ -51,7 +54,7 @@ class UIProxyNewRandomGame : UICanvas() {
|
|||||||
Terrarum.setCurrentIngameInstance(ingame)
|
Terrarum.setCurrentIngameInstance(ingame)
|
||||||
//LoadScreen.screenToLoad = ingame
|
//LoadScreen.screenToLoad = ingame
|
||||||
//AppLoader.setScreen(LoadScreen)
|
//AppLoader.setScreen(LoadScreen)
|
||||||
val loadScreen = WorldgenLoadScreen(ingame, worldParam.width, worldParam.height)
|
val loadScreen = WorldgenLoadScreen(ingame, worldParam.newWorldParams.width, worldParam.newWorldParams.height)
|
||||||
App.setLoadScreen(loadScreen)
|
App.setLoadScreen(loadScreen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ object Common {
|
|||||||
|
|
||||||
// install custom (de)serialiser
|
// install custom (de)serialiser
|
||||||
init {
|
init {
|
||||||
|
jsoner.ignoreUnknownFields = true
|
||||||
|
|
||||||
|
|
||||||
// BigInteger
|
// BigInteger
|
||||||
jsoner.setSerializer(BigInteger::class.java, object : Json.Serializer<BigInteger> {
|
jsoner.setSerializer(BigInteger::class.java, object : Json.Serializer<BigInteger> {
|
||||||
override fun write(json: Json, obj: BigInteger?, knownType: Class<*>?) {
|
override fun write(json: Json, obj: BigInteger?, knownType: Class<*>?) {
|
||||||
|
|||||||
@@ -3,36 +3,31 @@ package net.torvald.terrarum.serialise
|
|||||||
import net.torvald.gdx.graphics.PixmapIO2
|
import net.torvald.gdx.graphics.PixmapIO2
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.console.Echo
|
import net.torvald.terrarum.console.Echo
|
||||||
|
import net.torvald.terrarum.gameworld.PhysicalStatus
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.tvda.*
|
import net.torvald.terrarum.tvda.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.zip.GZIPOutputStream
|
import java.util.zip.GZIPOutputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will happily overwrite existing entry
|
||||||
|
*/
|
||||||
|
private fun addFile(disk: VirtualDisk, file: DiskEntry) {
|
||||||
|
disk.entries[file.entryID] = file
|
||||||
|
file.parentEntryID = 0
|
||||||
|
val dir = VDUtil.getAsDirectory(disk, 0)
|
||||||
|
if (!dir.contains(file.entryID)) dir.add(file.entryID)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2021-09-14.
|
* Created by minjaesong on 2021-09-14.
|
||||||
*/
|
*/
|
||||||
class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: TerrarumIngame, val hasThumbnail: Boolean, val isAuto: Boolean, val callback: () -> Unit) : Runnable {
|
class WorldSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: TerrarumIngame, val hasThumbnail: Boolean, val isAuto: Boolean, val callback: () -> Unit) : Runnable {
|
||||||
|
|
||||||
/**
|
|
||||||
* Will happily overwrite existing entry
|
|
||||||
*/
|
|
||||||
private fun addFile(disk: VirtualDisk, file: DiskEntry) {
|
|
||||||
disk.entries[file.entryID] = file
|
|
||||||
file.parentEntryID = 0
|
|
||||||
val dir = VDUtil.getAsDirectory(disk, 0)
|
|
||||||
if (!dir.contains(file.entryID)) dir.add(file.entryID)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val chunkProgressMultiplier = 1f
|
|
||||||
private val actorProgressMultiplier = 1f
|
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
callback()
|
|
||||||
return
|
|
||||||
|
|
||||||
// TODO //
|
|
||||||
|
|
||||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||||
|
|
||||||
@@ -42,15 +37,14 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val playersList: List<IngamePlayer> = listOf(ingame.actorContainerActive, ingame.actorContainerInactive).flatMap{ it.filter { it is IngamePlayer } } as List<IngamePlayer>
|
||||||
val actorsList = listOf(ingame.actorContainerActive, ingame.actorContainerInactive).flatMap { it.filter { WriteWorld.actorAcceptable(it) } }
|
val actorsList = listOf(ingame.actorContainerActive, ingame.actorContainerInactive).flatMap { it.filter { WriteWorld.actorAcceptable(it) } }
|
||||||
val layers = intArrayOf(0,1).map { ingame.world.getLayer(it) }
|
val layers = intArrayOf(0,1).map { ingame.world.getLayer(it) }
|
||||||
val cw = ingame.world.width / LandUtil.CHUNK_W
|
val cw = ingame.world.width / LandUtil.CHUNK_W
|
||||||
val ch = ingame.world.height / LandUtil.CHUNK_H
|
val ch = ingame.world.height / LandUtil.CHUNK_H
|
||||||
|
|
||||||
WriteSavegame.saveProgress = 0f
|
WriteSavegame.saveProgress = 0f
|
||||||
WriteSavegame.saveProgressMax = 2f +
|
WriteSavegame.saveProgressMax = 2f + (cw * ch * layers.size) + actorsList.size
|
||||||
(cw * ch * layers.size) * chunkProgressMultiplier +
|
|
||||||
actorsList.size * actorProgressMultiplier
|
|
||||||
|
|
||||||
|
|
||||||
val tgaout = ByteArray64GrowableOutputStream()
|
val tgaout = ByteArray64GrowableOutputStream()
|
||||||
@@ -62,11 +56,6 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
|||||||
val time_t = App.getTIME_T()
|
val time_t = App.getTIME_T()
|
||||||
|
|
||||||
|
|
||||||
// Write Meta //
|
|
||||||
val metaContent = EntryFile(WriteMeta.encodeToByteArray64(ingame, time_t))
|
|
||||||
val meta = DiskEntry(-1, 0, creation_t, time_t, metaContent)
|
|
||||||
addFile(disk, meta)
|
|
||||||
|
|
||||||
if (hasThumbnail) {
|
if (hasThumbnail) {
|
||||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||||
IngameRenderer.fboRGBexport.dispose()
|
IngameRenderer.fboRGBexport.dispose()
|
||||||
@@ -114,10 +103,13 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
|||||||
// addFile(disk, apocryphas)
|
// addFile(disk, apocryphas)
|
||||||
|
|
||||||
// Write World //
|
// Write World //
|
||||||
// val worldNum = ingame.world.worldIndex
|
// record all player's last position
|
||||||
// val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t))
|
playersList.forEach {
|
||||||
// val world = DiskEntry(worldNum.toLong(), 0, creation_t, time_t, worldMeta)
|
ingame.world.playersLastStatus[it.uuid] = PhysicalStatus(it)
|
||||||
// addFile(disk, world)
|
}
|
||||||
|
val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t))
|
||||||
|
val world = DiskEntry(-1L, 0, creation_t, time_t, worldMeta)
|
||||||
|
addFile(disk, world)
|
||||||
|
|
||||||
WriteSavegame.saveProgress += 1f
|
WriteSavegame.saveProgress += 1f
|
||||||
|
|
||||||
@@ -137,7 +129,7 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
|||||||
// "W1L0-92,15"
|
// "W1L0-92,15"
|
||||||
addFile(disk, entry)
|
addFile(disk, entry)
|
||||||
|
|
||||||
WriteSavegame.saveProgress += chunkProgressMultiplier
|
WriteSavegame.saveProgress += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +143,7 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
|||||||
val actor = DiskEntry(it.referenceID.toLong(), 0, creation_t, time_t, actorContent)
|
val actor = DiskEntry(it.referenceID.toLong(), 0, creation_t, time_t, actorContent)
|
||||||
addFile(disk, actor)
|
addFile(disk, actor)
|
||||||
|
|
||||||
WriteSavegame.saveProgress += actorProgressMultiplier
|
WriteSavegame.saveProgress += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -174,4 +166,23 @@ class GameSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: Ter
|
|||||||
|
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function called means the "Avatar" was not externally created and thus has no sprite-bodypart-name-to-entry-number-map
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2021-10-08
|
||||||
|
*/
|
||||||
|
class PlayerSavingThread(val disk: VirtualDisk, val outFile: File, val ingame: TerrarumIngame, val hasThumbnail: Boolean, val isAuto: Boolean, val callback: () -> Unit) : Runnable {
|
||||||
|
|
||||||
|
override fun run() {
|
||||||
|
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||||
|
disk.capacity = 0L
|
||||||
|
|
||||||
|
Echo("Writing The Player...")
|
||||||
|
WritePlayer(ingame.actorGamer, disk)
|
||||||
|
VDUtil.dumpToRealMachine(disk, outFile)
|
||||||
|
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ object WriteActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Player-specific [WriteActor].
|
* Player-specific [WriteActor]. Will write JSON and Animation Description Languages
|
||||||
*
|
*
|
||||||
* Created by minjaesong on 2021-10-07.
|
* Created by minjaesong on 2021-10-07.
|
||||||
*/
|
*/
|
||||||
@@ -74,12 +74,12 @@ object WritePlayer {
|
|||||||
|
|
||||||
val adlContents = EntryFile(ByteArray64.fromByteArray(adl.toByteArray(Common.CHARSET)))
|
val adlContents = EntryFile(ByteArray64.fromByteArray(adl.toByteArray(Common.CHARSET)))
|
||||||
val adlCreationDate = playerDisk.getEntry(-2)?.creationDate ?: time_t
|
val adlCreationDate = playerDisk.getEntry(-2)?.creationDate ?: time_t
|
||||||
addFile(playerDisk, DiskEntry(-1L, 0L, adlCreationDate, time_t, adlContents))
|
addFile(playerDisk, DiskEntry(-2L, 0L, adlCreationDate, time_t, adlContents))
|
||||||
|
|
||||||
if (adlGlow != null) {
|
if (adlGlow != null) {
|
||||||
val adlGlowContents = EntryFile(ByteArray64.fromByteArray(adlGlow.toByteArray(Common.CHARSET)))
|
val adlGlowContents = EntryFile(ByteArray64.fromByteArray(adlGlow.toByteArray(Common.CHARSET)))
|
||||||
val adlGlowCreationDate = playerDisk.getEntry(-3)?.creationDate ?: time_t
|
val adlGlowCreationDate = playerDisk.getEntry(-3)?.creationDate ?: time_t
|
||||||
addFile(playerDisk, DiskEntry(-1L, 0L, adlGlowCreationDate, time_t, adlGlowContents))
|
addFile(playerDisk, DiskEntry(-3L, 0L, adlGlowCreationDate, time_t, adlGlowContents))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,11 +23,21 @@ import java.io.Reader
|
|||||||
*/
|
*/
|
||||||
object WriteSavegame {
|
object WriteSavegame {
|
||||||
|
|
||||||
|
enum class SaveMode {
|
||||||
|
META, PLAYER, WORLD, SHARED
|
||||||
|
}
|
||||||
|
|
||||||
@Volatile var savingStatus = -1 // -1: not started, 0: saving in progress, 255: saving finished
|
@Volatile var savingStatus = -1 // -1: not started, 0: saving in progress, 255: saving finished
|
||||||
@Volatile var saveProgress = 0f
|
@Volatile var saveProgress = 0f
|
||||||
@Volatile var saveProgressMax = 1f
|
@Volatile var saveProgressMax = 1f
|
||||||
|
|
||||||
operator fun invoke(disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, callback: () -> Unit = {}) {
|
private fun getSaveThread(mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, hasThumbnail: Boolean, isAuto: Boolean, callback: () -> Unit = {}) = when (mode) {
|
||||||
|
SaveMode.WORLD -> WorldSavingThread(disk, outFile, ingame, hasThumbnail, isAuto, callback)
|
||||||
|
SaveMode.PLAYER -> PlayerSavingThread(disk, outFile, ingame, hasThumbnail, isAuto, callback)
|
||||||
|
else -> throw IllegalArgumentException("$mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun invoke(mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, callback: () -> Unit = {}) {
|
||||||
savingStatus = 0
|
savingStatus = 0
|
||||||
|
|
||||||
Echo("Save queued")
|
Echo("Save queued")
|
||||||
@@ -47,7 +57,7 @@ object WriteSavegame {
|
|||||||
}
|
}
|
||||||
IngameRenderer.screencapRequested = true
|
IngameRenderer.screencapRequested = true
|
||||||
|
|
||||||
val savingThread = Thread(GameSavingThread(disk, outFile, ingame, true, isAuto, callback), "TerrarumBasegameGameSaveThread")
|
val savingThread = Thread(getSaveThread(mode, disk, outFile, ingame, true, isAuto, callback), "TerrarumBasegameGameSaveThread")
|
||||||
savingThread.start()
|
savingThread.start()
|
||||||
|
|
||||||
// it is caller's job to keep the game paused or keep a "save in progress" ui up
|
// it is caller's job to keep the game paused or keep a "save in progress" ui up
|
||||||
@@ -55,16 +65,13 @@ object WriteSavegame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun immediate(disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, callback: () -> Unit = {}) {
|
fun immediate(mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, hasThumbnail: Boolean, isAuto: Boolean, callback: () -> Unit = {}) {
|
||||||
return
|
|
||||||
|
|
||||||
// TODO //
|
|
||||||
|
|
||||||
savingStatus = 0
|
savingStatus = 0
|
||||||
|
|
||||||
Echo("Immediate save fired")
|
Echo("Immediate save fired")
|
||||||
|
|
||||||
val savingThread = Thread(GameSavingThread(disk, outFile, ingame, false, isAuto, callback), "TerrarumBasegameGameSaveThread")
|
val savingThread = Thread(getSaveThread(mode, disk, outFile, ingame, false, isAuto, callback), "TerrarumBasegameGameSaveThread")
|
||||||
savingThread.start()
|
savingThread.start()
|
||||||
|
|
||||||
// it is caller's job to keep the game paused or keep a "save in progress" ui up
|
// it is caller's job to keep the game paused or keep a "save in progress" ui up
|
||||||
@@ -134,7 +141,6 @@ object LoadSavegame {
|
|||||||
world.layerTerrain = BlockLayer(world.width, world.height)
|
world.layerTerrain = BlockLayer(world.width, world.height)
|
||||||
world.layerWall = BlockLayer(world.width, world.height)
|
world.layerWall = BlockLayer(world.width, world.height)
|
||||||
|
|
||||||
newIngame.savegameArchive = disk
|
|
||||||
newIngame.creationTime = meta.creation_t
|
newIngame.creationTime = meta.creation_t
|
||||||
newIngame.lastPlayTime = meta.lastplay_t
|
newIngame.lastPlayTime = meta.lastplay_t
|
||||||
newIngame.totalPlayTime = meta.playtime_t
|
newIngame.totalPlayTime = meta.playtime_t
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.torvald.terrarum.gameworld.BlockLayer
|
|||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.GameWorldTitleScreen
|
import net.torvald.terrarum.gameworld.GameWorldTitleScreen
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.tvda.ByteArray64
|
import net.torvald.terrarum.tvda.ByteArray64
|
||||||
import net.torvald.terrarum.tvda.ByteArray64Writer
|
import net.torvald.terrarum.tvda.ByteArray64Writer
|
||||||
@@ -22,7 +23,8 @@ object WriteWorld {
|
|||||||
fun actorAcceptable(actor: Actor): Boolean {
|
fun actorAcceptable(actor: Actor): Boolean {
|
||||||
return actor.referenceID !in ReferencingRanges.ACTORS_WIRES &&
|
return actor.referenceID !in ReferencingRanges.ACTORS_WIRES &&
|
||||||
actor.referenceID !in ReferencingRanges.ACTORS_WIRES_HELPER &&
|
actor.referenceID !in ReferencingRanges.ACTORS_WIRES_HELPER &&
|
||||||
actor != (CommonResourcePool.get("blockmarking_actor") as BlockMarkerActor)
|
actor != (CommonResourcePool.get("blockmarking_actor") as BlockMarkerActor) &&
|
||||||
|
actor !is IngamePlayer // IngamePlayers must not be saved with the world
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun preWrite(ingame: TerrarumIngame, time_t: Long): GameWorld {
|
private fun preWrite(ingame: TerrarumIngame, time_t: Long): GameWorld {
|
||||||
|
|||||||
@@ -7,9 +7,12 @@ import net.torvald.terrarum.gameitem.ItemID
|
|||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
import net.torvald.terrarum.gameworld.FluidType
|
import net.torvald.terrarum.gameworld.FluidType
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.PhysicalStatus
|
||||||
import net.torvald.terrarum.tvda.ByteArray64Reader
|
import net.torvald.terrarum.tvda.ByteArray64Reader
|
||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
import java.io.StringReader
|
import java.io.StringReader
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2021-08-26.
|
* Created by minjaesong on 2021-08-26.
|
||||||
@@ -22,7 +25,7 @@ class HashedFluidType: HashMap<BlockAddress, FluidType>()
|
|||||||
class HashedWirings: HashMap<BlockAddress, GameWorld.WiringNode>()
|
class HashedWirings: HashMap<BlockAddress, GameWorld.WiringNode>()
|
||||||
class HashedWiringGraph: HashMap<BlockAddress, WiringGraphMap>()
|
class HashedWiringGraph: HashMap<BlockAddress, WiringGraphMap>()
|
||||||
class MetaModuleCSVPair: HashMap<String, ZipCodedStr>()
|
class MetaModuleCSVPair: HashMap<String, ZipCodedStr>()
|
||||||
|
class PlayersLastPhysics: HashMap<UUID, PhysicalStatus>()
|
||||||
/**
|
/**
|
||||||
* @param doc plaintext
|
* @param doc plaintext
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user