loading player from json file

This commit is contained in:
minjaesong
2021-08-28 16:31:06 +09:00
parent 29cccea19b
commit b84a0a770b
31 changed files with 308 additions and 145 deletions

View File

@@ -77,6 +77,11 @@ class Cvec {
set(color) set(color)
} }
operator fun component1() = r
operator fun component2() = g
operator fun component3() = b
operator fun component4() = a
/** /**
* Get RGBA Element using index, of which: * Get RGBA Element using index, of which:
* - 0: R * - 0: R

View File

@@ -18,6 +18,16 @@ interface HasAssembledSprite {
// FIXME sometimes the animmation is invisible (row and nFrames mismatch -- row is changed to 1 but it's drawing 3rd frame?) // FIXME sometimes the animmation is invisible (row and nFrames mismatch -- row is changed to 1 but it's drawing 3rd frame?)
/**
* Example usage:
* ```
* this.animDescPath = "..."
* this.animDescPathGlow = "..."
* this.sprite = SpriteAnimation(actor)
* this.spriteGlow = SpriteAnimation(actor)
* reassembleSprite(this.sprite, this.spriteGlow)
* ```
*/
fun reassembleSprite(sprite: SpriteAnimation, spriteGlow: SpriteAnimation? = null) { fun reassembleSprite(sprite: SpriteAnimation, spriteGlow: SpriteAnimation? = null) {
_rebuild(ADProperties(Gdx.files.internal(animDescPath).read()), sprite) _rebuild(ADProperties(Gdx.files.internal(animDescPath).read()), sprite)
if (animDescPathGlow != null && spriteGlow != null) if (animDescPathGlow != null && spriteGlow != null)

View File

@@ -50,7 +50,6 @@ import static net.torvald.terrarum.TerrarumKt.printStackTrace;
public class AppLoader implements ApplicationListener { public class AppLoader implements ApplicationListener {
public static final String GAME_NAME = TerrarumAppConfiguration.GAME_NAME; public static final String GAME_NAME = TerrarumAppConfiguration.GAME_NAME;
public static final String COPYRIGHT_DATE_NAME = TerrarumAppConfiguration.COPYRIGHT_DATE_NAME;
// is this jvm good? // is this jvm good?
static { static {

View File

@@ -225,9 +225,16 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
open fun removeActor(actor: Actor?) { open fun removeActor(actor: Actor?) {
if (actor == null) return if (actor == null) return
val indexToDelete = actorContainerActive.searchFor(actor.referenceID) { it.referenceID } forceRemoveActor(actor)
if (indexToDelete != null) { }
actorContainerActive.remove(indexToDelete)
open fun forceRemoveActor(actor: Actor) {
arrayOf(actorContainerActive, actorContainerInactive).forEach { actorContainer ->
val indexToDelete = actorContainer.searchFor(actor.referenceID) { it.referenceID }
if (indexToDelete != null) {
actor.dispose()
actorContainer.remove(indexToDelete)
}
} }
} }

View File

@@ -5,7 +5,15 @@ import org.dyn4j.geometry.Vector2
/** /**
* Created by minjaesong on 2016-01-15. * Created by minjaesong on 2016-01-15.
*/ */
data class Point2d(var x: Double, var y: Double) : Cloneable { class Point2d() : Cloneable {
var x: Double = 0.0
var y: Double = 0.0
constructor(x: Double, y: Double) : this() {
this.x = x
this.y = y
}
override fun toString(): String { override fun toString(): String {
return "($x, $y)" return "($x, $y)"
@@ -66,9 +74,21 @@ data class Point2d(var x: Double, var y: Double) : Cloneable {
return this return this
} }
operator fun component1() = x
operator fun component2() = y
} }
data class Point2i(var x: Int, var y: Int) { class Point2i() {
var x: Int = 0
var y: Int = 0
constructor(x: Int, y: Int) : this() {
this.x = x
this.y = y
}
fun set(x: Int, y: Int) { fun set(x: Int, y: Int) {
this.x = x this.x = x
this.y = y this.y = y
@@ -94,4 +114,7 @@ data class Point2i(var x: Int, var y: Int) {
return this return this
} }
operator fun component1() = x
operator fun component2() = y
} }

View File

@@ -494,6 +494,7 @@ val ccG = GameFontBase.toColorCode(0xF8F8)
val ccV = GameFontBase.toColorCode(0xF080) val ccV = GameFontBase.toColorCode(0xF080)
val ccX = GameFontBase.toColorCode(0xF853) val ccX = GameFontBase.toColorCode(0xF853)
val ccK = GameFontBase.toColorCode(0xF888) val ccK = GameFontBase.toColorCode(0xF888)
val ccE = GameFontBase.toColorCode(0xFBBB)
typealias Second = Float typealias Second = Float

View File

@@ -1,5 +1,7 @@
package net.torvald.terrarum package net.torvald.terrarum
import net.torvald.terrarum.langpack.Lang
/** /**
* You directly modify the source code to tune the engine to suit your needs. * You directly modify the source code to tune the engine to suit your needs.
* *
@@ -11,6 +13,7 @@ object TerrarumAppConfiguration {
////////////////////////////////////// //////////////////////////////////////
const val GAME_NAME = "Terrarum" const val GAME_NAME = "Terrarum"
const val COPYRIGHT_DATE_NAME = "Copyright 2013-2021 CuriousTorvald (minjaesong)" const val COPYRIGHT_DATE_NAME = "Copyright 2013-2021 CuriousTorvald (minjaesong)"
val COPYRIGHT_LICENSE: String; get() = Lang["COPYRIGHT_GNU_GPL_3"]
/** /**
* *

View File

@@ -257,8 +257,8 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
batch.color = Color.LIGHT_GRAY batch.color = Color.LIGHT_GRAY
val COPYTING = arrayOf( val COPYTING = arrayOf(
AppLoader.COPYRIGHT_DATE_NAME, TerrarumAppConfiguration.COPYRIGHT_DATE_NAME,
Lang["COPYRIGHT_GNU_GPL_3"] TerrarumAppConfiguration.COPYRIGHT_LICENSE
) )
COPYTING.forEachIndexed { index, s -> COPYTING.forEachIndexed { index, s ->

View File

@@ -8,6 +8,7 @@ import java.util.*
*/ */
object CommandDict { object CommandDict {
// todo replace with reflection?
internal val dict: HashMap<String, ConsoleCommand> = hashMapOf( internal val dict: HashMap<String, ConsoleCommand> = hashMapOf(
"echo" to Echo, "echo" to Echo,
"error" to EchoError, "error" to EchoError,
@@ -63,6 +64,7 @@ object CommandDict {
/* !! */"exportworld" to ExportWorld, /* !! */"exportworld" to ExportWorld,
/* !! */"exportactor" to ExportActor, /* !! */"exportactor" to ExportActor,
/* !! */"importworld" to ImportWorld, /* !! */"importworld" to ImportWorld,
/* !! */"importactor" to ImportActor,
/* !! */"exportfborgb" to ExportRendererFboRGB, /* !! */"exportfborgb" to ExportRendererFboRGB,
/* !! */"printworld" to PrintWorld /* !! */"printworld" to PrintWorld
) )

View File

@@ -12,7 +12,20 @@ typealias ActorID = Int
* *
* Created by minjaesong on 2015-12-31. * Created by minjaesong on 2015-12-31.
*/ */
abstract class Actor(var renderOrder: RenderOrder, id: ActorID?) : Comparable<Actor>, Runnable { abstract class Actor() : Comparable<Actor>, Runnable {
/**
* Valid RefID is equal to or greater than 16777216.
* @return Reference ID. (16777216-0x7FFF_FFFF)
*/
open var referenceID: ActorID = 0 // in old time this was nullable without initialiser. If you're going to revert to that, add the reason why this should be nullable.
var renderOrder = RenderOrder.MIDDLE
// needs zero-arg constructor for serialiser to work
constructor(renderOrder: RenderOrder, id: ActorID?) : this() {
referenceID = id ?: Terrarum.generateUniqueReferenceID(renderOrder)
}
enum class RenderOrder { enum class RenderOrder {
BEHIND, // tapestries, some particles (obstructed by terrain) BEHIND, // tapestries, some particles (obstructed by terrain)
@@ -32,11 +45,6 @@ abstract class Actor(var renderOrder: RenderOrder, id: ActorID?) : Comparable<Ac
abstract fun update(delta: Float) abstract fun update(delta: Float)
/**
* Valid RefID is equal to or greater than 16777216.
* @return Reference ID. (16777216-0x7FFF_FFFF)
*/
open var referenceID: ActorID = id ?: Terrarum.generateUniqueReferenceID(renderOrder) // in old time this was nullable without initialiser. If you're going to revert to that, add the reason why this should be nullable.
var actorValue = ActorValue(this) // FIXME cyclic reference on GSON var actorValue = ActorValue(this) // FIXME cyclic reference on GSON
@Volatile var flagDespawn = false @Volatile var flagDespawn = false

View File

@@ -5,17 +5,23 @@ import net.torvald.terrarum.KVHashMap
/** /**
* Created by minjaesong on 2017-04-28. * Created by minjaesong on 2017-04-28.
*/ */
class ActorValue(@Transient val actor: Actor) : KVHashMap() { class ActorValue : KVHashMap {
private constructor(actor: Actor, newMap: HashMap<String, Any>): this(actor) { @Transient lateinit var actor: Actor
internal set
private constructor()
constructor(actor: Actor) : this() {
this.actor = actor
}
private constructor(actor: Actor, newMap: HashMap<String, Any>): this() {
this.actor = actor
hashMap = newMap hashMap = newMap
} }
override fun set(key: String, value: Any) { override fun set(key: String, value: Any) {
/*if (key == AVKey.__PLAYER_QUICKSLOTSEL) {
printStackTrace(this)
}*/
super.set(key, value) super.set(key, value)
actor.onActorValueChange(key, value) // fire the event handler actor.onActorValueChange(key, value) // fire the event handler
} }

View File

@@ -36,9 +36,15 @@ import kotlin.math.roundToInt
* *
* Created by minjaesong on 2016-01-13. * Created by minjaesong on 2016-01-13.
*/ */
open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties, id: ActorID? = null) : open class ActorWithBody() : Actor() {
Actor(renderOrder, id) {
var physProp = PhysProperties.HUMANOID_DEFAULT
constructor(renderOrder: RenderOrder, physProp: PhysProperties, id: ActorID? = null) : this() {
this.physProp = physProp
this.renderOrder = renderOrder
id?.let { this.referenceID = id }
}
@Transient val COLLISION_TEST_MODE = false @Transient val COLLISION_TEST_MODE = false

View File

@@ -11,18 +11,15 @@ import org.dyn4j.geometry.Vector2
* *
* Created by minjaesong on 2016-01-15. * Created by minjaesong on 2016-01-15.
*/ */
class Hitbox (x1: Double, y1: Double, width: Double, height: Double, var suppressWarning: Boolean = true) { class Hitbox {
@Volatile var hitboxStart: Point2d var suppressWarning = true
private set
inline val hitboxEnd: Point2d private constructor()
get() = Point2d(hitboxStart.x + width, hitboxStart.y + height)
var width: Double = 0.0 constructor(x1: Double, y1: Double, width: Double, height: Double, suppressWarning: Boolean = true) : this() {
private set this.suppressWarning = suppressWarning
var height: Double = 0.0
private set
init {
hitboxStart = Point2d(x1, y1) hitboxStart = Point2d(x1, y1)
this.width = width this.width = width
this.height = height this.height = height
@@ -33,6 +30,15 @@ class Hitbox (x1: Double, y1: Double, width: Double, height: Double, var suppres
} }
} }
@Volatile var hitboxStart: Point2d = Point2d(-1.0, -1.0)
private set
inline val hitboxEnd: Point2d
get() = Point2d(hitboxStart.x + width, hitboxStart.y + height)
var width: Double = 0.0
private set
var height: Double = 0.0
private set
val startX: Double val startX: Double
get() = hitboxStart.x get() = hitboxStart.x

View File

@@ -28,11 +28,11 @@ import kotlin.math.absoluteValue
typealias BlockAddress = Long typealias BlockAddress = Long
class GameWorld : Disposable { class GameWorld() : Disposable {
var worldName: String = "New World" var worldName: String = "New World"
/** Index start at 1 */ /** Index start at 1 */
var worldIndex: Int var worldIndex: Int = 1234567890
set(value) { set(value) {
if (value <= 0) if (value <= 0)
throw Error("World index start at 1; you've entered $value") throw Error("World index start at 1; you've entered $value")
@@ -42,14 +42,14 @@ class GameWorld : Disposable {
field = value field = value
} }
val width: Int var width: Int = 999; private set
val height: Int var height: Int = 999; private set
var creationTime: Long var creationTime: Long = AppLoader.getTIME_T()
internal set internal set
var lastPlayTime: Long var lastPlayTime: Long = AppLoader.getTIME_T()
internal set // there's a case of save-and-continue-playing internal set // there's a case of save-and-continue-playing
var totalPlayTime: Int var totalPlayTime: Int = 0
internal set internal set
/** Used to calculate play time */ /** Used to calculate play time */
@@ -63,9 +63,9 @@ class GameWorld : Disposable {
//val layerFluidPressure: MapLayerHalfFloat // (milibar - 1000) //val layerFluidPressure: MapLayerHalfFloat // (milibar - 1000)
/** Tilewise spawn point */ /** Tilewise spawn point */
var spawnX: Int var spawnX: Int = 0
/** Tilewise spawn point */ /** Tilewise spawn point */
var spawnY: Int var spawnY: Int = 0
val wallDamages = HashArray<Float>() val wallDamages = HashArray<Float>()
val terrainDamages = HashArray<Float>() val terrainDamages = HashArray<Float>()
@@ -119,7 +119,7 @@ class GameWorld : Disposable {
/** /**
* Create new world * Create new world
*/ */
constructor(worldIndex: Int, width: Int, height: Int, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) { constructor(worldIndex: Int, width: Int, height: Int, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int): this() {
if (width <= 0 || height <= 0) throw IllegalArgumentException("Non-positive width/height: ($width, $height)") if (width <= 0 || height <= 0) throw IllegalArgumentException("Non-positive width/height: ($width, $height)")
this.worldIndex = worldIndex this.worldIndex = worldIndex
@@ -146,18 +146,6 @@ class GameWorld : Disposable {
postLoad() postLoad()
} }
constructor() {
worldIndex = 1234567890
width = 999
height = 999
val time = AppLoader.getTIME_T()
creationTime = time
lastPlayTime = time
totalPlayTime = 0
spawnX = 0
spawnY = 0
}
fun postLoad() { fun postLoad() {
AppLoader.tileMaker.tags.forEach { AppLoader.tileMaker.tags.forEach {
printdbg(this, "tileNumber ${it.value.tileNumber} <-> tileName ${it.key}") printdbg(this, "tileNumber ${it.value.tileNumber} <-> tileName ${it.key}")

View File

@@ -32,7 +32,6 @@ import net.torvald.terrarum.gameworld.WorldSimulator
import net.torvald.terrarum.modulebasegame.gameworld.GameEconomy import net.torvald.terrarum.modulebasegame.gameworld.GameEconomy
import net.torvald.terrarum.modulebasegame.ui.* import net.torvald.terrarum.modulebasegame.ui.*
import net.torvald.terrarum.weather.WeatherMixer import net.torvald.terrarum.weather.WeatherMixer
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldgenParams import net.torvald.terrarum.modulebasegame.worldgenerator.WorldgenParams
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
@@ -40,7 +39,6 @@ import net.torvald.terrarum.worlddrawer.BlocksDrawer
import net.torvald.terrarum.worlddrawer.FeaturesDrawer import net.torvald.terrarum.worlddrawer.FeaturesDrawer
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.util.CircularArray import net.torvald.util.CircularArray
import net.torvald.util.SortedArrayList
import java.util.* import java.util.*
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
import kotlin.math.roundToInt import kotlin.math.roundToInt
@@ -313,8 +311,8 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
/** Load rest of the game with GL context */ /** Load rest of the game with GL context */
fun postInit() { fun postInit() {
//setTheRealGamerFirstTime(PlayerBuilderSigrid()) //setTheRealGamerFirstTime(PlayerBuilderSigrid())
// setTheRealGamerFirstTime(PlayerBuilderTestSubject1()) setTheRealGamerFirstTime(PlayerBuilderTestSubject1())
setTheRealGamerFirstTime(PlayerBuilderWerebeastTest()) // setTheRealGamerFirstTime(PlayerBuilderWerebeastTest())
@@ -850,9 +848,9 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
if (it is Pocketed) { if (it is Pocketed) {
it.inventory.forEach { inventoryEntry -> it.inventory.forEach { inventoryEntry ->
ItemCodex[inventoryEntry.item]!!.effectWhileInPocket(delta) ItemCodex[inventoryEntry.itm]!!.effectWhileInPocket(delta)
if (it.equipped(inventoryEntry.item)) { if (it.equipped(inventoryEntry.itm)) {
ItemCodex[inventoryEntry.item]!!.effectWhenEquipped(delta) ItemCodex[inventoryEntry.itm]!!.effectWhenEquipped(delta)
} }
} }
} }
@@ -920,17 +918,25 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
if (actor.referenceID == theRealGamer.referenceID || actor.referenceID == 0x51621D) // do not delete this magic if (actor.referenceID == theRealGamer.referenceID || actor.referenceID == 0x51621D) // do not delete this magic
throw RuntimeException("Attempted to remove player.") throw RuntimeException("Attempted to remove player.")
val indexToDelete = actorContainerActive.searchForIndex(actor.referenceID) { it.referenceID }
if (indexToDelete != null) {
printdbg(this, "Removing actor $actor")
printStackTrace(this)
actorContainerActive.removeAt(indexToDelete) forceRemoveActor(actor)
}
// indexToDelete >= 0 means that the actor certainly exists in the game override fun forceRemoveActor(actor: Actor) {
// which means we don't need to check if i >= 0 again arrayOf(actorContainerActive, actorContainerInactive).forEach { actorContainer ->
if (actor is ActorWithBody) { val indexToDelete = actorContainer.searchForIndex(actor.referenceID) { it.referenceID }
actorToRenderQueue(actor).remove(actor) if (indexToDelete != null) {
printdbg(this, "Removing actor $actor")
printStackTrace(this)
actor.dispose()
actorContainer.removeAt(indexToDelete)
// indexToDelete >= 0 means that the actor certainly exists in the game
// which means we don't need to check if i >= 0 again
if (actor is ActorWithBody) {
actorToRenderQueue(actor).remove(actor)
}
} }
} }
} }
@@ -973,10 +979,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
} }
actorContainerActive.add(actor) actorContainerActive.add(actor)
if (actor is ActorWithBody) actorToRenderQueue(actor).add(actor)
if (actor is ActorWithBody) {
actorToRenderQueue(actor).add(actor)
}
} }
} }

View File

@@ -6,6 +6,7 @@ import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.ConsoleCommand import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.serialise.WriteActor import net.torvald.terrarum.serialise.WriteActor
import net.torvald.terrarum.serialise.WriteMeta import net.torvald.terrarum.serialise.WriteMeta
import net.torvald.terrarum.serialise.WriteWorld import net.torvald.terrarum.serialise.WriteWorld
@@ -40,10 +41,10 @@ object ExportWorld : ConsoleCommand {
if (args.size == 2) { if (args.size == 2) {
try { try {
val str = WriteWorld(Terrarum.ingame!! as TerrarumIngame).invoke() val str = WriteWorld(Terrarum.ingame!! as TerrarumIngame).invoke()
val writer = java.io.FileWriter(AppLoader.defaultDir + "/Exports/${args[1]}", false) val writer = java.io.FileWriter(AppLoader.defaultDir + "/Exports/${args[1]}.json", false)
writer.write(str) writer.write(str)
writer.close() writer.close()
Echo("Exportworld: exported to ${args[1]}") Echo("Exportworld: exported to ${args[1]}.json")
} }
catch (e: IOException) { catch (e: IOException) {
Echo("Exportworld: IOException raised.") Echo("Exportworld: IOException raised.")
@@ -56,7 +57,7 @@ object ExportWorld : ConsoleCommand {
} }
override fun printUsage() { override fun printUsage() {
Echo("Usage: Exportworld filename.json") Echo("Usage: Exportworld filename-without-extension")
} }
} }
@@ -67,7 +68,7 @@ object ExportActor : ConsoleCommand {
val player = (Terrarum.ingame!! as TerrarumIngame).actorNowPlaying val player = (Terrarum.ingame!! as TerrarumIngame).actorNowPlaying
if (player == null) return if (player == null) return
val str = WriteActor(player) val str = WriteActor(player as IngamePlayer)
val writer = java.io.FileWriter(AppLoader.defaultDir + "/Exports/${args[1]}.json", false) val writer = java.io.FileWriter(AppLoader.defaultDir + "/Exports/${args[1]}.json", false)
writer.write(str) writer.write(str)
writer.close() writer.close()

View File

@@ -5,6 +5,7 @@ import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.ConsoleCommand import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.serialise.ReadActor
import net.torvald.terrarum.serialise.ReadWorld import net.torvald.terrarum.serialise.ReadWorld
import net.torvald.terrarum.serialise.WriteMeta import net.torvald.terrarum.serialise.WriteMeta
import java.io.IOException import java.io.IOException
@@ -16,9 +17,9 @@ object ImportWorld : ConsoleCommand {
override fun execute(args: Array<String>) { override fun execute(args: Array<String>) {
if (args.size == 2) { if (args.size == 2) {
try { try {
val reader = java.io.FileReader(AppLoader.defaultDir + "/Exports/${args[1]}") val reader = java.io.FileReader(AppLoader.defaultDir + "/Exports/${args[1]}.json")
ReadWorld(Terrarum.ingame!! as TerrarumIngame).invoke(reader) ReadWorld(Terrarum.ingame!! as TerrarumIngame).invoke(reader)
Echo("Importworld: imported a world from ${args[1]}") Echo("Importworld: imported a world from ${args[1]}.json")
} }
catch (e: IOException) { catch (e: IOException) {
Echo("Importworld: IOException raised.") Echo("Importworld: IOException raised.")
@@ -31,6 +32,29 @@ object ImportWorld : ConsoleCommand {
} }
override fun printUsage() { override fun printUsage() {
Echo("Usage: Importworld filename.json") Echo("Usage: Importworld filename-without-extension")
}
}
object ImportActor : ConsoleCommand {
override fun execute(args: Array<String>) {
if (args.size == 2) {
try {
val reader = java.io.FileReader(AppLoader.defaultDir + "/Exports/${args[1]}.json")
ReadActor(Terrarum.ingame!! as TerrarumIngame).invoke(reader)
Echo("Importactor: imported an actor from ${args[1]}.json")
}
catch (e: IOException) {
Echo("Importactor: IOException raised.")
e.printStackTrace()
}
}
else {
printUsage()
}
}
override fun printUsage() {
Echo("Usage: Importactor filename-without-extension")
} }
} }

View File

@@ -9,11 +9,9 @@ import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.gameactors.* import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.gameactors.faction.Faction import net.torvald.terrarum.gameactors.faction.Faction
import net.torvald.terrarum.gameitem.GameItem import net.torvald.terrarum.gameitem.GameItem
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.itemproperties.Material import net.torvald.terrarum.itemproperties.Material
import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.worlddrawer.LightmapRenderer
import org.dyn4j.geometry.Vector2 import org.dyn4j.geometry.Vector2
import java.util.* import java.util.*
@@ -28,12 +26,13 @@ import java.util.*
* *
* Created by minjaesong on 2016-10-24. * Created by minjaesong on 2016-10-24.
*/ */
open class ActorHumanoid( open class ActorHumanoid() : ActorWithBody(), Controllable, Pocketed, Factionable, Luminous, LandHolder, HistoricalFigure {
birth: Long,
death: Long? = null,
physProp: PhysProperties = PhysProperties.HUMANOID_DEFAULT
) : ActorWithBody(RenderOrder.MIDDLE, physProp = physProp), Controllable, Pocketed, Factionable, Luminous, LandHolder, HistoricalFigure {
constructor(birth: Long, death: Long? = null, physProp: PhysProperties = PhysProperties.HUMANOID_DEFAULT) : this() {
actorValue[AVKey.__HISTORICAL_BORNTIME] = birth
death?.let { actorValue[AVKey.__HISTORICAL_DEADTIME] = death }
this.physProp = physProp
}
var vehicleRiding: Controllable? = null // usually player only var vehicleRiding: Controllable? = null // usually player only
@@ -176,11 +175,6 @@ open class ActorHumanoid(
override val material = Material() override val material = Material()
} }
init {
actorValue[AVKey.__HISTORICAL_BORNTIME] = birth
death?.let { actorValue[AVKey.__HISTORICAL_DEADTIME] = death }
}
override fun update(delta: Float) { override fun update(delta: Float) {
super.update(delta) super.update(delta)
@@ -217,11 +211,11 @@ open class ActorHumanoid(
// update inventory items // update inventory items
inventory.forEach { inventory.forEach {
if (!inventory.itemEquipped.contains(it.item)) { // unequipped if (!inventory.itemEquipped.contains(it.itm)) { // unequipped
ItemCodex[it.item]!!.effectWhileInPocket(delta) ItemCodex[it.itm]!!.effectWhileInPocket(delta)
} }
else { // equipped else { // equipped
ItemCodex[it.item]!!.effectWhenEquipped(delta) ItemCodex[it.itm]!!.effectWhenEquipped(delta)
} }
} }
} }
@@ -640,7 +634,7 @@ open class ActorHumanoid(
// make quickslot work // make quickslot work
if (key == AVKey.__PLAYER_QUICKSLOTSEL && value != null) { if (key == AVKey.__PLAYER_QUICKSLOTSEL && value != null) {
// ONLY FOR HAND_GRIPs!! // ONLY FOR HAND_GRIPs!!
val quickBarItem = ItemCodex[inventory.getQuickslot(actorValue.getAsInt(key)!!)?.item] val quickBarItem = ItemCodex[inventory.getQuickslot(actorValue.getAsInt(key)!!)?.itm]
if (quickBarItem != null && quickBarItem.equipPosition == GameItem.EquipPosition.HAND_GRIP) { if (quickBarItem != null && quickBarItem.equipPosition == GameItem.EquipPosition.HAND_GRIP) {
equipItem(quickBarItem) equipItem(quickBarItem)

View File

@@ -1,29 +1,30 @@
package net.torvald.terrarum.modulebasegame.gameactors package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.terrarum.AppLoader import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameitem.GameItem import net.torvald.terrarum.gameitem.GameItem
import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.gameitem.ItemID import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.lock
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.ui.UIQuickslotBar import net.torvald.terrarum.modulebasegame.ui.UIQuickslotBar
import java.math.BigInteger
import java.util.*
import java.util.concurrent.locks.ReentrantLock
/** /**
* Created by minjaesong on 2016-03-15. * Created by minjaesong on 2016-03-15.
*/ */
class ActorInventory(@Transient val actor: Pocketed, maxCapacity: Int, capacityMode: Int): class ActorInventory() : FixtureInventory() {
FixtureInventory(maxCapacity, capacityMode) {
// FIXME unless absolutely necessary, don't store full item object; only store its dynamicID // FIXME unless absolutely necessary, don't store full item object; only store its dynamicID
@Transient lateinit var actor: Pocketed
internal set
constructor(actor: Pocketed, maxCapacity: Int, capacityMode: Int) : this() {
this.actor = actor
this.maxCapacity = maxCapacity
this.capacityMode = capacityMode
}
/** /**
* List of all equipped items (tools, armours, rings, necklaces, etc.) * List of all equipped items (tools, armours, rings, necklaces, etc.)
*/ */
@@ -38,7 +39,7 @@ class ActorInventory(@Transient val actor: Pocketed, maxCapacity: Int, capacityM
override fun remove(item: GameItem, count: Int) { override fun remove(item: GameItem, count: Int) {
super.remove(item, count) { existingItem -> super.remove(item, count) { existingItem ->
// unequip, if applicable // unequip, if applicable
actor.unequipItem(existingItem.item) actor.unequipItem(existingItem.itm)
// also unequip on the quickslot // also unequip on the quickslot
actor.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)?.let { actor.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)?.let {
setQuickBar(it, null) setQuickBar(it, null)

View File

@@ -13,8 +13,16 @@ import java.util.concurrent.locks.ReentrantLock
* Created by minjaesong on 2021-03-16. * Created by minjaesong on 2021-03-16.
*/ */
open class FixtureInventory(var maxCapacity: Int, var capacityMode: Int) { open class FixtureInventory() {
var maxCapacity = 100
var capacityMode = CAPACITY_MODE_COUNT
constructor(maxCapacity: Int, capacityMode: Int) : this() {
this.maxCapacity = maxCapacity
this.capacityMode = capacityMode
}
companion object { companion object {
val CAPACITY_MODE_NO_ENCUMBER = 0 val CAPACITY_MODE_NO_ENCUMBER = 0
val CAPACITY_MODE_COUNT = 1 val CAPACITY_MODE_COUNT = 1
@@ -60,7 +68,7 @@ open class FixtureInventory(var maxCapacity: Int, var capacityMode: Int) {
// if the item already exists // if the item already exists
if (existingItem != null) { if (existingItem != null) {
// increment count // increment count
existingItem.amount += count existingItem.qty += count
} }
// new item // new item
else { else {
@@ -90,14 +98,14 @@ open class FixtureInventory(var maxCapacity: Int, var capacityMode: Int) {
val existingItem = invSearchByDynamicID(item.dynamicID) val existingItem = invSearchByDynamicID(item.dynamicID)
if (existingItem != null) { // if the item already exists if (existingItem != null) { // if the item already exists
val newCount = existingItem.amount - count val newCount = existingItem.qty - count
if (newCount < 0) { if (newCount < 0) {
throw Error("Tried to remove $count of $item, but the inventory only contains ${existingItem.amount} of them.") throw Error("Tried to remove $count of $item, but the inventory only contains ${existingItem.qty} of them.")
} }
else if (newCount > 0) { else if (newCount > 0) {
// decrement count // decrement count
existingItem.amount = newCount existingItem.qty = newCount
} }
else { else {
// depleted item; remove entry from inventory // depleted item; remove entry from inventory
@@ -128,12 +136,12 @@ open class FixtureInventory(var maxCapacity: Int, var capacityMode: Int) {
else else
getTotalCount().toDouble() getTotalCount().toDouble()
fun getTotalWeight(): Double = itemList.map { ItemCodex[it.item]!!.mass * it.amount }.sum() fun getTotalWeight(): Double = itemList.map { ItemCodex[it.itm]!!.mass * it.qty }.sum()
/** /**
* Real amount * Real amount
*/ */
fun getTotalCount(): Int = itemList.map { it.amount }.sum() fun getTotalCount(): Int = itemList.map { it.qty }.sum()
/** /**
* Unique amount, multiple items are calculated as one * Unique amount, multiple items are calculated as one
@@ -182,7 +190,7 @@ open class FixtureInventory(var maxCapacity: Int, var capacityMode: Int) {
ReentrantLock().lock { ReentrantLock().lock {
var j = arr.lastIndex - 1 var j = arr.lastIndex - 1
val x = arr.last() val x = arr.last()
while (j >= 0 && arr[j].item > x.item) { while (j >= 0 && arr[j].itm > x.itm) {
arr[j + 1] = arr[j] arr[j + 1] = arr[j]
j -= 1 j -= 1
} }
@@ -200,9 +208,9 @@ open class FixtureInventory(var maxCapacity: Int, var capacityMode: Int) {
val mid = (low + high).ushr(1) // safe from overflows val mid = (low + high).ushr(1) // safe from overflows
val midVal = if (searchMode == STATIC_ID) val midVal = if (searchMode == STATIC_ID)
ItemCodex[this[mid].item]!!.originalID ItemCodex[this[mid].itm]!!.originalID
else else
ItemCodex[this[mid].item]!!.dynamicID ItemCodex[this[mid].itm]!!.dynamicID
if (ID > midVal) if (ID > midVal)
low = mid + 1 low = mid + 1
@@ -215,4 +223,19 @@ open class FixtureInventory(var maxCapacity: Int, var capacityMode: Int) {
} }
} }
data class InventoryPair(val item: ItemID, var amount: Int) class InventoryPair {
var itm: ItemID = ""; private set
var qty: Int = 0
private constructor()
constructor(item: ItemID, quantity: Int) : this() {
itm = item
qty = quantity
}
operator fun component1() = itm
operator fun component2() = qty
}

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.spriteanimation.HasAssembledSprite import net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.AVKey
/** /**
@@ -10,11 +11,17 @@ import net.torvald.terrarum.Terrarum
* Created by minjaesong on 2015-12-31. * Created by minjaesong on 2015-12-31.
*/ */
class IngamePlayer( class IngamePlayer() : ActorHumanoid(), HasAssembledSprite {
override var animDescPath: String,
override var animDescPathGlow: String? = null, override var animDescPath = "invalid"
born: Long override var animDescPathGlow: String? = null
) : ActorHumanoid(born), HasAssembledSprite {
constructor(animDescPath: String, animDescPathGlow: String?, born: Long) : this() {
this.animDescPath = animDescPath
this.animDescPathGlow = animDescPathGlow
actorValue[AVKey.__HISTORICAL_BORNTIME] = born
}
/** /**
* Creates new Player instance with empty elements (sprites, actorvalue, etc.). * Creates new Player instance with empty elements (sprites, actorvalue, etc.).

View File

@@ -16,9 +16,9 @@ class ThreadActorUpdate(val startIndex: Int, val endIndex: Int) : Callable<Unit>
if (it is Pocketed) { if (it is Pocketed) {
it.inventory.forEach { inventoryEntry -> it.inventory.forEach { inventoryEntry ->
ItemCodex[inventoryEntry.item]?.effectWhileInPocket(AppLoader.UPDATE_RATE) ItemCodex[inventoryEntry.itm]?.effectWhileInPocket(AppLoader.UPDATE_RATE)
if (it.equipped(inventoryEntry.item)) { if (it.equipped(inventoryEntry.itm)) {
ItemCodex[inventoryEntry.item]?.effectWhenEquipped(AppLoader.UPDATE_RATE) ItemCodex[inventoryEntry.itm]?.effectWhenEquipped(AppLoader.UPDATE_RATE)
} }
} }
} }

View File

@@ -19,7 +19,7 @@ object AmmoMeterProxy {
else { else {
meter.vitalGetterVal = { meter.vitalGetterVal = {
if (currentItem.stackable && currentItem.maxDurability == GameItem.DURABILITY_NA) { if (currentItem.stackable && currentItem.maxDurability == GameItem.DURABILITY_NA) {
actor.inventory.invSearchByDynamicID(currentItem.dynamicID)!!.amount.toFloat() actor.inventory.invSearchByDynamicID(currentItem.dynamicID)!!.qty.toFloat()
} }
else else
currentItem.durability currentItem.durability

View File

@@ -139,7 +139,7 @@ class UIItemInventoryEquippedView(
val itemRecord = inventory.invSearchByDynamicID(item)!! val itemRecord = inventory.invSearchByDynamicID(item)!!
itemGrid[k].item = ItemCodex[item] itemGrid[k].item = ItemCodex[item]
itemGrid[k].amount = itemRecord.amount itemGrid[k].amount = itemRecord.qty
itemGrid[k].itemImage = ItemCodex.getItemImage(item) itemGrid[k].itemImage = ItemCodex.getItemImage(item)
itemGrid[k].quickslot = null // don't need to be displayed itemGrid[k].quickslot = null // don't need to be displayed
itemGrid[k].equippedSlot = null // don't need to be displayed itemGrid[k].equippedSlot = null // don't need to be displayed

View File

@@ -120,7 +120,7 @@ class UIItemInventoryItemGrid(
inventory.setQuickBar( inventory.setQuickBar(
slot, slot,
if (currentSlotItem?.item != item.dynamicID) if (currentSlotItem?.itm != item.dynamicID)
item.dynamicID // register item.dynamicID // register
else else
null // drop registration null // drop registration
@@ -129,7 +129,7 @@ class UIItemInventoryItemGrid(
// search for duplicates in the quickbar, except mine // search for duplicates in the quickbar, except mine
// if there is, unregister the other // if there is, unregister the other
(0..9).minus(slot).forEach { (0..9).minus(slot).forEach {
if (inventory.getQuickslot(it)?.item == item.dynamicID) { if (inventory.getQuickslot(it)?.itm == item.dynamicID) {
inventory.setQuickBar(it, null) inventory.setQuickBar(it, null)
} }
} }
@@ -412,27 +412,27 @@ class UIItemInventoryItemGrid(
// filter items // filter items
inventory.forEach { inventory.forEach {
if ((filter.contains(ItemCodex[it.item]!!.inventoryCategory) || filter[0] == CAT_ALL)) if ((filter.contains(ItemCodex[it.itm]!!.inventoryCategory) || filter[0] == CAT_ALL))
inventorySortList.add(it) inventorySortList.add(it)
} }
// sort if needed // sort if needed
// test sort by name // test sort by name
inventorySortList.sortBy { ItemCodex[it.item]!!.name } inventorySortList.sortBy { ItemCodex[it.itm]!!.name }
// map sortList to item list // map sortList to item list
for (k in items.indices) { for (k in items.indices) {
// we have an item // we have an item
try { try {
val sortListItem = inventorySortList[k + itemPage * items.size] val sortListItem = inventorySortList[k + itemPage * items.size]
items[k].item = ItemCodex[sortListItem.item] items[k].item = ItemCodex[sortListItem.itm]
items[k].amount = sortListItem.amount items[k].amount = sortListItem.qty
items[k].itemImage = ItemCodex.getItemImage(sortListItem.item) items[k].itemImage = ItemCodex.getItemImage(sortListItem.itm)
// set quickslot number // set quickslot number
if (inventory is ActorInventory) { if (inventory is ActorInventory) {
for (qs in 1..UIQuickslotBar.SLOT_COUNT) { for (qs in 1..UIQuickslotBar.SLOT_COUNT) {
if (sortListItem.item == inventory.getQuickslot(qs - 1)?.item) { if (sortListItem.itm == inventory.getQuickslot(qs - 1)?.itm) {
items[k].quickslot = qs % 10 // 10 -> 0, 1..9 -> 1..9 items[k].quickslot = qs % 10 // 10 -> 0, 1..9 -> 1..9
break break
} }

View File

@@ -48,7 +48,7 @@ class UIQuickslotBar : UICanvas() {
override fun renderUI(batch: SpriteBatch, camera: Camera) { override fun renderUI(batch: SpriteBatch, camera: Camera) {
for (i in 0..SLOT_COUNT - 1) { for (i in 0..SLOT_COUNT - 1) {
val item = ItemCodex[(Terrarum.ingame!! as TerrarumIngame).actorNowPlaying?.inventory?.getQuickslot(i)?.item] val item = ItemCodex[(Terrarum.ingame!! as TerrarumIngame).actorNowPlaying?.inventory?.getQuickslot(i)?.itm]
val image = if (i == selection) val image = if (i == selection)
ItemSlotImageFactory.produceLarge(false, (i + 1) % SLOT_COUNT, item) ItemSlotImageFactory.produceLarge(false, (i + 1) % SLOT_COUNT, item)

View File

@@ -64,7 +64,7 @@ class UIQuickslotPie : UICanvas() {
override fun renderUI(batch: SpriteBatch, camera: Camera) { override fun renderUI(batch: SpriteBatch, camera: Camera) {
// draw radial thingies // draw radial thingies
for (i in 0..slotCount - 1) { for (i in 0..slotCount - 1) {
val item = ItemCodex[(Terrarum.ingame!! as TerrarumIngame).actorNowPlaying?.inventory?.getQuickslot(i)?.item] val item = ItemCodex[(Terrarum.ingame!! as TerrarumIngame).actorNowPlaying?.inventory?.getQuickslot(i)?.itm]
// set position // set position
val angle = Math.PI * 2.0 * (i.toDouble() / slotCount) + Math.PI // 180 deg monitor-wise val angle = Math.PI * 2.0 * (i.toDouble() / slotCount) + Math.PI // 180 deg monitor-wise

View File

@@ -0,0 +1,41 @@
package net.torvald.terrarum.serialise
import net.torvald.spriteanimation.HasAssembledSprite
import net.torvald.spriteanimation.SpriteAnimation
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 java.io.InputStream
import java.io.Reader
/**
* 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))
}
open fun invoke(worldDataStream: Reader) {
IngamePlayer()
postRead(Common.jsoner.fromJson(IngamePlayer::class.java, worldDataStream))
}
private fun postRead(actor: IngamePlayer) {
// 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)
// replace existing player
ingame.forceRemoveActor(ingame.actorNowPlaying!!)
ingame.addNewActor(actor)
ingame.actorNowPlaying = actor
}
}

View File

@@ -4,6 +4,7 @@ import com.badlogic.gdx.utils.Json
import com.badlogic.gdx.utils.JsonValue import com.badlogic.gdx.utils.JsonValue
import com.badlogic.gdx.utils.JsonWriter import com.badlogic.gdx.utils.JsonWriter
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64 import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64
import java.math.BigInteger import java.math.BigInteger
@@ -12,11 +13,11 @@ import java.math.BigInteger
*/ */
object WriteActor { object WriteActor {
operator fun invoke(actor: Actor): String { operator fun invoke(actor: IngamePlayer): String {
return Common.jsoner.toJson(actor) return Common.jsoner.toJson(actor)
} }
fun encodeToByteArray64(actor: Actor): ByteArray64 { fun encodeToByteArray64(actor: IngamePlayer): ByteArray64 {
val ba = ByteArray64() val ba = ByteArray64()
this.invoke(actor).toByteArray().forEach { ba.add(it) } this.invoke(actor).toByteArray().forEach { ba.add(it) }
return ba return ba

View File

@@ -4,12 +4,12 @@ import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Camera import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.AppLoader import net.torvald.EMDASH
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.*
import net.torvald.terrarum.console.Authenticator import net.torvald.terrarum.console.Authenticator
import net.torvald.terrarum.console.CommandInterpreter import net.torvald.terrarum.console.CommandInterpreter
import net.torvald.terrarum.fillRect
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarumsansbitmap.gdx.GameFontBase
import net.torvald.util.CircularArray import net.torvald.util.CircularArray
@@ -183,7 +183,8 @@ class ConsoleWindow : UICanvas() {
commandInputPool = StringBuilder() commandInputPool = StringBuilder()
if (Authenticator.b()) { if (Authenticator.b()) {
sendMessage("${AppLoader.GAME_NAME} ${AppLoader.getVERSION_STRING()}") sendMessage("$ccE${TerrarumAppConfiguration.GAME_NAME} ${AppLoader.getVERSION_STRING()} $EMDASH ${TerrarumAppConfiguration.COPYRIGHT_DATE_NAME}")
sendMessage("$ccE${TerrarumAppConfiguration.COPYRIGHT_LICENSE}")
sendMessage(Lang["DEV_MESSAGE_CONSOLE_CODEX"]) sendMessage(Lang["DEV_MESSAGE_CONSOLE_CODEX"])
} }
} }

View File

@@ -132,6 +132,9 @@ class Vector2 {
this.y = Math.sin(direction) this.y = Math.sin(direction)
} }
operator fun component1() = x
operator fun component2() = y
/** /**
* Returns a copy of this [Vector2]. * Returns a copy of this [Vector2].
* @return [Vector2] * @return [Vector2]