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.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'")

View File

@@ -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,

View File

@@ -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)

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.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
}
}

View File

@@ -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 {

View File

@@ -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},