From 3fc6e28c4d2a35c199a5a2481d667717e73e8de7 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sun, 29 Aug 2021 13:07:44 +0900 Subject: [PATCH] read/writeactor to process all subclasses of Actor, not just a player; actor possession confirmed working --- src/net/torvald/terrarum/IngameInstance.kt | 15 ++++--- .../torvald/terrarum/console/CommandDict.kt | 6 +-- .../terrarum/modulebasegame/TerrarumIngame.kt | 26 ++++++------- .../modulebasegame/console/Possess.kt | 30 ++++++++++++++ .../torvald/terrarum/serialise/ReadActor.kt | 39 ++++++++++++++----- .../torvald/terrarum/serialise/WriteActor.kt | 3 +- .../torvald/terrarum/serialise/WriteMeta.kt | 2 +- 7 files changed, 88 insertions(+), 33 deletions(-) create mode 100644 src/net/torvald/terrarum/modulebasegame/console/Possess.kt diff --git a/src/net/torvald/terrarum/IngameInstance.kt b/src/net/torvald/terrarum/IngameInstance.kt index b651b2f8a..4efa905fa 100644 --- a/src/net/torvald/terrarum/IngameInstance.kt +++ b/src/net/torvald/terrarum/IngameInstance.kt @@ -2,9 +2,9 @@ package net.torvald.terrarum import com.badlogic.gdx.Screen import com.badlogic.gdx.graphics.g2d.SpriteBatch -import com.badlogic.gdx.utils.Queue import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.gameactors.Actor +import net.torvald.terrarum.gameactors.ActorID import net.torvald.terrarum.gameactors.BlockMarkerActor import net.torvald.terrarum.gameitem.ItemID import net.torvald.terrarum.gameworld.GameWorld @@ -90,7 +90,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { // add blockmarking_actor into the actorlist (CommonResourcePool.get("blockmarking_actor") as BlockMarkerActor).let { 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 { 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 } if (actor == null) { @@ -201,7 +201,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { "Actor with ID $ID does not exist.", null, JOptionPane.ERROR_MESSAGE )*/ - throw IllegalArgumentException("Actor with ID $ID does not exist.") + throw NoSuchActorWithIDException(ID) } else return actor @@ -245,7 +245,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { if (actor == null) return if (theGameHasActor(actor.referenceID)) { - throw Error("The actor $actor already exists in the game") + throw ReferencedActorAlreadyExistsException(actor) } else { actorContainerActive.add(actor) @@ -291,3 +291,8 @@ inline fun Lock.lock(body: () -> Unit) { 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'") diff --git a/src/net/torvald/terrarum/console/CommandDict.kt b/src/net/torvald/terrarum/console/CommandDict.kt index 56ee0ea28..7dcee46a4 100644 --- a/src/net/torvald/terrarum/console/CommandDict.kt +++ b/src/net/torvald/terrarum/console/CommandDict.kt @@ -22,11 +22,9 @@ object CommandDict { "togglenoclip" to ToggleNoClip, "nc" to ToggleNoClip, "setlocale" to SetLocale, - //"zoom" to Zoom, "teleport" to Teleport, "tp" to Teleport, "cat" to CatStdout, - "exportav" to ExportAV, "setgl" to SetGlobalLightOverride, "getfaction" to GetFactioning, "auth" to Authenticator, @@ -43,11 +41,12 @@ object CommandDict { "actorslist" to ActorsList, "setscale" to SetScale, "kill" to KillActor, - "money" to MoneyDisp, "screenshot" to TakeScreenshot, "resize" to ResizeScreen, + "possess" to Possess, // Test codes + "money" to MoneyDisp, "bulletintest" to SetBulletin, "tips" to PrintRandomTips, "langtest" to LangTest, @@ -60,6 +59,7 @@ object CommandDict { "spawnlunarlander" to SpawnPhysTestLunarLander, "savetest" to SavegameWriterTest, + "exportav" to ExportAV, /* !! */"exportmeta" to ExportMeta, /* !! */"exportworld" to ExportWorld, /* !! */"exportactor" to ExportActor, diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index f91029881..caa08e9aa 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -207,8 +207,6 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { lateinit var gameLoadMode: GameLoadMode 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 - theRealGamer = actor addNewActor(actorNowPlaying) } @@ -736,23 +733,23 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { // check if currently pocessed actor is removed from game if (!theGameHasActor(actorNowPlaying)) { // re-possess canonical player - if (theGameHasActor(Terrarum.PLAYER_REF_ID)) - changePossession(Terrarum.PLAYER_REF_ID) + if (theGameHasActor(actorGamer)) + changePossession(actorGamer) 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)) { - throw IllegalArgumentException("No such actor in the game: $newActor") + throw NoSuchActorWithRefException(newActor) } actorNowPlaying = newActor //WorldSimulator(actorNowPlaying, AppLoader.getSmoothDelta().toFloat()) } - private fun changePossession(refid: Int) { + internal fun changePossession(refid: Int) { val actorToChange = getActorByID(refid) if (actorToChange !is ActorHumanoid) { @@ -916,8 +913,8 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { override fun removeActor(actor: Actor?) { if (actor == null) return - if (actor.referenceID == theRealGamer.referenceID || actor.referenceID == 0x51621D) // do not delete this magic - throw RuntimeException("Attempted to remove player.") + if (actor.referenceID == actorGamer.referenceID || actor.referenceID == 0x51621D) // do not delete this magic + throw ProtectedActorRemovalException("Player") forceRemoveActor(actor) } @@ -970,7 +967,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { if (actor == null) return if (AppLoader.IS_DEVELOPMENT_BUILD && theGameHasActor(actor.referenceID)) { - throw Error("The actor $actor already exists in the game") + throw ReferencedActorAlreadyExistsException(actor) } else { 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) { if (AppLoader.IS_DEVELOPMENT_BUILD && !isInactive(actor.referenceID)) { - if (isActive(actor.referenceID)) + /*if (isActive(actor.referenceID)) throw Error("The actor $actor is already activated") else - throw Error("The actor $actor already exists in the game") + throw Error("The actor $actor already exists in the game")*/ + return } else { actorContainerInactive.remove(actor) diff --git a/src/net/torvald/terrarum/modulebasegame/console/Possess.kt b/src/net/torvald/terrarum/modulebasegame/console/Possess.kt new file mode 100644 index 000000000..3ddd86c37 --- /dev/null +++ b/src/net/torvald/terrarum/modulebasegame/console/Possess.kt @@ -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) { + 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") + } + +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/ReadActor.kt b/src/net/torvald/terrarum/serialise/ReadActor.kt index 3f71148dd..8ed49a0b7 100644 --- a/src/net/torvald/terrarum/serialise/ReadActor.kt +++ b/src/net/torvald/terrarum/serialise/ReadActor.kt @@ -2,38 +2,59 @@ package net.torvald.terrarum.serialise import net.torvald.spriteanimation.HasAssembledSprite import net.torvald.spriteanimation.SpriteAnimation +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 java.io.InputStream 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. */ class ReadActor(val ingame: TerrarumIngame) { open fun invoke(worldDataStream: InputStream) { - postRead(Common.jsoner.fromJson(IngamePlayer::class.java, worldDataStream)) + postRead(Common.jsoner.fromJson(null, worldDataStream)) } 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 actor.actorValue.actor = actor - actor.inventory.actor = actor - actor.sprite = SpriteAnimation(actor) - if (actor.animDescPathGlow != null) actor.spriteGlow = SpriteAnimation(actor) - actor.reassembleSprite(actor.sprite!!, actor.spriteGlow) + + if (actor is Pocketed) + actor.inventory.actor = actor + + 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 - 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.actorNowPlaying = actor + + if (actor.referenceID == oldPlayerID) + ingame.actorNowPlaying = actor as ActorHumanoid } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/WriteActor.kt b/src/net/torvald/terrarum/serialise/WriteActor.kt index 8085f4fa3..66b98a839 100644 --- a/src/net/torvald/terrarum/serialise/WriteActor.kt +++ b/src/net/torvald/terrarum/serialise/WriteActor.kt @@ -14,7 +14,8 @@ import java.math.BigInteger object WriteActor { 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 { diff --git a/src/net/torvald/terrarum/serialise/WriteMeta.kt b/src/net/torvald/terrarum/serialise/WriteMeta.kt index 8b3aa654a..bca151623 100644 --- a/src/net/torvald/terrarum/serialise/WriteMeta.kt +++ b/src/net/torvald/terrarum/serialise/WriteMeta.kt @@ -27,7 +27,7 @@ open class WriteMeta(val ingame: TerrarumIngame) { "randseed1": ${RoguelikeRandomiser.RNG.state1}, "weatseed0": ${WeatherMixer.RNG.state0}, "weatseed1": ${WeatherMixer.RNG.state1}, -"playerid": ${ingame.theRealGamer.referenceID}, +"playerid": ${ingame.actorGamer.referenceID}, "creation_t": ${world.creationTime}, "lastplay_t": ${world.lastPlayTime}, "playtime_t": ${world.totalPlayTime},