player load ui

This commit is contained in:
minjaesong
2021-10-12 00:17:44 +09:00
parent cdd09e71a5
commit 2d359415c8
17 changed files with 212 additions and 270 deletions

View File

@@ -16,6 +16,7 @@ The main game directory is composed of following directories:
}
*if file -1025 is not there, read bodyparts from assets directory
*optionally encrypt the files other than -1
*disk name is player's name encoded in UTF-8
+ Shared
- <e.g. Disk GUID>, TEVD { * }
- <this directory can have anything>
@@ -26,6 +27,7 @@ The main game directory is composed of following directories:
[0x1_0000_0000L or (layerNumber shl 24) or chunkNumber] chunk data,
[-2] screenshot.tga.gz taken by the last player
}
*disk name is world's name encoded in UTF-8
```
(TEVD stands for Terrarum Virtual Disk spec version 3, TVDA stands for spec version 254; both have MAGIC header of `TEVd`)

View File

@@ -1,10 +1,8 @@
package net.torvald.spriteanimation
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Texture
import net.torvald.spriteassembler.ADProperties
import net.torvald.spriteassembler.AssembleSheetPixmap
import net.torvald.terrarum.tvda.DiskSkimmer
import net.torvald.terrarum.tvda.SimpleFileSystem
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
@@ -71,7 +69,7 @@ interface HasAssembledSprite {
private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) {
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
val pixmap = AssembleSheetPixmap.fromVirtualDisk(disk, ad)
val pixmap = if (disk.getEntry(-1025) != null) AssembleSheetPixmap.fromVirtualDisk(disk, ad) else AssembleSheetPixmap.fromAssetsDir(ad)
val texture = Texture(pixmap)
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
pixmap.dispose()

View File

@@ -5,6 +5,7 @@ import net.torvald.terrarum.linearSearchBy
import net.torvald.terrarum.serialise.Common
import java.io.InputStream
import java.io.Reader
import java.io.StringReader
import java.util.*
internal data class Joint(val name: String, val position: ADPropertyObject.Vector2i) {
@@ -79,30 +80,29 @@ class ADProperties {
constructor(gdxFile: FileHandle) {
fileFrom = gdxFile.path()
adlString = gdxFile.readString(Common.CHARSET.name())
javaProp.load(gdxFile.read())
continueLoad()
}
constructor(reader: Reader) {
adlString = reader.readText()
javaProp.load(reader)
continueLoad()
}
constructor(inputStream: InputStream) {
adlString = inputStream.readAllBytes().toString(Common.CHARSET)
javaProp.load(inputStream)
continueLoad()
}
private fun continueLoad() {
javaProp.load(StringReader(adlString))
// sanity check
reservedProps.forEach {
try {
javaProp[it]!!
}
catch (e: NullPointerException) {
throw IllegalArgumentException("Prop '$it' not found from ${fileFrom.ifBlank { "(path unavailable)" }}", e)
throw IllegalArgumentException("Prop '$it' not found from ${fileFrom.ifBlank { "'${adlString.substring(0, 1024)}'" }}", e)
}
}
@@ -210,7 +210,7 @@ class ADProperties {
if (it.name.isBlank())
throw IllegalArgumentException("Empty Bodypart name on BODYPARTS; try removing trailing semicolon (';')?")
else
throw IllegalArgumentException("Bodyparts definition for '${it.name}' not found from ${fileFrom.ifBlank { "(path unavailable)" }}", e)
throw IllegalArgumentException("Bodyparts definition for '${it.name}' not found from ${fileFrom.ifBlank { "'${adlString.substring(0, 1024)}'" }}", e)
}
}

View File

@@ -189,7 +189,9 @@ public class App implements ApplicationListener {
* Sorted by the lastplaytime, in reverse order (index 0 is the most recent game played)
*/
public static TreeMap<UUID, DiskSkimmer> savegameWorlds = new TreeMap<>();
public static TreeMap<UUID, String> savegameWorldsName = new TreeMap<>();
public static TreeMap<UUID, DiskSkimmer> savegamePlayers = new TreeMap<>();
public static TreeMap<UUID, String> savegamePlayersName = new TreeMap<>();
public static void updateListOfSavegames() {
AppUpdateListOfSavegames();

View File

@@ -19,6 +19,7 @@ import net.torvald.terrarum.App.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.WireCodex
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorID
import net.torvald.terrarum.gameactors.faction.FactionCodex
@@ -682,7 +683,9 @@ class Codex : KVHashMap() {
fun AppUpdateListOfSavegames() {
App.savegamePlayers.clear()
App.savegamePlayersName.clear()
App.savegameWorlds.clear()
App.savegameWorldsName.clear()
println("listing savegames...")
@@ -692,7 +695,7 @@ fun AppUpdateListOfSavegames() {
DiskSkimmer(file, Common.CHARSET, true)
}
catch (e: Throwable) {
System.err.println("Unable to load a savefile ${file.absolutePath}")
System.err.println("Unable to load a world file ${file.absolutePath}")
e.printStackTrace()
null
}
@@ -705,9 +708,33 @@ fun AppUpdateListOfSavegames() {
val json = JsonReader().parse(ByteArray64Reader(jsonFile.bytes, Common.CHARSET).readText())
val worldUUID = UUID.fromString(json.get("worldIndex")!!.asString())
App.savegameWorlds[worldUUID] = it
App.savegameWorldsName[worldUUID] = it.getDiskName(Common.CHARSET)
}
// create list of players
(File(App.playersDir).listFiles().filter { !it.isDirectory && !it.name.contains('.') }.map { file ->
try {
DiskSkimmer(file, Common.CHARSET, true)
}
catch (e: Throwable) {
System.err.println("Unable to load a player file ${file.absolutePath}")
e.printStackTrace()
null
}
}.filter { it != null }.sortedByDescending { it!!.diskFile.lastModified() } as List<DiskSkimmer>).forEach {
println(it.diskFile.absolutePath)
it.rebuild() // disk skimmer was created without initialisation, so do it now
// TODO write simple and dumb SAX parser for JSON
val jsonFile = it.getFile(-1L)!!
val json = JsonReader().parse(ByteArray64Reader(jsonFile.bytes, Common.CHARSET).readText())
val playerUUID = UUID.fromString(json.get("uuid")!!.asString())
App.savegamePlayers[playerUUID] = it
// App.savegamePlayersName[playerUUID] = it.getDiskName(Common.CHARSET)
App.savegamePlayersName[playerUUID] = json.get("actorValue")?.getChild(AVKey.NAME)?.asString() ?: ""
}
// TODO: savegamePlayers
}
/**

View File

@@ -333,13 +333,13 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
worldDisk = VDUtil.createNewDisk(
1L shl 60,
worldSavefileName,
savegameNickname,
Common.CHARSET
)
playerDisk = VDUtil.createNewDisk(
1L shl 60,
playerSavefileName,
actorGamer.actorValue.getAsString(AVKey.NAME) ?: "",
Common.CHARSET
)

View File

@@ -119,7 +119,7 @@ class IngamePlayer : ActorHumanoid {
private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) {
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
val pixmap = AssembleSheetPixmap.fromVirtualDisk(disk, ad)
val pixmap = if (disk.getEntry(-1025) != null) AssembleSheetPixmap.fromVirtualDisk(disk, ad) else AssembleSheetPixmap.fromAssetsDir(ad)
val texture = Texture(pixmap)
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
pixmap.dispose()

View File

@@ -5,9 +5,8 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.TIMES
import net.torvald.terrarum.App
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELL_COL
import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemTextButton
@@ -63,7 +62,7 @@ class GraphicsControlPanel : UICanvas() {
batch.color = Color.WHITE
Toolkit.drawBoxBorder(batch, drawX, drawY, width, height)
batch.color = CELLCOLOUR_BLACK
batch.color = CELL_COL
Toolkit.fillArea(batch, drawX, drawY, width, height)
batch.color = Color.WHITE

View File

@@ -34,6 +34,8 @@ class UIInventoryFull(
override var openCloseTime: Second = 0.0f
companion object {
val CELL_COL = Color(0x28282888)
const val INVEN_DEBUG_MODE = false
const val REQUIRED_MARGIN: Int = 138 // hard-coded value. Don't know the details. Range: [91-146]. I chose MAX-8 because cell gap is 8

View File

@@ -5,8 +5,8 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.*
import net.torvald.terrarum.gameitem.GameItem
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK_ACTIVE
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELL_COL
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.itemListHeight
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.createInvCellGenericKeyDownFun
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.createInvCellGenericTouchDownFun
@@ -43,7 +43,7 @@ class UIItemInventoryEquippedView(
lateinit var inventorySortList: Array<GameItem?>
private var rebuildList = true
val spriteViewBackCol: Color = CELLCOLOUR_BLACK
val spriteViewBackCol: Color = CELL_COL
private val equipPosIcon = CommonResourcePool.getAsTextureRegionPack("inventory_category")
private val cellToIcon = intArrayOf(0,1,2,3,4,5,6,7,6,7,6,7)
@@ -59,7 +59,7 @@ class UIItemInventoryEquippedView(
itemImage = null,
mouseoverBackCol = Color(CELLCOLOUR_BLACK_ACTIVE),
mouseoverBackBlendMode = BlendMode.SCREEN,
backCol = CELLCOLOUR_BLACK,
backCol = CELL_COL,
backBlendMode = BlendMode.NORMAL,
drawBackOnNull = true,
keyDownFun = createInvCellGenericKeyDownFun(),

View File

@@ -13,8 +13,8 @@ import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK_ACTIVE
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELL_COL
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.INVEN_DEBUG_MODE
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItem
@@ -55,7 +55,7 @@ class UIItemInventoryItemGrid(
override val width = horizontalCells * UIItemInventoryElemSimple.height + (horizontalCells - 1) * listGap
override val height = verticalCells * UIItemInventoryElemSimple.height + (verticalCells - 1) * listGap
val backColour = CELLCOLOUR_BLACK
val backColour = CELL_COL
init {
CommonResourcePool.addToLoadingList("inventory_walletnumberfont") {

View File

@@ -1,129 +0,0 @@
package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.utils.JsonValue
import net.torvald.terrarum.*
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItem
import java.util.*
/**
* Created by minjaesong on 2019-02-05.
*
* If ingamePlayer is specified, sprite of current ingamePlayer will be drawn, instead of the SaveMetaData's thumbnail.
*/
class UIItemPlayerInfoCell(
parent: UICanvas,
val saveInfo: JsonValue,
override val width: Int,
initialX: Int,
initialY: Int,
var highlightable: Boolean,
var ingamePlayer: IngamePlayer? = null
) : UIItem(parent, initialX, initialY) {
override val height = HEIGHT
companion object {
const val HEIGHT = 64
}
private val spriteAreaWidth = 56
private val spriteToNameAreaGap = 8
private val edgeGap = 8
private val backColInactive = ItemSlotImageFactory.CELLCOLOUR_BLACK
private val backColActive = ItemSlotImageFactory.CELLCOLOUR_BLACK_ACTIVE
private val textRow1 = (((height / 2) - App.fontGame.lineHeight) / 2).toFloat()
private val textRow2 = textRow1 + (height / 2)
private val creationTimeStr: String
private val modificationTimeStr: String
private val worldCountStr: String
private val worldCountStrWidth: Int
init {
val cal = Calendar.getInstance()
cal.timeInMillis = saveInfo.getLong("creation_t") * 1000
creationTimeStr = "${cal[Calendar.YEAR]}-" +
"${cal[Calendar.MONTH].toString().padStart(2,'0')}-" +
"${cal[Calendar.DATE].toString().padStart(2,'0')}"
cal.timeInMillis = saveInfo.getLong("lastplay_t") * 1000
modificationTimeStr = "${cal[Calendar.YEAR]}-" +
"${cal[Calendar.MONTH].toString().padStart(2,'0')}-" +
"${cal[Calendar.DATE].toString().padStart(2,'0')}"
worldCountStr = Lang["CONTEXT_WORLD_COUNT"] + saveInfo.get("worlds").asIntArray().size
worldCountStrWidth = App.fontGame.getWidth(worldCountStr)
}
override fun render(batch: SpriteBatch, camera: Camera) {
// background
if (highlightable && mouseUp) {
batch.color = backColActive
blendScreen(batch)
}
else {
batch.color = backColInactive
blendNormal(batch)
}
batch.fillRect(posX.toFloat(), posY.toFloat(), width.toFloat(), height.toFloat())
blendNormal(batch)
/*batch.color = SPRITE_DRAW_COL
// character sprite image
if (ingamePlayer != null) {
val spriteImage = ingamePlayer?.sprite?.textureRegion?.get(0,0)
batch.draw(spriteImage,
((spriteImage?.regionWidth ?: 2) - spriteAreaWidth).div(2).toFloat(),
((spriteImage?.regionHeight ?: 2) - height).div(2).toFloat()
)
}
else {
val spriteImage = saveInfo.thumbnail
batch.draw(spriteImage,
(spriteImage.width - spriteAreaWidth).div(2).toFloat(),
(spriteImage.height - height).div(2).toFloat()
)
}
// texts //
// name
batch.color = Color.WHITE
AppLoader.fontGame.draw(batch, saveInfo.playerName, spriteAreaWidth + spriteToNameAreaGap.toFloat(), textRow1)
// creation and modification time
AppLoader.fontGame.draw(batch, "$creationTimeStr/$modificationTimeStr", spriteAreaWidth + spriteToNameAreaGap.toFloat(), textRow2)
// world count
AppLoader.fontGame.draw(batch, worldCountStr, width - (edgeGap + worldCountStrWidth).toFloat(), textRow1)
// wallet
val walletStr = "¤ " + (ingamePlayer?.inventory?.wallet ?: saveInfo.playerWallet)
val walletStrWidth = AppLoader.fontGame.getWidth(walletStr)
AppLoader.fontGame.draw(batch, walletStr, width - (edgeGap + walletStrWidth).toFloat(), textRow2)
*/
}
override fun update(delta: Float) {
super.update(delta)
oldPosX = posX
oldPosY = posY
}
override fun dispose() {
}
}

View File

@@ -1,32 +0,0 @@
package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItem
import java.io.File
/**
* @param savefile TEVd file
*
* Created by minjaesong on 2018-09-15.
*/
class UIItemSavegameInfoCell(
parent: UICanvas,
savefile: File,
override val width: Int,
initialX: Int,
initialY: Int
) : UIItem(parent, initialX, initialY) {
override val height: Int = App.fontGame.lineHeight.toInt() * 2
override fun render(batch: SpriteBatch, camera: Camera) {
}
override fun dispose() {
}
}

View File

@@ -8,12 +8,18 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import com.badlogic.gdx.utils.JsonReader
import com.jme3.math.FastMath
import net.torvald.EMDASH
import net.torvald.getKeycapConsole
import net.torvald.getKeycapPC
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.spriteassembler.ADProperties
import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELL_COL
import net.torvald.terrarum.serialise.Common
import net.torvald.terrarum.serialise.ReadPlayer
import net.torvald.terrarum.tvda.ByteArray64InputStream
import net.torvald.terrarum.tvda.ByteArray64Reader
import net.torvald.terrarum.tvda.DiskSkimmer
@@ -97,6 +103,15 @@ class UILoadDemoSavefiles : UICanvas() {
private var showSpinner = false
// used by UIItem*Cells
internal var playerDisk: DiskSkimmer? = null
internal var worldDisk: DiskSkimmer? = null
private val worldCells = ArrayList<UIItemWorldCells>()
private val playerCells = ArrayList<UIItemPlayerCells>()
var mode = 0 // 0: show players, 1: show worlds
override fun show() {
printdbg(this, "savefiles show()")
@@ -109,19 +124,31 @@ class UILoadDemoSavefiles : UICanvas() {
Thread {
// read savegames
var savegamesCount = 0
App.savegameWorlds.forEach { (uuid, skimmer) ->
App.savegameWorlds.forEach { (_, skimmer) ->
val x = uiX + if (App.getConfigBoolean("fx_streamerslayout")) App.scr.chatWidth / 2 else 0
val y = titleTopGradEnd + cellInterval * savegamesCount
try {
addUIitem(UIItemWorldCells(this, x, y, skimmer))
worldCells.add(UIItemWorldCells(this, x, y, skimmer))
savegamesCount += 1
}
catch (e: Throwable) {
System.err.println("[UILoadDemoSavefiles] Error while loading World '${skimmer.diskFile.absolutePath}'")
e.printStackTrace()
}
}
savegamesCount = 0
App.savegamePlayers.forEach { (_, skimmer) ->
val x = uiX + if (App.getConfigBoolean("fx_streamerslayout")) App.scr.chatWidth / 2 else 0
val y = titleTopGradEnd + cellInterval * savegamesCount
try {
playerCells.add(UIItemPlayerCells(this, x, y, skimmer))
savegamesCount += 1
}
catch (e: Throwable) {
System.err.println("[UILoadDemoSavefiles] Error while loading Player '${skimmer.diskFile.absolutePath}'")
e.printStackTrace()
}
}
@@ -134,10 +161,14 @@ class UILoadDemoSavefiles : UICanvas() {
}
override fun hide() {
uiItems.forEach { it.dispose() }
uiItems.clear()
worldCells.forEach { it.dispose() }
worldCells.clear()
playerCells.forEach { it.dispose() }
playerCells.clear()
}
private fun getCells() = if (mode == 0) playerCells else worldCells
override fun updateUI(delta: Float) {
if (scrollTarget != listScroll) {
@@ -156,8 +187,10 @@ class UILoadDemoSavefiles : UICanvas() {
}
}
for (index in 0 until uiItems.size) {
val it = uiItems[index]
val cells = getCells()
for (index in 0 until cells.size) {
val it = cells[index]
if (index in listScroll - 2 until listScroll + savesVisible + 2) {
// re-position
it.posY = (it.initialY - uiScroll).roundToInt()
@@ -172,6 +205,8 @@ class UILoadDemoSavefiles : UICanvas() {
batch.end()
val cells = getCells()
lateinit var savePixmap: Pixmap
sliderFBO.inAction(camera as OrthographicCamera, batch) {
gdxClearAndSetBlend(0f,0f,0f,0f)
@@ -179,8 +214,8 @@ class UILoadDemoSavefiles : UICanvas() {
setCameraPosition(batch, camera, 0f, 0f)
batch.color = Color.WHITE
batch.inUse {
for (index in 0 until uiItems.size) {
val it = uiItems[index]
for (index in 0 until cells.size) {
val it = cells[index]
if (index in listScroll - 2 until listScroll + savesVisible + 2) {
it.render(batch, camera)
}
@@ -240,12 +275,14 @@ class UILoadDemoSavefiles : UICanvas() {
override fun keyDown(keycode: Int): Boolean {
if (this.isVisible) {
val cells = getCells()
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) {
scrollFrom = listScroll
scrollTarget -= 1
scrollAnimCounter = 0f
}
else if ((keycode == Input.Keys.DOWN || keycode == App.getConfigInt("control_key_down")) && scrollTarget < uiItems.size - savesVisible) {
else if ((keycode == Input.Keys.DOWN || keycode == App.getConfigInt("control_key_down")) && scrollTarget < cells.size - savesVisible) {
scrollFrom = listScroll
scrollTarget += 1
scrollAnimCounter = 0f
@@ -256,12 +293,14 @@ class UILoadDemoSavefiles : UICanvas() {
override fun scrolled(amountX: Float, amountY: Float): Boolean {
if (this.isVisible) {
val cells = getCells()
if (amountY <= -1f && scrollTarget > 0) {
scrollFrom = listScroll
scrollTarget -= 1
scrollAnimCounter = 0f
}
else if (amountY >= 1f && scrollTarget < uiItems.size - savesVisible) {
else if (amountY >= 1f && scrollTarget < cells.size - savesVisible) {
scrollFrom = listScroll
scrollTarget += 1
scrollAnimCounter = 0f
@@ -323,9 +362,109 @@ class UIItemPlayerCells(
override val width = SAVE_CELL_WIDTH
override val height = SAVE_CELL_HEIGHT
private var thumbPixmap: Pixmap? = null
private var thumb: TextureRegion? = null
override var clickOnceListener: ((Int, Int, Int) -> Unit)? = { _: Int, _: Int, _: Int ->
parent.playerDisk = skimmer
}
private var playerName: String = "$EMDASH"
private var worldName: String = "$EMDASH"
private var lastPlayTime: String = "--h--m--s"
private var totalPlayTime: String = "--:--:--"
init {
skimmer.getFile(-1L)?.bytes?.let {
val json = JsonReader().parse(ByteArray64Reader(it, Common.CHARSET))
val playerUUID = UUID.fromString(json["uuid"]?.asString())
val worldUUID = UUID.fromString(json["worldCurrentlyPlaying"]?.asString())
App.savegamePlayersName[playerUUID]?.let { if (it.isNotBlank()) playerName = it }
App.savegameWorldsName[worldUUID]?.let { if (it.isNotBlank()) worldName = it }
json["lastPlayTime"]?.asString()?.let {
lastPlayTime = Instant.ofEpochSecond(it.toLong())
.atZone(TimeZone.getDefault().toZoneId())
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
}
json["totalPlayTime"]?.asString()?.let {
totalPlayTime = parseDuration(it.toLong())
}
}
}
private fun parseDuration(seconds: Long): String {
val s = seconds % 60
val m = (seconds / 60) % 60
val h = (seconds / 3600) % 24
val d = seconds / 86400
return if (d == 0L)
"${h.toString().padStart(2,'0')}h${m.toString().padStart(2,'0')}m${s.toString().padStart(2,'0')}s"
else
"${d}d${h.toString().padStart(2,'0')}h${m.toString().padStart(2,'0')}m${s.toString().padStart(2,'0')}s"
}
private var sprite: SpriteAnimation? = null
internal var hasTexture = false
private set
private val cellCol = CELL_COL
override fun render(batch: SpriteBatch, camera: Camera) {
// try to generate a texture
if (skimmer.initialised && !hasTexture) {
skimmer.getFile(-1L)?.bytes?.let {
val animFile = skimmer.getFile(-2L)!!
val p = ReadPlayer(skimmer, ByteArray64Reader(it, Common.CHARSET))
val sprite = SpriteAnimation(p)
val animDesc = ADProperties(ByteArray64Reader(animFile.bytes, Common.CHARSET))
p.reassembleSprite(skimmer, sprite, animDesc)
sprite.textureRegion.get(0,0).let {
thumb = it
}
this.sprite = sprite
}
hasTexture = true
}
val highlightCol = if (mouseUp) UIItemTextButton.defaultActiveCol else Color.WHITE
val x = posX.toFloat()
val y = posY.toFloat()
// draw box backgrounds
batch.color = cellCol
Toolkit.fillArea(batch, posX, posY, 106, height)
Toolkit.fillArea(batch, posX + 116, posY + 63, width - 116, 57)
// draw borders
batch.color = highlightCol
// avatar border
Toolkit.drawBoxBorder(batch, posX - 1, posY - 1, 106 + 2, height + 2)
// infocell border
Toolkit.drawBoxBorder(batch, posX + 115, posY + 62, width - 114, 59)
// infocell divider
Toolkit.fillArea(batch, posX + 118, posY + 90, width - 120, 1)
// player avatar
batch.color = Color.WHITE
thumb?.let {
batch.draw(it, x + FastMath.ceil((106f - it.regionWidth) / 2f), y + FastMath.ceil((height - it.regionHeight) / 2f))
}
// texts
App.fontGame.draw(batch, playerName, x + 120f, y + height - 54f)
App.fontGame.draw(batch, worldName, x + 120f, y + height - 24f)
App.fontGame.draw(batch, lastPlayTime, x + width - 4f - App.fontGame.getWidth(lastPlayTime), y + height - 54f)
App.fontGame.draw(batch, totalPlayTime, x + width - 4f - App.fontGame.getWidth(totalPlayTime), y + height - 24f)
}
override fun dispose() {
thumb?.texture?.dispose()
thumbPixmap?.dispose()
sprite?.dispose()
}
@@ -398,6 +537,7 @@ class UIItemWorldCells(
private val colourBad = Color(0xFF0011FF.toInt())
private val cellCol = CELL_COL
init {
@@ -405,6 +545,7 @@ class UIItemWorldCells(
}
override var clickOnceListener: ((Int, Int, Int) -> Unit)? = { _: Int, _: Int, _: Int ->
parent.worldDisk = skimmer
TODO()
}
@@ -435,8 +576,10 @@ class UIItemWorldCells(
val x = posX.toFloat()
val y = posY.toFloat()
// TODO draw border
// draw background
batch.color = cellCol
Toolkit.fillArea(batch, posX, posY, width, height)
// draw border
batch.color = highlightCol
Toolkit.drawBoxBorder(batch, posX-1, posY-1, width+2, height+2)

View File

@@ -1,73 +0,0 @@
package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.Second
import net.torvald.terrarum.blendNormal
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemList
/**
* Created by minjaesong on 2018-09-15.
*/
class UITitleCharactersList : UICanvas() {
override var openCloseTime: Second = 0f
private val moduleAreaHMargin = 48
private val moduleAreaBorder = 8
override var width = App.scr.width - UIRemoCon.remoConWidth - moduleAreaHMargin
override var height = App.scr.height - moduleAreaHMargin * 2
private val moduleInfoCells = ArrayList<UIItemSavegameInfoCell>()
// build characters list
init {
//SavegameLedger.getSavefileList()?.forEachIndexed { index, file ->
//
//}
}
private val mouduleArea = UIItemList<UIItemSavegameInfoCell>(
this,
moduleInfoCells,
UIRemoCon.remoConWidth, moduleAreaHMargin,
width,
height,
inactiveCol = Color.WHITE,
border = moduleAreaBorder
)
init {
uiItems.add(mouduleArea)
}
override fun updateUI(delta: Float) {
mouduleArea.update(delta)
}
override fun renderUI(batch: SpriteBatch, camera: Camera) {
batch.color = Color.WHITE
blendNormal(batch)
mouduleArea.render(batch, camera)
}
override fun doOpening(delta: Float) {
}
override fun doClosing(delta: Float) {
}
override fun endOpening(delta: Float) {
}
override fun endClosing(delta: Float) {
}
override fun dispose() {
}
}

View File

@@ -101,6 +101,9 @@ object WritePlayer {
/**
* Player-specific [ReadActor].
*
* @param disk disk
* @param dataStream Reader containing JSON file
*
* Created by minjaesong on 2021-10-07.
*/
object ReadPlayer {

Binary file not shown.