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 *if file -1025 is not there, read bodyparts from assets directory
*optionally encrypt the files other than -1 *optionally encrypt the files other than -1
*disk name is player's name encoded in UTF-8
+ Shared + Shared
- <e.g. Disk GUID>, TEVD { * } - <e.g. Disk GUID>, TEVD { * }
- <this directory can have anything> - <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, [0x1_0000_0000L or (layerNumber shl 24) or chunkNumber] chunk data,
[-2] screenshot.tga.gz taken by the last player [-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`) (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 package net.torvald.spriteanimation
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.Texture
import net.torvald.spriteassembler.ADProperties import net.torvald.spriteassembler.ADProperties
import net.torvald.spriteassembler.AssembleSheetPixmap import net.torvald.spriteassembler.AssembleSheetPixmap
import net.torvald.terrarum.tvda.DiskSkimmer
import net.torvald.terrarum.tvda.SimpleFileSystem import net.torvald.terrarum.tvda.SimpleFileSystem
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
@@ -71,7 +69,7 @@ interface HasAssembledSprite {
private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) { private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) {
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job? // 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) val texture = Texture(pixmap)
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest) texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
pixmap.dispose() pixmap.dispose()

View File

@@ -5,6 +5,7 @@ import net.torvald.terrarum.linearSearchBy
import net.torvald.terrarum.serialise.Common import net.torvald.terrarum.serialise.Common
import java.io.InputStream import java.io.InputStream
import java.io.Reader import java.io.Reader
import java.io.StringReader
import java.util.* import java.util.*
internal data class Joint(val name: String, val position: ADPropertyObject.Vector2i) { internal data class Joint(val name: String, val position: ADPropertyObject.Vector2i) {
@@ -79,30 +80,29 @@ class ADProperties {
constructor(gdxFile: FileHandle) { constructor(gdxFile: FileHandle) {
fileFrom = gdxFile.path() fileFrom = gdxFile.path()
adlString = gdxFile.readString(Common.CHARSET.name()) adlString = gdxFile.readString(Common.CHARSET.name())
javaProp.load(gdxFile.read())
continueLoad() continueLoad()
} }
constructor(reader: Reader) { constructor(reader: Reader) {
adlString = reader.readText() adlString = reader.readText()
javaProp.load(reader)
continueLoad() continueLoad()
} }
constructor(inputStream: InputStream) { constructor(inputStream: InputStream) {
adlString = inputStream.readAllBytes().toString(Common.CHARSET) adlString = inputStream.readAllBytes().toString(Common.CHARSET)
javaProp.load(inputStream)
continueLoad() continueLoad()
} }
private fun continueLoad() { private fun continueLoad() {
javaProp.load(StringReader(adlString))
// sanity check // sanity check
reservedProps.forEach { reservedProps.forEach {
try { try {
javaProp[it]!! javaProp[it]!!
} }
catch (e: NullPointerException) { 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()) if (it.name.isBlank())
throw IllegalArgumentException("Empty Bodypart name on BODYPARTS; try removing trailing semicolon (';')?") throw IllegalArgumentException("Empty Bodypart name on BODYPARTS; try removing trailing semicolon (';')?")
else 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) * 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, DiskSkimmer> savegameWorlds = new TreeMap<>();
public static TreeMap<UUID, String> savegameWorldsName = new TreeMap<>();
public static TreeMap<UUID, DiskSkimmer> savegamePlayers = new TreeMap<>(); public static TreeMap<UUID, DiskSkimmer> savegamePlayers = new TreeMap<>();
public static TreeMap<UUID, String> savegamePlayersName = new TreeMap<>();
public static void updateListOfSavegames() { public static void updateListOfSavegames() {
AppUpdateListOfSavegames(); AppUpdateListOfSavegames();

View File

@@ -19,6 +19,7 @@ import net.torvald.terrarum.App.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.WireCodex import net.torvald.terrarum.blockproperties.WireCodex
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorID import net.torvald.terrarum.gameactors.ActorID
import net.torvald.terrarum.gameactors.faction.FactionCodex import net.torvald.terrarum.gameactors.faction.FactionCodex
@@ -682,7 +683,9 @@ class Codex : KVHashMap() {
fun AppUpdateListOfSavegames() { fun AppUpdateListOfSavegames() {
App.savegamePlayers.clear() App.savegamePlayers.clear()
App.savegamePlayersName.clear()
App.savegameWorlds.clear() App.savegameWorlds.clear()
App.savegameWorldsName.clear()
println("listing savegames...") println("listing savegames...")
@@ -692,7 +695,7 @@ fun AppUpdateListOfSavegames() {
DiskSkimmer(file, Common.CHARSET, true) DiskSkimmer(file, Common.CHARSET, true)
} }
catch (e: Throwable) { 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() e.printStackTrace()
null null
} }
@@ -705,9 +708,33 @@ fun AppUpdateListOfSavegames() {
val json = JsonReader().parse(ByteArray64Reader(jsonFile.bytes, Common.CHARSET).readText()) val json = JsonReader().parse(ByteArray64Reader(jsonFile.bytes, Common.CHARSET).readText())
val worldUUID = UUID.fromString(json.get("worldIndex")!!.asString()) val worldUUID = UUID.fromString(json.get("worldIndex")!!.asString())
App.savegameWorlds[worldUUID] = it 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( worldDisk = VDUtil.createNewDisk(
1L shl 60, 1L shl 60,
worldSavefileName, savegameNickname,
Common.CHARSET Common.CHARSET
) )
playerDisk = VDUtil.createNewDisk( playerDisk = VDUtil.createNewDisk(
1L shl 60, 1L shl 60,
playerSavefileName, actorGamer.actorValue.getAsString(AVKey.NAME) ?: "",
Common.CHARSET Common.CHARSET
) )

View File

@@ -119,7 +119,7 @@ class IngamePlayer : ActorHumanoid {
private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) { private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) {
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job? // 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) val texture = Texture(pixmap)
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest) texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
pixmap.dispose() pixmap.dispose()

View File

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

View File

@@ -34,6 +34,8 @@ class UIInventoryFull(
override var openCloseTime: Second = 0.0f override var openCloseTime: Second = 0.0f
companion object { companion object {
val CELL_COL = Color(0x28282888)
const val INVEN_DEBUG_MODE = false 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 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 com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.gameitem.GameItem 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.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.UIInventoryFull.Companion.itemListHeight
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.createInvCellGenericKeyDownFun import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.createInvCellGenericKeyDownFun
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.createInvCellGenericTouchDownFun import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.createInvCellGenericTouchDownFun
@@ -43,7 +43,7 @@ class UIItemInventoryEquippedView(
lateinit var inventorySortList: Array<GameItem?> lateinit var inventorySortList: Array<GameItem?>
private var rebuildList = true private var rebuildList = true
val spriteViewBackCol: Color = CELLCOLOUR_BLACK val spriteViewBackCol: Color = CELL_COL
private val equipPosIcon = CommonResourcePool.getAsTextureRegionPack("inventory_category") private val equipPosIcon = CommonResourcePool.getAsTextureRegionPack("inventory_category")
private val cellToIcon = intArrayOf(0,1,2,3,4,5,6,7,6,7,6,7) private val cellToIcon = intArrayOf(0,1,2,3,4,5,6,7,6,7,6,7)
@@ -59,7 +59,7 @@ class UIItemInventoryEquippedView(
itemImage = null, itemImage = null,
mouseoverBackCol = Color(CELLCOLOUR_BLACK_ACTIVE), mouseoverBackCol = Color(CELLCOLOUR_BLACK_ACTIVE),
mouseoverBackBlendMode = BlendMode.SCREEN, mouseoverBackBlendMode = BlendMode.SCREEN,
backCol = CELLCOLOUR_BLACK, backCol = CELL_COL,
backBlendMode = BlendMode.NORMAL, backBlendMode = BlendMode.NORMAL,
drawBackOnNull = true, drawBackOnNull = true,
keyDownFun = createInvCellGenericKeyDownFun(), 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.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair 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.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.modulebasegame.ui.UIInventoryFull.Companion.INVEN_DEBUG_MODE
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItem import net.torvald.terrarum.ui.UIItem
@@ -55,7 +55,7 @@ class UIItemInventoryItemGrid(
override val width = horizontalCells * UIItemInventoryElemSimple.height + (horizontalCells - 1) * listGap override val width = horizontalCells * UIItemInventoryElemSimple.height + (horizontalCells - 1) * listGap
override val height = verticalCells * UIItemInventoryElemSimple.height + (verticalCells - 1) * listGap override val height = verticalCells * UIItemInventoryElemSimple.height + (verticalCells - 1) * listGap
val backColour = CELLCOLOUR_BLACK val backColour = CELL_COL
init { init {
CommonResourcePool.addToLoadingList("inventory_walletnumberfont") { 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.FrameBuffer
import com.badlogic.gdx.graphics.glutils.ShapeRenderer import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import com.badlogic.gdx.utils.JsonReader import com.badlogic.gdx.utils.JsonReader
import com.jme3.math.FastMath
import net.torvald.EMDASH
import net.torvald.getKeycapConsole import net.torvald.getKeycapConsole
import net.torvald.getKeycapPC import net.torvald.getKeycapPC
import net.torvald.spriteanimation.SpriteAnimation
import net.torvald.spriteassembler.ADProperties
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.langpack.Lang 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.Common
import net.torvald.terrarum.serialise.ReadPlayer
import net.torvald.terrarum.tvda.ByteArray64InputStream import net.torvald.terrarum.tvda.ByteArray64InputStream
import net.torvald.terrarum.tvda.ByteArray64Reader import net.torvald.terrarum.tvda.ByteArray64Reader
import net.torvald.terrarum.tvda.DiskSkimmer import net.torvald.terrarum.tvda.DiskSkimmer
@@ -97,6 +103,15 @@ class UILoadDemoSavefiles : UICanvas() {
private var showSpinner = false 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() { override fun show() {
printdbg(this, "savefiles show()") printdbg(this, "savefiles show()")
@@ -109,19 +124,31 @@ class UILoadDemoSavefiles : UICanvas() {
Thread { Thread {
// read savegames // read savegames
var savegamesCount = 0 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 x = uiX + if (App.getConfigBoolean("fx_streamerslayout")) App.scr.chatWidth / 2 else 0
val y = titleTopGradEnd + cellInterval * savegamesCount val y = titleTopGradEnd + cellInterval * savegamesCount
try { try {
addUIitem(UIItemWorldCells(this, x, y, skimmer)) worldCells.add(UIItemWorldCells(this, x, y, skimmer))
savegamesCount += 1 savegamesCount += 1
} }
catch (e: Throwable) { catch (e: Throwable) {
System.err.println("[UILoadDemoSavefiles] Error while loading World '${skimmer.diskFile.absolutePath}'") System.err.println("[UILoadDemoSavefiles] Error while loading World '${skimmer.diskFile.absolutePath}'")
e.printStackTrace() 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() { override fun hide() {
uiItems.forEach { it.dispose() } worldCells.forEach { it.dispose() }
uiItems.clear() worldCells.clear()
playerCells.forEach { it.dispose() }
playerCells.clear()
} }
private fun getCells() = if (mode == 0) playerCells else worldCells
override fun updateUI(delta: Float) { override fun updateUI(delta: Float) {
if (scrollTarget != listScroll) { if (scrollTarget != listScroll) {
@@ -156,8 +187,10 @@ class UILoadDemoSavefiles : UICanvas() {
} }
} }
for (index in 0 until uiItems.size) { val cells = getCells()
val it = uiItems[index]
for (index in 0 until cells.size) {
val it = cells[index]
if (index in listScroll - 2 until listScroll + savesVisible + 2) { if (index in listScroll - 2 until listScroll + savesVisible + 2) {
// re-position // re-position
it.posY = (it.initialY - uiScroll).roundToInt() it.posY = (it.initialY - uiScroll).roundToInt()
@@ -172,6 +205,8 @@ class UILoadDemoSavefiles : UICanvas() {
batch.end() batch.end()
val cells = getCells()
lateinit var savePixmap: Pixmap lateinit var savePixmap: Pixmap
sliderFBO.inAction(camera as OrthographicCamera, batch) { sliderFBO.inAction(camera as OrthographicCamera, batch) {
gdxClearAndSetBlend(0f,0f,0f,0f) gdxClearAndSetBlend(0f,0f,0f,0f)
@@ -179,8 +214,8 @@ class UILoadDemoSavefiles : UICanvas() {
setCameraPosition(batch, camera, 0f, 0f) setCameraPosition(batch, camera, 0f, 0f)
batch.color = Color.WHITE batch.color = Color.WHITE
batch.inUse { batch.inUse {
for (index in 0 until uiItems.size) { for (index in 0 until cells.size) {
val it = uiItems[index] val it = cells[index]
if (index in listScroll - 2 until listScroll + savesVisible + 2) { if (index in listScroll - 2 until listScroll + savesVisible + 2) {
it.render(batch, camera) it.render(batch, camera)
} }
@@ -240,12 +275,14 @@ class UILoadDemoSavefiles : UICanvas() {
override fun keyDown(keycode: Int): Boolean { override fun keyDown(keycode: Int): Boolean {
if (this.isVisible) { if (this.isVisible) {
val cells = getCells()
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) { if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) {
scrollFrom = listScroll scrollFrom = listScroll
scrollTarget -= 1 scrollTarget -= 1
scrollAnimCounter = 0f 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 scrollFrom = listScroll
scrollTarget += 1 scrollTarget += 1
scrollAnimCounter = 0f scrollAnimCounter = 0f
@@ -256,12 +293,14 @@ class UILoadDemoSavefiles : UICanvas() {
override fun scrolled(amountX: Float, amountY: Float): Boolean { override fun scrolled(amountX: Float, amountY: Float): Boolean {
if (this.isVisible) { if (this.isVisible) {
val cells = getCells()
if (amountY <= -1f && scrollTarget > 0) { if (amountY <= -1f && scrollTarget > 0) {
scrollFrom = listScroll scrollFrom = listScroll
scrollTarget -= 1 scrollTarget -= 1
scrollAnimCounter = 0f scrollAnimCounter = 0f
} }
else if (amountY >= 1f && scrollTarget < uiItems.size - savesVisible) { else if (amountY >= 1f && scrollTarget < cells.size - savesVisible) {
scrollFrom = listScroll scrollFrom = listScroll
scrollTarget += 1 scrollTarget += 1
scrollAnimCounter = 0f scrollAnimCounter = 0f
@@ -323,9 +362,109 @@ class UIItemPlayerCells(
override val width = SAVE_CELL_WIDTH override val width = SAVE_CELL_WIDTH
override val height = SAVE_CELL_HEIGHT 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() { override fun dispose() {
thumb?.texture?.dispose()
thumbPixmap?.dispose()
sprite?.dispose()
} }
@@ -398,6 +537,7 @@ class UIItemWorldCells(
private val colourBad = Color(0xFF0011FF.toInt()) private val colourBad = Color(0xFF0011FF.toInt())
private val cellCol = CELL_COL
init { init {
@@ -405,6 +545,7 @@ class UIItemWorldCells(
} }
override var clickOnceListener: ((Int, Int, Int) -> Unit)? = { _: Int, _: Int, _: Int -> override var clickOnceListener: ((Int, Int, Int) -> Unit)? = { _: Int, _: Int, _: Int ->
parent.worldDisk = skimmer
TODO() TODO()
} }
@@ -435,8 +576,10 @@ class UIItemWorldCells(
val x = posX.toFloat() val x = posX.toFloat()
val y = posY.toFloat() val y = posY.toFloat()
// draw background
// TODO draw border batch.color = cellCol
Toolkit.fillArea(batch, posX, posY, width, height)
// draw border
batch.color = highlightCol batch.color = highlightCol
Toolkit.drawBoxBorder(batch, posX-1, posY-1, width+2, height+2) 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]. * Player-specific [ReadActor].
* *
* @param disk disk
* @param dataStream Reader containing JSON file
*
* Created by minjaesong on 2021-10-07. * Created by minjaesong on 2021-10-07.
*/ */
object ReadPlayer { object ReadPlayer {

Binary file not shown.