new save format wip (no branching on this commit)

This commit is contained in:
minjaesong
2021-10-07 14:40:04 +09:00
parent d6a22f6567
commit 6d8a7520ac
15 changed files with 94 additions and 39 deletions

View File

@@ -4,6 +4,8 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.Texture
import net.torvald.spriteassembler.ADProperties import net.torvald.spriteassembler.ADProperties
import net.torvald.spriteassembler.AssembleSheetPixmap import net.torvald.spriteassembler.AssembleSheetPixmap
import net.torvald.terrarum.tvda.DiskSkimmer
import net.torvald.terrarum.tvda.SimpleFileSystem
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/** /**
@@ -12,9 +14,9 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
interface HasAssembledSprite { interface HasAssembledSprite {
/** ADL path for main sprite. Necessary. */ /** ADL path for main sprite. Necessary. */
var animDescPath: String var animDesc: ADProperties?
/** ADL path for glow sprite. Optional. */ /** ADL path for glow sprite. Optional. */
var animDescPathGlow: String? 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?)
@@ -28,10 +30,11 @@ interface HasAssembledSprite {
* reassembleSprite(this.sprite, this.spriteGlow) * reassembleSprite(this.sprite, this.spriteGlow)
* ``` * ```
*/ */
fun reassembleSprite(sprite: SpriteAnimation, spriteGlow: SpriteAnimation? = null) { fun reassembleSprite(sprite: SpriteAnimation?, anim: ADProperties?, spriteGlow: SpriteAnimation? = null, animGlow: ADProperties? = null) {
_rebuild(ADProperties(Gdx.files.internal(animDescPath)), sprite) if (anim != null && sprite != null)
if (animDescPathGlow != null && spriteGlow != null) _rebuild(anim, sprite)
_rebuild(ADProperties(Gdx.files.internal(animDescPathGlow)), spriteGlow) if (animGlow != null && spriteGlow != null)
_rebuild(animGlow, spriteGlow)
} }
/*fun rebuild(animDescPath: String, spriteAnimation: SpriteAnimation) { /*fun rebuild(animDescPath: String, spriteAnimation: SpriteAnimation) {
@@ -50,6 +53,8 @@ interface HasAssembledSprite {
private fun _rebuild(ad: ADProperties, sprite: SpriteAnimation) { private fun _rebuild(ad: ADProperties, sprite: SpriteAnimation) {
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job? // TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
// TODO resolve bodyparts (must read ID-to-bodypartmap.properties first)
val pixmap = AssembleSheetPixmap(ad) val pixmap = AssembleSheetPixmap(ad)
val texture = Texture(pixmap) val texture = Texture(pixmap)
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest) texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)

View File

@@ -2,6 +2,7 @@ package net.torvald.spriteassembler
import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.files.FileHandle
import net.torvald.terrarum.linearSearchBy import net.torvald.terrarum.linearSearchBy
import net.torvald.terrarum.serialise.Common
import java.io.InputStream import java.io.InputStream
import java.io.Reader import java.io.Reader
import java.util.* import java.util.*
@@ -33,6 +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 = ""
private val javaProp = Properties() private val javaProp = Properties()
/** Every key is CAPITALISED */ /** Every key is CAPITALISED */
@@ -68,30 +70,31 @@ class ADProperties {
var rows = -1; private set var rows = -1; private set
var cols = -1; private set var cols = -1; private set
fun getRawADL() = adlString
companion object { companion object {
const val ALL_JOINT_SELECT_KEY = "ALL" const val ALL_JOINT_SELECT_KEY = "ALL"
} }
constructor(gdxFile: FileHandle) { constructor(gdxFile: FileHandle) {
fileFrom = gdxFile.path() fileFrom = gdxFile.path()
adlString = gdxFile.readString(Common.CHARSET.name())
javaProp.load(gdxFile.read()) javaProp.load(gdxFile.read())
continueLoad() continueLoad()
} }
constructor(reader: Reader) { constructor(reader: Reader) {
adlString = reader.readText()
javaProp.load(reader) javaProp.load(reader)
continueLoad() continueLoad()
} }
constructor(inputStream: InputStream) { constructor(inputStream: InputStream) {
adlString = inputStream.readAllBytes().toString(Common.CHARSET)
javaProp.load(inputStream) javaProp.load(inputStream)
continueLoad() continueLoad()
} }
constructor(javaProp: Properties) {
this.javaProp.putAll(javaProp.toMap())
}
private fun continueLoad() { private fun continueLoad() {
// sanity check // sanity check
reservedProps.forEach { reservedProps.forEach {

View File

@@ -2,7 +2,9 @@ package net.torvald.spriteassembler
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.terrarum.linearSearch import net.torvald.terrarum.linearSearch
import java.io.InputStream
/** /**
* Assembles the single frame of the animation, outputs GDX Pixmap. * Assembles the single frame of the animation, outputs GDX Pixmap.
@@ -17,10 +19,13 @@ object AssembleSheetPixmap {
val canvas = Pixmap(properties.cols * properties.frameWidth, properties.rows * properties.frameHeight, Pixmap.Format.RGBA8888) val canvas = Pixmap(properties.cols * properties.frameWidth, properties.rows * properties.frameHeight, Pixmap.Format.RGBA8888)
canvas.blending = Pixmap.Blending.SourceOver canvas.blending = Pixmap.Blending.SourceOver
val fileGetter = { path: String ->
Gdx.files.internal(path).read()
}
// actually draw // actually draw
properties.transforms.forEach { t, _ -> properties.transforms.forEach { t, _ ->
drawThisFrame(t, canvas, properties) drawThisFrame(t, canvas, properties, fileGetter)
} }
return canvas return canvas
@@ -28,15 +33,21 @@ object AssembleSheetPixmap {
private fun drawThisFrame(frameName: String, private fun drawThisFrame(frameName: String,
canvas: Pixmap, canvas: Pixmap,
properties: ADProperties properties: ADProperties,
fileGetter: (String) -> InputStream
) { ) {
val theAnim = properties.getAnimByFrameName(frameName) val theAnim = properties.getAnimByFrameName(frameName)
val skeleton = theAnim.skeleton.joints.reversed() val skeleton = theAnim.skeleton.joints.reversed()
val transforms = properties.getTransform(frameName) val transforms = properties.getTransform(frameName)
val bodypartOrigins = properties.bodyparts val bodypartOrigins = properties.bodyparts
val bodypartImages = properties.bodyparts.keys.map { val bodypartImages = properties.bodyparts.keys.map {
val file = Gdx.files.internal("assets/${properties.toFilename(it)}") try {
it to (if (file.exists()) Pixmap(file) else null) val bytes = fileGetter("assets/${properties.toFilename(it)}").readAllBytes()
it to Pixmap(bytes, 0, bytes.size)
}
catch (e: GdxRuntimeException) {
it to null
}
}.toMap() }.toMap()
val transformList = AssembleFrameBase.makeTransformList(skeleton, transforms) val transformList = AssembleFrameBase.makeTransformList(skeleton, transforms)

View File

@@ -287,7 +287,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
private fun postInitForLoadFromSave(codices: Codices) { private fun postInitForLoadFromSave(codices: Codices) {
codices.actors.forEach { codices.actors.forEach {
try { try {
val actor = ReadActor(LoadSavegame.getFileReader(codices.disk, it.toLong())) val actor = ReadActor(codices.disk, LoadSavegame.getFileReader(codices.disk, it.toLong()))
addNewActor(actor) addNewActor(actor)
} }
catch (e: NullPointerException) { catch (e: NullPointerException) {

View File

@@ -34,7 +34,7 @@ object ImportWorld : ConsoleCommand {
Echo("Usage: Importworld filename-without-extension") Echo("Usage: Importworld filename-without-extension")
} }
} }
/*
object ImportActor : ConsoleCommand { object ImportActor : ConsoleCommand {
override fun execute(args: Array<String>) { override fun execute(args: Array<String>) {
if (args.size == 2) { if (args.size == 2) {
@@ -56,4 +56,4 @@ object ImportActor : ConsoleCommand {
override fun printUsage() { override fun printUsage() {
Echo("Usage: Importactor filename-without-extension") Echo("Usage: Importactor filename-without-extension")
} }
} }*/

View File

@@ -1,6 +1,8 @@
package net.torvald.terrarum.modulebasegame.gameactors package net.torvald.terrarum.modulebasegame.gameactors
import com.badlogic.gdx.Gdx
import net.torvald.spriteanimation.HasAssembledSprite import net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.spriteassembler.ADProperties
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
@@ -13,15 +15,15 @@ import net.torvald.terrarum.gameactors.AVKey
class IngamePlayer : ActorHumanoid, HasAssembledSprite { class IngamePlayer : ActorHumanoid, HasAssembledSprite {
override var animDescPath = "invalid" override var animDesc: ADProperties? = null
override var animDescPathGlow: String? = null override var animDescGlow: ADProperties? = null
internal var worldCurrentlyPlaying = 0 // only filled up on save and load; DO NOT USE THIS internal var worldCurrentlyPlaying = 0 // only filled up on save and load; DO NOT USE THIS
private constructor() private constructor()
constructor(animDescPath: String, animDescPathGlow: String?, born: Long) : super(born) { constructor(animDescPath: String, animDescPathGlow: String?, born: Long) : super(born) {
this.animDescPath = animDescPath animDesc = ADProperties(Gdx.files.internal(animDescPath))
this.animDescPathGlow = animDescPathGlow if (animDescPathGlow != null) animDescGlow = ADProperties(Gdx.files.internal(animDescPathGlow))
actorValue[AVKey.__HISTORICAL_BORNTIME] = born actorValue[AVKey.__HISTORICAL_BORNTIME] = born
} }

View File

@@ -31,7 +31,7 @@ object PlayerBuilderTestSubject1 {
p.sprite = SpriteAnimation(p) p.sprite = SpriteAnimation(p)
p.spriteGlow = SpriteAnimation(p) p.spriteGlow = SpriteAnimation(p)
p.reassembleSprite(p.sprite!!, p.spriteGlow) p.reassembleSprite(p.sprite, p.animDesc, p.spriteGlow, p.animDescGlow)
p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT) ?: ActorHumanoid.BASE_HEIGHT, 21, 0) p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT) ?: ActorHumanoid.BASE_HEIGHT, 21, 0)
// ingame must teleport the player to the spawn point // ingame must teleport the player to the spawn point

View File

@@ -31,7 +31,7 @@ object PlayerBuilderWerebeastTest {
p.sprite = SpriteAnimation(p) p.sprite = SpriteAnimation(p)
p.spriteGlow = SpriteAnimation(p) p.spriteGlow = SpriteAnimation(p)
p.reassembleSprite(p.sprite!!, p.spriteGlow) p.reassembleSprite(p.sprite, p.animDesc, p.spriteGlow, p.animDescGlow)
p.setHitboxDimension(22, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 30, 0) p.setHitboxDimension(22, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 30, 0)
p.setPosition(3.0 * TILE_SIZE, 3.0 * TILE_SIZE) p.setPosition(3.0 * TILE_SIZE, 3.0 * TILE_SIZE)

View File

@@ -28,7 +28,6 @@ class UIProxyNewBuildingMaker : UICanvas() {
} }
override fun doClosing(delta: Float) { override fun doClosing(delta: Float) {
TODO("not implemented")
} }
override fun endOpening(delta: Float) { override fun endOpening(delta: Float) {
@@ -40,10 +39,8 @@ class UIProxyNewBuildingMaker : UICanvas() {
} }
override fun endClosing(delta: Float) { override fun endClosing(delta: Float) {
TODO("not implemented")
} }
override fun dispose() { override fun dispose() {
TODO("not implemented")
} }
} }

View File

@@ -31,7 +31,6 @@ class UIProxyNewRandomGame : UICanvas() {
} }
override fun doClosing(delta: Float) { override fun doClosing(delta: Float) {
TODO("not implemented")
} }
override fun endOpening(delta: Float) { override fun endOpening(delta: Float) {

View File

@@ -2,14 +2,15 @@ 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.spriteassembler.ADProperties
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
import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.TerrarumIngame
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.gameactors.Pocketed import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.tvda.ByteArray64 import net.torvald.terrarum.tvda.*
import net.torvald.terrarum.tvda.ByteArray64Writer
import java.io.Reader import java.io.Reader
/** /**
@@ -42,6 +43,22 @@ object WriteActor {
} }
/**
* Player-specific [WriteActor].
*
* Created by minjaesong on 2021-10-07.
*/
object WritePlayer {
operator fun invoke(player: IngamePlayer, disk: VirtualDisk) {
val actorJson = WriteActor.encodeToByteArray64(player)
val adl = player.animDesc?.getRawADL() // NULLABLE!
val adlGlow = player.animDescGlow?.getRawADL() // NULLABLE!
}
operator fun invoke(player: IngamePlayer, skimmer: DiskSkimmer) {
}
}
/** /**
@@ -54,29 +71,37 @@ object WriteActor {
*/ */
object ReadActor { object ReadActor {
operator fun invoke(worldDataStream: Reader): Actor = operator fun invoke(disk: SimpleFileSystem, worldDataStream: Reader): Actor =
fillInDetails(Common.jsoner.fromJson(null, worldDataStream)) fillInDetails(disk, Common.jsoner.fromJson(null, worldDataStream))
fun readActorBare(worldDataStream: Reader): Actor = fun readActorBare(worldDataStream: Reader): Actor =
Common.jsoner.fromJson(null, worldDataStream) Common.jsoner.fromJson(null, worldDataStream)
private fun fillInDetails(actor: Actor): Actor { private fun fillInDetails(disk: SimpleFileSystem, actor: Actor): Actor {
actor.actorValue.actor = actor actor.actorValue.actor = actor
if (actor is Pocketed) if (actor is Pocketed)
actor.inventory.actor = actor actor.inventory.actor = actor
if (actor is ActorWithBody && actor is HasAssembledSprite) { if (actor is ActorWithBody && actor is HasAssembledSprite) {
val animFile = disk.getFile(-2L)
val animFileGlow = disk.getFile(-3L)
actor.sprite = SpriteAnimation(actor) actor.sprite = SpriteAnimation(actor)
if (actor.animDescPathGlow != null) actor.spriteGlow = SpriteAnimation(actor) if (animFileGlow != null) actor.spriteGlow = SpriteAnimation(actor)
actor.reassembleSprite(actor.sprite ?: throw InternalError("actor.sprite (type: SpriteAnimation) is null"), actor.spriteGlow) actor.reassembleSprite(
actor.sprite!!,
ADProperties(ByteArray64Reader(animFile!!.bytes, Common.CHARSET)),
actor.spriteGlow,
if (animFileGlow == null) null else ADProperties(ByteArray64Reader(animFileGlow.bytes, Common.CHARSET))
)
} }
return actor return actor
} }
fun readActorAndAddToWorld(ingame: TerrarumIngame, worldDataStream: Reader): Actor { fun readActorAndAddToWorld(ingame: TerrarumIngame, disk: SimpleFileSystem, worldDataStream: Reader): Actor {
val actor = invoke(worldDataStream) val actor = invoke(disk, worldDataStream)
// replace existing player // replace existing player
val oldPlayerID = ingame.actorNowPlaying?.referenceID val oldPlayerID = ingame.actorNowPlaying?.referenceID

View File

@@ -23,7 +23,7 @@ class DiskSkimmer(
val diskFile: File, val diskFile: File,
val charset: Charset = Charset.defaultCharset(), val charset: Charset = Charset.defaultCharset(),
noInit: Boolean = false noInit: Boolean = false
) { ): SimpleFileSystem {
/* /*
@@ -250,6 +250,8 @@ removefile:
} }
} }
override fun getFile(id: EntryID) = requestFile(id)?.contents as? EntryFile
/** /**
* Try to find a file with given path (which uses '/' as a separator). Is search is failed for whatever reason, * Try to find a file with given path (which uses '/' as a separator). Is search is failed for whatever reason,
* `null` is returned. * `null` is returned.

View File

@@ -0,0 +1,8 @@
package net.torvald.terrarum.tvda
/**
* Created by minjaesong on 2021-10-07.
*/
interface SimpleFileSystem {
fun getFile(id: EntryID): EntryFile?
}

View File

@@ -124,7 +124,7 @@ class VirtualDisk(
/** capacity of 0 makes the disk read-only */ /** capacity of 0 makes the disk read-only */
var capacity: Long, var capacity: Long,
var diskName: ByteArray = ByteArray(NAME_LENGTH) var diskName: ByteArray = ByteArray(NAME_LENGTH)
) { ): SimpleFileSystem {
var extraInfoBytes = ByteArray(16) var extraInfoBytes = ByteArray(16)
val entries = HashMap<EntryID, DiskEntry>() val entries = HashMap<EntryID, DiskEntry>()
var isReadOnly: Boolean var isReadOnly: Boolean
@@ -143,6 +143,8 @@ class VirtualDisk(
extraInfoBytes = footer.toByteArray() extraInfoBytes = footer.toByteArray()
} }
override fun getFile(id: EntryID) = try { VDUtil.getAsNormalFile(this, id) } catch (e: NullPointerException) { null }
private fun serializeEntriesOnly(): ByteArray64 { private fun serializeEntriesOnly(): ByteArray64 {
val buffer = ByteArray64() val buffer = ByteArray64()
entries.forEach { entries.forEach {

View File

@@ -84,7 +84,8 @@ class ArrayListMap<K, V> : MutableMap<K, V> {
} }
override fun clear() { override fun clear() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates. keysArray.clear()
valuesArray.clear()
} }
override fun compute(key: K, remappingFunction: BiFunction<in K, in V?, out V?>): V? { override fun compute(key: K, remappingFunction: BiFunction<in K, in V?, out V?>): V? {