mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
new save format wip (no branching on this commit)
This commit is contained in:
@@ -4,6 +4,8 @@ import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import net.torvald.spriteassembler.ADProperties
|
||||
import net.torvald.spriteassembler.AssembleSheetPixmap
|
||||
import net.torvald.terrarum.tvda.DiskSkimmer
|
||||
import net.torvald.terrarum.tvda.SimpleFileSystem
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
|
||||
/**
|
||||
@@ -12,9 +14,9 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
interface HasAssembledSprite {
|
||||
|
||||
/** ADL path for main sprite. Necessary. */
|
||||
var animDescPath: String
|
||||
var animDesc: ADProperties?
|
||||
/** 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?)
|
||||
|
||||
@@ -28,10 +30,11 @@ interface HasAssembledSprite {
|
||||
* reassembleSprite(this.sprite, this.spriteGlow)
|
||||
* ```
|
||||
*/
|
||||
fun reassembleSprite(sprite: SpriteAnimation, spriteGlow: SpriteAnimation? = null) {
|
||||
_rebuild(ADProperties(Gdx.files.internal(animDescPath)), sprite)
|
||||
if (animDescPathGlow != null && spriteGlow != null)
|
||||
_rebuild(ADProperties(Gdx.files.internal(animDescPathGlow)), 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 rebuild(animDescPath: String, spriteAnimation: SpriteAnimation) {
|
||||
@@ -50,6 +53,8 @@ interface HasAssembledSprite {
|
||||
private fun _rebuild(ad: ADProperties, sprite: SpriteAnimation) {
|
||||
// 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 texture = Texture(pixmap)
|
||||
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.torvald.spriteassembler
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import net.torvald.terrarum.linearSearchBy
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import java.io.InputStream
|
||||
import java.io.Reader
|
||||
import java.util.*
|
||||
@@ -33,6 +34,7 @@ internal data class Transform(val joint: Joint, val translate: ADPropertyObject.
|
||||
|
||||
class ADProperties {
|
||||
private var fileFrom = ""
|
||||
private var adlString = ""
|
||||
private val javaProp = Properties()
|
||||
|
||||
/** Every key is CAPITALISED */
|
||||
@@ -68,30 +70,31 @@ class ADProperties {
|
||||
var rows = -1; private set
|
||||
var cols = -1; private set
|
||||
|
||||
fun getRawADL() = adlString
|
||||
|
||||
companion object {
|
||||
const val ALL_JOINT_SELECT_KEY = "ALL"
|
||||
}
|
||||
|
||||
constructor(gdxFile: FileHandle) {
|
||||
fileFrom = gdxFile.path()
|
||||
adlString = gdxFile.readString(Common.CHARSET.name())
|
||||
javaProp.load(gdxFile.read())
|
||||
continueLoad()
|
||||
}
|
||||
|
||||
constructor(reader: Reader) {
|
||||
adlString = reader.readText()
|
||||
javaProp.load(reader)
|
||||
continueLoad()
|
||||
}
|
||||
|
||||
constructor(inputStream: InputStream) {
|
||||
adlString = inputStream.readAllBytes().toString(Common.CHARSET)
|
||||
javaProp.load(inputStream)
|
||||
continueLoad()
|
||||
}
|
||||
|
||||
constructor(javaProp: Properties) {
|
||||
this.javaProp.putAll(javaProp.toMap())
|
||||
}
|
||||
|
||||
private fun continueLoad() {
|
||||
// sanity check
|
||||
reservedProps.forEach {
|
||||
|
||||
@@ -2,7 +2,9 @@ package net.torvald.spriteassembler
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import net.torvald.terrarum.linearSearch
|
||||
import java.io.InputStream
|
||||
|
||||
/**
|
||||
* 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)
|
||||
canvas.blending = Pixmap.Blending.SourceOver
|
||||
|
||||
val fileGetter = { path: String ->
|
||||
Gdx.files.internal(path).read()
|
||||
}
|
||||
|
||||
// actually draw
|
||||
properties.transforms.forEach { t, _ ->
|
||||
drawThisFrame(t, canvas, properties)
|
||||
drawThisFrame(t, canvas, properties, fileGetter)
|
||||
}
|
||||
|
||||
return canvas
|
||||
@@ -28,15 +33,21 @@ object AssembleSheetPixmap {
|
||||
|
||||
private fun drawThisFrame(frameName: String,
|
||||
canvas: Pixmap,
|
||||
properties: ADProperties
|
||||
properties: ADProperties,
|
||||
fileGetter: (String) -> InputStream
|
||||
) {
|
||||
val theAnim = properties.getAnimByFrameName(frameName)
|
||||
val skeleton = theAnim.skeleton.joints.reversed()
|
||||
val transforms = properties.getTransform(frameName)
|
||||
val bodypartOrigins = properties.bodyparts
|
||||
val bodypartImages = properties.bodyparts.keys.map {
|
||||
val file = Gdx.files.internal("assets/${properties.toFilename(it)}")
|
||||
it to (if (file.exists()) Pixmap(file) else null)
|
||||
try {
|
||||
val bytes = fileGetter("assets/${properties.toFilename(it)}").readAllBytes()
|
||||
it to Pixmap(bytes, 0, bytes.size)
|
||||
}
|
||||
catch (e: GdxRuntimeException) {
|
||||
it to null
|
||||
}
|
||||
}.toMap()
|
||||
val transformList = AssembleFrameBase.makeTransformList(skeleton, transforms)
|
||||
|
||||
|
||||
@@ -287,7 +287,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
private fun postInitForLoadFromSave(codices: Codices) {
|
||||
codices.actors.forEach {
|
||||
try {
|
||||
val actor = ReadActor(LoadSavegame.getFileReader(codices.disk, it.toLong()))
|
||||
val actor = ReadActor(codices.disk, LoadSavegame.getFileReader(codices.disk, it.toLong()))
|
||||
addNewActor(actor)
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
|
||||
@@ -34,7 +34,7 @@ object ImportWorld : ConsoleCommand {
|
||||
Echo("Usage: Importworld filename-without-extension")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
object ImportActor : ConsoleCommand {
|
||||
override fun execute(args: Array<String>) {
|
||||
if (args.size == 2) {
|
||||
@@ -56,4 +56,4 @@ object ImportActor : ConsoleCommand {
|
||||
override fun printUsage() {
|
||||
Echo("Usage: Importactor filename-without-extension")
|
||||
}
|
||||
}
|
||||
}*/
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.torvald.terrarum.modulebasegame.gameactors
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import net.torvald.spriteanimation.HasAssembledSprite
|
||||
import net.torvald.spriteassembler.ADProperties
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gameactors.AVKey
|
||||
|
||||
@@ -13,15 +15,15 @@ import net.torvald.terrarum.gameactors.AVKey
|
||||
|
||||
class IngamePlayer : ActorHumanoid, HasAssembledSprite {
|
||||
|
||||
override var animDescPath = "invalid"
|
||||
override var animDescPathGlow: String? = null
|
||||
override var animDesc: ADProperties? = null
|
||||
override var animDescGlow: ADProperties? = null
|
||||
internal var worldCurrentlyPlaying = 0 // only filled up on save and load; DO NOT USE THIS
|
||||
|
||||
private constructor()
|
||||
|
||||
constructor(animDescPath: String, animDescPathGlow: String?, born: Long) : super(born) {
|
||||
this.animDescPath = animDescPath
|
||||
this.animDescPathGlow = animDescPathGlow
|
||||
animDesc = ADProperties(Gdx.files.internal(animDescPath))
|
||||
if (animDescPathGlow != null) animDescGlow = ADProperties(Gdx.files.internal(animDescPathGlow))
|
||||
actorValue[AVKey.__HISTORICAL_BORNTIME] = born
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ object PlayerBuilderTestSubject1 {
|
||||
|
||||
p.sprite = 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)
|
||||
|
||||
// ingame must teleport the player to the spawn point
|
||||
|
||||
@@ -31,7 +31,7 @@ object PlayerBuilderWerebeastTest {
|
||||
|
||||
p.sprite = 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.setPosition(3.0 * TILE_SIZE, 3.0 * TILE_SIZE)
|
||||
|
||||
@@ -28,7 +28,6 @@ class UIProxyNewBuildingMaker : UICanvas() {
|
||||
}
|
||||
|
||||
override fun doClosing(delta: Float) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun endOpening(delta: Float) {
|
||||
@@ -40,10 +39,8 @@ class UIProxyNewBuildingMaker : UICanvas() {
|
||||
}
|
||||
|
||||
override fun endClosing(delta: Float) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@ class UIProxyNewRandomGame : UICanvas() {
|
||||
}
|
||||
|
||||
override fun doClosing(delta: Float) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun endOpening(delta: Float) {
|
||||
|
||||
@@ -2,14 +2,15 @@ package net.torvald.terrarum.serialise
|
||||
|
||||
import net.torvald.spriteanimation.HasAssembledSprite
|
||||
import net.torvald.spriteanimation.SpriteAnimation
|
||||
import net.torvald.spriteassembler.ADProperties
|
||||
import net.torvald.terrarum.NoSuchActorWithIDException
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
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.tvda.ByteArray64
|
||||
import net.torvald.terrarum.tvda.ByteArray64Writer
|
||||
import net.torvald.terrarum.tvda.*
|
||||
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 {
|
||||
|
||||
operator fun invoke(worldDataStream: Reader): Actor =
|
||||
fillInDetails(Common.jsoner.fromJson(null, worldDataStream))
|
||||
operator fun invoke(disk: SimpleFileSystem, worldDataStream: Reader): Actor =
|
||||
fillInDetails(disk, Common.jsoner.fromJson(null, worldDataStream))
|
||||
|
||||
fun readActorBare(worldDataStream: Reader): Actor =
|
||||
Common.jsoner.fromJson(null, worldDataStream)
|
||||
|
||||
private fun fillInDetails(actor: Actor): Actor {
|
||||
private fun fillInDetails(disk: SimpleFileSystem, actor: Actor): Actor {
|
||||
actor.actorValue.actor = actor
|
||||
|
||||
if (actor is Pocketed)
|
||||
actor.inventory.actor = actor
|
||||
|
||||
if (actor is ActorWithBody && actor is HasAssembledSprite) {
|
||||
val animFile = disk.getFile(-2L)
|
||||
val animFileGlow = disk.getFile(-3L)
|
||||
|
||||
actor.sprite = SpriteAnimation(actor)
|
||||
if (actor.animDescPathGlow != null) actor.spriteGlow = SpriteAnimation(actor)
|
||||
actor.reassembleSprite(actor.sprite ?: throw InternalError("actor.sprite (type: SpriteAnimation) is null"), actor.spriteGlow)
|
||||
if (animFileGlow != null) actor.spriteGlow = SpriteAnimation(actor)
|
||||
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
|
||||
}
|
||||
|
||||
fun readActorAndAddToWorld(ingame: TerrarumIngame, worldDataStream: Reader): Actor {
|
||||
val actor = invoke(worldDataStream)
|
||||
fun readActorAndAddToWorld(ingame: TerrarumIngame, disk: SimpleFileSystem, worldDataStream: Reader): Actor {
|
||||
val actor = invoke(disk, worldDataStream)
|
||||
|
||||
// replace existing player
|
||||
val oldPlayerID = ingame.actorNowPlaying?.referenceID
|
||||
|
||||
@@ -23,7 +23,7 @@ class DiskSkimmer(
|
||||
val diskFile: File,
|
||||
val charset: Charset = Charset.defaultCharset(),
|
||||
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,
|
||||
* `null` is returned.
|
||||
|
||||
8
src/net/torvald/terrarum/tvda/SimpleFileSystem.kt
Normal file
8
src/net/torvald/terrarum/tvda/SimpleFileSystem.kt
Normal file
@@ -0,0 +1,8 @@
|
||||
package net.torvald.terrarum.tvda
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2021-10-07.
|
||||
*/
|
||||
interface SimpleFileSystem {
|
||||
fun getFile(id: EntryID): EntryFile?
|
||||
}
|
||||
@@ -124,7 +124,7 @@ class VirtualDisk(
|
||||
/** capacity of 0 makes the disk read-only */
|
||||
var capacity: Long,
|
||||
var diskName: ByteArray = ByteArray(NAME_LENGTH)
|
||||
) {
|
||||
): SimpleFileSystem {
|
||||
var extraInfoBytes = ByteArray(16)
|
||||
val entries = HashMap<EntryID, DiskEntry>()
|
||||
var isReadOnly: Boolean
|
||||
@@ -143,6 +143,8 @@ class VirtualDisk(
|
||||
extraInfoBytes = footer.toByteArray()
|
||||
}
|
||||
|
||||
override fun getFile(id: EntryID) = try { VDUtil.getAsNormalFile(this, id) } catch (e: NullPointerException) { null }
|
||||
|
||||
private fun serializeEntriesOnly(): ByteArray64 {
|
||||
val buffer = ByteArray64()
|
||||
entries.forEach {
|
||||
|
||||
@@ -84,7 +84,8 @@ class ArrayListMap<K, V> : MutableMap<K, V> {
|
||||
}
|
||||
|
||||
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? {
|
||||
|
||||
Reference in New Issue
Block a user