read/writeactor to process all subclasses of Actor, not just a player; actor possession confirmed working

This commit is contained in:
minjaesong
2021-08-29 13:07:44 +09:00
parent c247f99e0e
commit 3fc6e28c4d
7 changed files with 88 additions and 33 deletions

View File

@@ -2,9 +2,9 @@ package net.torvald.terrarum
import com.badlogic.gdx.Screen import com.badlogic.gdx.Screen
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.utils.Queue
import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorID
import net.torvald.terrarum.gameactors.BlockMarkerActor import net.torvald.terrarum.gameactors.BlockMarkerActor
import net.torvald.terrarum.gameitem.ItemID import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
@@ -90,7 +90,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
// add blockmarking_actor into the actorlist // add blockmarking_actor into the actorlist
(CommonResourcePool.get("blockmarking_actor") as BlockMarkerActor).let { (CommonResourcePool.get("blockmarking_actor") as BlockMarkerActor).let {
it.isVisible = false // make sure the actor is invisible on new instance it.isVisible = false // make sure the actor is invisible on new instance
try { addNewActor(it) } catch (e: Error) {} try { addNewActor(it) } catch (e: ReferencedActorAlreadyExistsException) {}
} }
@@ -189,7 +189,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
fun getActorByID(ID: Int): Actor { fun getActorByID(ID: Int): Actor {
if (actorContainerActive.size == 0 && actorContainerInactive.size == 0) if (actorContainerActive.size == 0 && actorContainerInactive.size == 0)
throw IllegalArgumentException("Actor with ID $ID does not exist.") throw NoSuchActorWithIDException(ID)
var actor = actorContainerActive.searchFor(ID) { it.referenceID } var actor = actorContainerActive.searchFor(ID) { it.referenceID }
if (actor == null) { if (actor == null) {
@@ -201,7 +201,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
"Actor with ID $ID does not exist.", "Actor with ID $ID does not exist.",
null, JOptionPane.ERROR_MESSAGE null, JOptionPane.ERROR_MESSAGE
)*/ )*/
throw IllegalArgumentException("Actor with ID $ID does not exist.") throw NoSuchActorWithIDException(ID)
} }
else else
return actor return actor
@@ -245,7 +245,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
if (actor == null) return if (actor == null) return
if (theGameHasActor(actor.referenceID)) { if (theGameHasActor(actor.referenceID)) {
throw Error("The actor $actor already exists in the game") throw ReferencedActorAlreadyExistsException(actor)
} }
else { else {
actorContainerActive.add(actor) actorContainerActive.add(actor)
@@ -291,3 +291,8 @@ inline fun Lock.lock(body: () -> Unit) {
this.unlock() this.unlock()
} }
} }
class NoSuchActorWithIDException(id: ActorID) : Exception("Actor with ID $id does not exist.")
class NoSuchActorWithRefException(actor: Actor) : Exception("No such actor in the game: $actor")
class ReferencedActorAlreadyExistsException(actor: Actor) : Exception("The actor $actor already exists in the game")
class ProtectedActorRemovalException(whatisit: String) : Exception("Attempted to removed protected actor '$whatisit'")

View File

@@ -22,11 +22,9 @@ object CommandDict {
"togglenoclip" to ToggleNoClip, "togglenoclip" to ToggleNoClip,
"nc" to ToggleNoClip, "nc" to ToggleNoClip,
"setlocale" to SetLocale, "setlocale" to SetLocale,
//"zoom" to Zoom,
"teleport" to Teleport, "teleport" to Teleport,
"tp" to Teleport, "tp" to Teleport,
"cat" to CatStdout, "cat" to CatStdout,
"exportav" to ExportAV,
"setgl" to SetGlobalLightOverride, "setgl" to SetGlobalLightOverride,
"getfaction" to GetFactioning, "getfaction" to GetFactioning,
"auth" to Authenticator, "auth" to Authenticator,
@@ -43,11 +41,12 @@ object CommandDict {
"actorslist" to ActorsList, "actorslist" to ActorsList,
"setscale" to SetScale, "setscale" to SetScale,
"kill" to KillActor, "kill" to KillActor,
"money" to MoneyDisp,
"screenshot" to TakeScreenshot, "screenshot" to TakeScreenshot,
"resize" to ResizeScreen, "resize" to ResizeScreen,
"possess" to Possess,
// Test codes // Test codes
"money" to MoneyDisp,
"bulletintest" to SetBulletin, "bulletintest" to SetBulletin,
"tips" to PrintRandomTips, "tips" to PrintRandomTips,
"langtest" to LangTest, "langtest" to LangTest,
@@ -60,6 +59,7 @@ object CommandDict {
"spawnlunarlander" to SpawnPhysTestLunarLander, "spawnlunarlander" to SpawnPhysTestLunarLander,
"savetest" to SavegameWriterTest, "savetest" to SavegameWriterTest,
"exportav" to ExportAV,
/* !! */"exportmeta" to ExportMeta, /* !! */"exportmeta" to ExportMeta,
/* !! */"exportworld" to ExportWorld, /* !! */"exportworld" to ExportWorld,
/* !! */"exportactor" to ExportActor, /* !! */"exportactor" to ExportActor,

View File

@@ -207,8 +207,6 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
lateinit var gameLoadMode: GameLoadMode lateinit var gameLoadMode: GameLoadMode
lateinit var gameLoadInfoPayload: Any lateinit var gameLoadInfoPayload: Any
lateinit var theRealGamer: IngamePlayer
// get() = actorGamer as IngamePlayer
@@ -255,7 +253,6 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
} }
actorNowPlaying = actor actorNowPlaying = actor
theRealGamer = actor
addNewActor(actorNowPlaying) addNewActor(actorNowPlaying)
} }
@@ -736,23 +733,23 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
// check if currently pocessed actor is removed from game // check if currently pocessed actor is removed from game
if (!theGameHasActor(actorNowPlaying)) { if (!theGameHasActor(actorNowPlaying)) {
// re-possess canonical player // re-possess canonical player
if (theGameHasActor(Terrarum.PLAYER_REF_ID)) if (theGameHasActor(actorGamer))
changePossession(Terrarum.PLAYER_REF_ID) changePossession(actorGamer)
else else
changePossession(0x51621D) // FIXME fallback debug mode (FIXME is there for a reminder visible in ya IDE) actorNowPlaying = null
} }
} }
private fun changePossession(newActor: ActorHumanoid) { internal fun changePossession(newActor: ActorHumanoid) {
if (!theGameHasActor(actorNowPlaying)) { if (!theGameHasActor(actorNowPlaying)) {
throw IllegalArgumentException("No such actor in the game: $newActor") throw NoSuchActorWithRefException(newActor)
} }
actorNowPlaying = newActor actorNowPlaying = newActor
//WorldSimulator(actorNowPlaying, AppLoader.getSmoothDelta().toFloat()) //WorldSimulator(actorNowPlaying, AppLoader.getSmoothDelta().toFloat())
} }
private fun changePossession(refid: Int) { internal fun changePossession(refid: Int) {
val actorToChange = getActorByID(refid) val actorToChange = getActorByID(refid)
if (actorToChange !is ActorHumanoid) { if (actorToChange !is ActorHumanoid) {
@@ -916,8 +913,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 == theRealGamer.referenceID || actor.referenceID == 0x51621D) // do not delete this magic if (actor.referenceID == actorGamer.referenceID || actor.referenceID == 0x51621D) // do not delete this magic
throw RuntimeException("Attempted to remove player.") throw ProtectedActorRemovalException("Player")
forceRemoveActor(actor) forceRemoveActor(actor)
} }
@@ -970,7 +967,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
if (actor == null) return if (actor == null) return
if (AppLoader.IS_DEVELOPMENT_BUILD && theGameHasActor(actor.referenceID)) { if (AppLoader.IS_DEVELOPMENT_BUILD && theGameHasActor(actor.referenceID)) {
throw Error("The actor $actor already exists in the game") throw ReferencedActorAlreadyExistsException(actor)
} }
else { else {
if (actor.referenceID !in ReferencingRanges.ACTORS_WIRES && actor.referenceID !in ReferencingRanges.ACTORS_WIRES_HELPER) { if (actor.referenceID !in ReferencingRanges.ACTORS_WIRES && actor.referenceID !in ReferencingRanges.ACTORS_WIRES_HELPER) {
@@ -985,10 +982,11 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
fun activateDormantActor(actor: Actor) { fun activateDormantActor(actor: Actor) {
if (AppLoader.IS_DEVELOPMENT_BUILD && !isInactive(actor.referenceID)) { if (AppLoader.IS_DEVELOPMENT_BUILD && !isInactive(actor.referenceID)) {
if (isActive(actor.referenceID)) /*if (isActive(actor.referenceID))
throw Error("The actor $actor is already activated") throw Error("The actor $actor is already activated")
else else
throw Error("The actor $actor already exists in the game") throw Error("The actor $actor already exists in the game")*/
return
} }
else { else {
actorContainerInactive.remove(actor) actorContainerInactive.remove(actor)

View File

@@ -0,0 +1,30 @@
package net.torvald.terrarum.modulebasegame.console
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.modulebasegame.TerrarumIngame
/**
* Created by minjaesong on 2021-08-29.
*/
object Possess : ConsoleCommand {
override fun execute(args: Array<String>) {
if (args.size == 2) {
val ingame = Terrarum.ingame!! as TerrarumIngame
if (args[1].lowercase() == "reset")
ingame.changePossession(ingame.actorGamer)
else
ingame.changePossession(args[1].toInt())
}
else {
printUsage()
}
}
override fun printUsage() {
Echo("Usage: possess (id) | possess reset")
}
}

View File

@@ -2,38 +2,59 @@ 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.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.IngamePlayer
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import java.io.InputStream import java.io.InputStream
import java.io.Reader import java.io.Reader
/** /**
* 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. * Created by minjaesong on 2021-08-27.
*/ */
class ReadActor(val ingame: TerrarumIngame) { class ReadActor(val ingame: TerrarumIngame) {
open fun invoke(worldDataStream: InputStream) { open fun invoke(worldDataStream: InputStream) {
postRead(Common.jsoner.fromJson(IngamePlayer::class.java, worldDataStream)) postRead(Common.jsoner.fromJson(null, worldDataStream))
} }
open fun invoke(worldDataStream: Reader) { open fun invoke(worldDataStream: Reader) {
postRead(Common.jsoner.fromJson(IngamePlayer::class.java, worldDataStream)) postRead(Common.jsoner.fromJson(null, worldDataStream))
} }
private fun postRead(actor: IngamePlayer) { private fun postRead(actor: Actor) {
// filling in Transients // filling in Transients
actor.actorValue.actor = actor actor.actorValue.actor = actor
actor.inventory.actor = actor
actor.sprite = SpriteAnimation(actor) if (actor is Pocketed)
if (actor.animDescPathGlow != null) actor.spriteGlow = SpriteAnimation(actor) actor.inventory.actor = actor
actor.reassembleSprite(actor.sprite!!, actor.spriteGlow)
if (actor is ActorWithBody) {
actor.sprite = SpriteAnimation(actor)
if (actor is HasAssembledSprite) {
if (actor.animDescPathGlow != null) actor.spriteGlow = SpriteAnimation(actor)
actor.reassembleSprite(actor.sprite!!, actor.spriteGlow)
}
}
// replace existing player // replace existing player
ingame.forceRemoveActor(ingame.actorNowPlaying!!) val oldPlayerID = ingame.actorNowPlaying?.referenceID
try {
ingame.forceRemoveActor(ingame.getActorByID(actor.referenceID))
}
catch (e: NoSuchActorWithIDException) { /* no actor to delete, you may proceed */ }
ingame.addNewActor(actor) ingame.addNewActor(actor)
ingame.actorNowPlaying = actor
if (actor.referenceID == oldPlayerID)
ingame.actorNowPlaying = actor as ActorHumanoid
} }
} }

View File

@@ -14,7 +14,8 @@ import java.math.BigInteger
object WriteActor { object WriteActor {
operator fun invoke(actor: IngamePlayer): String { operator fun invoke(actor: IngamePlayer): String {
return Common.jsoner.toJson(actor) val s = Common.jsoner.toJson(actor, actor.javaClass)
return """{"class":"${actor.javaClass.canonicalName}",${s.substring(1)}"""
} }
fun encodeToByteArray64(actor: IngamePlayer): ByteArray64 { fun encodeToByteArray64(actor: IngamePlayer): ByteArray64 {

View File

@@ -27,7 +27,7 @@ open class WriteMeta(val ingame: TerrarumIngame) {
"randseed1": ${RoguelikeRandomiser.RNG.state1}, "randseed1": ${RoguelikeRandomiser.RNG.state1},
"weatseed0": ${WeatherMixer.RNG.state0}, "weatseed0": ${WeatherMixer.RNG.state0},
"weatseed1": ${WeatherMixer.RNG.state1}, "weatseed1": ${WeatherMixer.RNG.state1},
"playerid": ${ingame.theRealGamer.referenceID}, "playerid": ${ingame.actorGamer.referenceID},
"creation_t": ${world.creationTime}, "creation_t": ${world.creationTime},
"lastplay_t": ${world.lastPlayTime}, "lastplay_t": ${world.lastPlayTime},
"playtime_t": ${world.totalPlayTime}, "playtime_t": ${world.totalPlayTime},