mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-12 19:44:05 +09:00
158 lines
5.5 KiB
Kotlin
158 lines
5.5 KiB
Kotlin
package net.torvald.terrarum.serialise
|
|
|
|
import net.torvald.spriteanimation.HasAssembledSprite
|
|
import net.torvald.spriteanimation.SpriteAnimation
|
|
import net.torvald.spriteassembler.ADProperties
|
|
import net.torvald.terrarum.gameactors.Actor
|
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
|
import net.torvald.terrarum.savegame.*
|
|
import java.io.Reader
|
|
|
|
/**
|
|
* Created by minjaesong on 2021-08-24.
|
|
*/
|
|
object WriteActor {
|
|
|
|
operator fun invoke(actor: Actor): String {
|
|
val s = Common.jsoner.toJson(actor, actor.javaClass)
|
|
return """{"class":"${actor.javaClass.canonicalName}",${s.substring(1)}"""
|
|
}
|
|
|
|
fun encodeToByteArray64(actor: Actor): ByteArray64 {
|
|
val baw = ByteArray64Writer(Common.CHARSET)
|
|
|
|
val classDef = """{"class":"${actor.javaClass.canonicalName}""""
|
|
baw.write(classDef)
|
|
Common.jsoner.toJson(actor, actor.javaClass, baw)
|
|
baw.flush(); baw.close()
|
|
// by this moment, contents of the baw will be:
|
|
// {"class":"some.class.Name"{"actorValue":{},......}
|
|
// (note that first bracket is not closed, and another open bracket after "class" property)
|
|
// and we want to turn it into this:
|
|
// {"class":"some.class.Name","actorValue":{},......}
|
|
val ba = baw.toByteArray64()
|
|
ba[classDef.toByteArray(Common.CHARSET).size.toLong()] = ','.code.toByte()
|
|
|
|
return ba
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Player-specific [WriteActor]. Will write JSON and Animation Description Languages
|
|
*
|
|
* Created by minjaesong on 2021-10-07.
|
|
*/
|
|
object WritePlayer {
|
|
|
|
/**
|
|
* 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)
|
|
}
|
|
|
|
operator fun invoke(player: IngamePlayer, playerDisk: VirtualDisk, ingame: TerrarumIngame, time_t: Long) {
|
|
player.lastPlayTime = time_t
|
|
player.totalPlayTime += time_t - ingame.loadedTime_t
|
|
|
|
|
|
// restore player prop backup created on load-time for multiplayer
|
|
if (ingame.isMultiplayer) {
|
|
player.setPosition(player.unauthorisedPlayerProps.physics.position)
|
|
player.actorValue = player.unauthorisedPlayerProps.actorValue!!
|
|
player.inventory = player.unauthorisedPlayerProps.inventory!!
|
|
}
|
|
|
|
player.worldCurrentlyPlaying = ingame.world.worldIndex
|
|
|
|
|
|
val actorJson = WriteActor.encodeToByteArray64(player)
|
|
val adl = player.animDesc!!.getRawADL()
|
|
val adlGlow = player.animDescGlow?.getRawADL() // NULLABLE!
|
|
|
|
val jsonContents = EntryFile(actorJson)
|
|
val jsonCreationDate = playerDisk.getEntry(-1)?.creationDate ?: time_t
|
|
addFile(playerDisk, DiskEntry(-1L, 0L, jsonCreationDate, time_t, jsonContents))
|
|
|
|
val adlContents = EntryFile(ByteArray64.fromByteArray(adl.toByteArray(Common.CHARSET)))
|
|
val adlCreationDate = playerDisk.getEntry(-2)?.creationDate ?: time_t
|
|
addFile(playerDisk, DiskEntry(-2L, 0L, adlCreationDate, time_t, adlContents))
|
|
|
|
if (adlGlow != null) {
|
|
val adlGlowContents = EntryFile(ByteArray64.fromByteArray(adlGlow.toByteArray(Common.CHARSET)))
|
|
val adlGlowCreationDate = playerDisk.getEntry(-3)?.creationDate ?: time_t
|
|
addFile(playerDisk, DiskEntry(-3L, 0L, adlGlowCreationDate, time_t, adlGlowContents))
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Player-specific [ReadActor].
|
|
*
|
|
* @param disk disk
|
|
* @param dataStream Reader containing JSON file
|
|
*
|
|
* Created by minjaesong on 2021-10-07.
|
|
*/
|
|
object ReadPlayer {
|
|
|
|
operator fun invoke(disk: SimpleFileSystem, dataStream: Reader): IngamePlayer =
|
|
ReadActor(disk, dataStream) as IngamePlayer
|
|
|
|
}
|
|
|
|
/**
|
|
* Actor's JSON representation is expected to have "class" property on the root object, such as:
|
|
* ```
|
|
* "class":"net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer"
|
|
* ```
|
|
*
|
|
* Created by minjaesong on 2021-08-27.
|
|
*/
|
|
object ReadActor {
|
|
|
|
operator fun invoke(disk: SimpleFileSystem, dataStream: Reader): Actor =
|
|
fillInDetails(disk, Common.jsoner.fromJson(null, dataStream))
|
|
|
|
private fun fillInDetails(disk: SimpleFileSystem, actor: Actor): Actor {
|
|
actor.reload()
|
|
|
|
|
|
if (actor is ActorWithBody && actor is IngamePlayer) {
|
|
val animFile = disk.getFile(-2L)
|
|
val animFileGlow = disk.getFile(-3L)
|
|
val bodypartsFile = disk.getFile(-1025)
|
|
|
|
actor.sprite = SpriteAnimation(actor)
|
|
actor.animDesc = ADProperties(ByteArray64Reader(animFile!!.bytes, Common.CHARSET))
|
|
if (animFileGlow != null) {
|
|
actor.spriteGlow = SpriteAnimation(actor)
|
|
actor.animDescGlow = ADProperties(ByteArray64Reader(animFileGlow.bytes, Common.CHARSET))
|
|
}
|
|
|
|
if (bodypartsFile != null)
|
|
actor.reassembleSprite(disk, actor.sprite!!, actor.spriteGlow)
|
|
else
|
|
actor.reassembleSprite(actor.sprite!!, actor.spriteGlow)
|
|
}
|
|
else if (actor is ActorWithBody && actor is HasAssembledSprite) {
|
|
if (actor.animDesc != null) actor.sprite = SpriteAnimation(actor)
|
|
if (actor.animDescGlow != null) actor.spriteGlow = SpriteAnimation(actor)
|
|
|
|
actor.reassembleSprite(actor.sprite, actor.spriteGlow)
|
|
}
|
|
|
|
|
|
return actor
|
|
}
|
|
|
|
} |