mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-09 21:31:51 +09:00
finally working again: create new character
todo: make delete character work
This commit is contained in:
@@ -10,7 +10,7 @@ import com.badlogic.gdx.Input
|
||||
object DefaultConfig {
|
||||
|
||||
val hashMap = hashMapOf<String, Any>(
|
||||
"jvm_xmx" to 8,
|
||||
"jvm_xmx" to 4,
|
||||
"jvm_extra_cmd" to "",
|
||||
"displayfps" to 0, // 0: no limit, non-zero: limit
|
||||
"displayfpsidle" to 0, // 0: no limit, non-zero: limit
|
||||
|
||||
@@ -39,10 +39,10 @@ class SavegameCollection(files0: List<DiskSkimmer>) {
|
||||
|
||||
class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollection?) {
|
||||
|
||||
private lateinit var manualPlayer: DiskSkimmer
|
||||
private lateinit var manualWorld: DiskSkimmer
|
||||
private lateinit var autoPlayer: DiskSkimmer
|
||||
private lateinit var autoWorld: DiskSkimmer
|
||||
private var manualPlayer: DiskSkimmer? = null
|
||||
private var manualWorld: DiskSkimmer? = null
|
||||
private var autoPlayer: DiskSkimmer? = null
|
||||
private var autoWorld: DiskSkimmer? = null
|
||||
|
||||
var status = 0 // 0: none available, 1: loadable manual save is newer than loadable auto; 2: loadable autosave is newer than loadable manual
|
||||
private set
|
||||
@@ -55,8 +55,8 @@ class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollect
|
||||
|
||||
if (player != null && world != null) {
|
||||
|
||||
printdbg(this, player.files.joinToString { it.diskFile.name })
|
||||
printdbg(this, world.files.joinToString { it.diskFile.name })
|
||||
printdbg(this, "player files: " + player.files.joinToString { it.diskFile.name })
|
||||
printdbg(this, "world files:" + world.files.joinToString { it.diskFile.name })
|
||||
|
||||
// if a pair of files were saved successfully, they must have identical lastModifiedTime()
|
||||
var pc = 0; val pt = player.files[0].getLastModifiedTime()
|
||||
@@ -75,7 +75,7 @@ class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollect
|
||||
|
||||
when (pcf.isAutosaved().toInt(1) or wcf.isAutosaved().toInt()) {
|
||||
3 -> {
|
||||
if (!::autoPlayer.isInitialized && !::autoWorld.isInitialized) {
|
||||
if (autoPlayer == null && autoWorld == null) {
|
||||
autoPlayer = pcf
|
||||
autoWorld = wcf
|
||||
}
|
||||
@@ -83,7 +83,7 @@ class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollect
|
||||
wc += 1
|
||||
}
|
||||
0 -> {
|
||||
if (!::manualPlayer.isInitialized && !::manualWorld.isInitialized) {
|
||||
if (manualPlayer == null && manualWorld == null) {
|
||||
manualPlayer = pcf
|
||||
manualWorld = wcf
|
||||
}
|
||||
@@ -105,32 +105,25 @@ class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollect
|
||||
|
||||
|
||||
|
||||
if (::manualPlayer.isInitialized && ::manualWorld.isInitialized && ::autoPlayer.isInitialized && ::autoWorld.isInitialized)
|
||||
if (manualPlayer != null && manualWorld != null && autoPlayer != null && autoWorld != null)
|
||||
break
|
||||
}
|
||||
|
||||
if (::manualPlayer.isInitialized && ::manualWorld.isInitialized && ::autoPlayer.isInitialized && ::autoWorld.isInitialized) {
|
||||
status = if (manualPlayer.getLastModifiedTime() > autoPlayer.getLastModifiedTime()) 1 else 2
|
||||
|
||||
printdbg(this, "manualPlayer = ${manualPlayer.diskFile.path}")
|
||||
printdbg(this, "manualWorld = ${manualWorld.diskFile.path}")
|
||||
printdbg(this, "autoPlayer = ${autoPlayer.diskFile.path}")
|
||||
printdbg(this, "autoWorld = ${autoWorld.diskFile.path}")
|
||||
if (manualPlayer != null && manualWorld != null && autoPlayer != null && autoWorld != null) {
|
||||
status = if (manualPlayer!!.getLastModifiedTime() > autoPlayer!!.getLastModifiedTime()) 1 else 2
|
||||
}
|
||||
else if (::manualPlayer.isInitialized && ::manualWorld.isInitialized || ::autoPlayer.isInitialized && ::autoWorld.isInitialized) {
|
||||
else if (manualPlayer != null && manualWorld != null || autoPlayer != null && autoWorld != null) {
|
||||
status = 1
|
||||
if (::manualPlayer.isInitialized) {
|
||||
printdbg(this, "manualPlayer = ${manualPlayer.diskFile.path}")
|
||||
printdbg(this, "manualWorld = ${manualWorld.diskFile.path}")
|
||||
}
|
||||
else {
|
||||
printdbg(this, "autoPlayer = ${autoPlayer.diskFile.path}")
|
||||
printdbg(this, "autoWorld = ${autoWorld.diskFile.path}")
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = 0
|
||||
}
|
||||
|
||||
printdbg(this, "manualPlayer = ${manualPlayer?.diskFile?.path}")
|
||||
printdbg(this, "manualWorld = ${manualWorld?.diskFile?.path}")
|
||||
printdbg(this, "autoPlayer = ${autoPlayer?.diskFile?.path}")
|
||||
printdbg(this, "autoWorld = ${autoWorld?.diskFile?.path}")
|
||||
printdbg(this, "status = $status")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,12 +142,20 @@ class SavegameCollectionPair(player: SavegameCollection?, world: SavegameCollect
|
||||
|
||||
fun getManualSave(): DiskPair? {
|
||||
if (status == 0) return null
|
||||
return DiskPair(manualPlayer, manualWorld)
|
||||
return DiskPair(manualPlayer!!, manualWorld!!)
|
||||
}
|
||||
|
||||
fun getAutoSave(): DiskPair? {
|
||||
if (status != 2) return null
|
||||
return DiskPair(autoPlayer, autoWorld)
|
||||
return DiskPair(autoPlayer!!, autoWorld!!)
|
||||
}
|
||||
|
||||
fun getLoadableSave(): DiskPair? {
|
||||
if (status == 0) return null
|
||||
return if (manualPlayer != null && manualWorld != null)
|
||||
DiskPair(manualPlayer!!, manualWorld!!)
|
||||
else
|
||||
DiskPair(autoPlayer!!, autoWorld!!)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ object ScreencapNogui: ConsoleCommand {
|
||||
PixmapIO2.writeTGA(Gdx.files.absolute(App.defaultDir + "/Exports/${args[1]}.tga"), p, true)
|
||||
p.dispose()
|
||||
}
|
||||
IngameRenderer.screencapRequested = true
|
||||
IngameRenderer.requestScreencap()
|
||||
Echo("FBO exported to$ccG Exports/${args[1]}.tga")
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -11,7 +11,7 @@ import com.badlogic.gdx.utils.Disposable
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.measureDebugTime
|
||||
import net.torvald.terrarum.App.*
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
@@ -21,6 +21,7 @@ import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
import net.torvald.terrarum.weather.WeatherMixer.render
|
||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||
@@ -365,13 +366,19 @@ object IngameRenderer : Disposable {
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (screencapRequested) {
|
||||
screencapRequested = false
|
||||
printdbg(this, "Screencap was requested, processing...")
|
||||
var hasError = false
|
||||
try {
|
||||
screencapExportCallback(fboMixedOut)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
printdbgerr(this, "An error occured while taking screencap:")
|
||||
e.printStackTrace()
|
||||
hasError = true
|
||||
}
|
||||
printdbg(this, "Screencap ${if (hasError) "failed" else "successful"}")
|
||||
screencapBusy = false
|
||||
screencapRequested = false
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@@ -416,11 +423,16 @@ object IngameRenderer : Disposable {
|
||||
* This "screencap" will capture the game WITHOUT gui and postprocessors!
|
||||
* To capture the entire game, use [App.requestScreenshot]
|
||||
*/
|
||||
@Volatile internal var screencapRequested = false
|
||||
@Volatile internal var fboRGBexportedLatch = false
|
||||
@Volatile private var screencapRequested = false
|
||||
@Volatile internal var screencapBusy = false; private set
|
||||
@Volatile internal var screencapExportCallback: (FrameBuffer) -> Unit = {}
|
||||
@Volatile internal lateinit var fboRGBexport: Pixmap
|
||||
|
||||
fun requestScreencap() {
|
||||
screencapRequested = true
|
||||
screencapBusy = true
|
||||
}
|
||||
|
||||
private fun drawToRGB(
|
||||
actorsRenderBehind: List<ActorWithBody>?,
|
||||
actorsRenderMiddle: List<ActorWithBody>?,
|
||||
|
||||
@@ -420,10 +420,15 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
// 2. cannot sync up the "counter" to determine whether both are finished
|
||||
uiAutosaveNotifier.setAsOpen()
|
||||
val saveTime_t = App.getTIME_T()
|
||||
printdbg(this, "Immediate Save")
|
||||
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.PLAYER, playerDisk, getPlayerSaveFiledesc(playerSavefileName), this, true, autosaveOnErrorAction) {
|
||||
printdbg(this, "immediate save callback from PLAYER")
|
||||
|
||||
makeSavegameBackupCopy(getPlayerSaveFiledesc(playerSavefileName))
|
||||
|
||||
WriteSavegame.immediate(saveTime_t, WriteSavegame.SaveMode.WORLD, worldDisk, getWorldSaveFiledesc(worldSavefileName), this, true, autosaveOnErrorAction) {
|
||||
printdbg(this, "immediate save callback from WORLD")
|
||||
|
||||
makeSavegameBackupCopy(getWorldSaveFiledesc(worldSavefileName)) // don't put it on the postInit() or render(); must be called using callback
|
||||
uiAutosaveNotifier.setAsClose()
|
||||
}
|
||||
@@ -472,7 +477,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
world.worldCreator = UUID.fromString(player.uuid.toString())
|
||||
|
||||
printdbg(this, "new woridIndex: ${world.worldIndex}")
|
||||
printdbg(this, "new worldIndex: ${world.worldIndex}")
|
||||
printdbg(this, "worldCurrentlyPlaying: ${player.worldCurrentlyPlaying}")
|
||||
|
||||
actorNowPlaying = player
|
||||
|
||||
@@ -1,36 +1,5 @@
|
||||
package net.torvald.terrarum.modulebasegame.serialise
|
||||
|
||||
import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.ItemCodex
|
||||
import net.torvald.terrarum.ModMgr
|
||||
import net.torvald.terrarum.ReferencingRanges.PREFIX_DYNAMICITEM
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.toInt
|
||||
import net.torvald.terrarum.savegame.*
|
||||
import net.torvald.terrarum.savegame.VDFileID.LOADORDER
|
||||
import net.torvald.terrarum.savegame.VDFileID.PLAYER_SCREENSHOT
|
||||
import net.torvald.terrarum.savegame.VDFileID.ROOT
|
||||
import net.torvald.terrarum.savegame.VDFileID.SAVEGAMEINFO
|
||||
import net.torvald.terrarum.savegame.VDFileID.THUMBNAIL
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import java.io.File
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
/**
|
||||
* Will happily overwrite existing entry
|
||||
*/
|
||||
private fun addFile(disk: VirtualDisk, file: DiskEntry) {
|
||||
disk.entries[file.entryID] = file
|
||||
file.parentEntryID = 0
|
||||
val dir = VDUtil.getAsDirectory(disk, 0)
|
||||
if (!dir.contains(file.entryID)) dir.add(file.entryID)
|
||||
}
|
||||
|
||||
abstract class SavingThread(private val errorHandler: (Throwable) -> Unit) : Runnable {
|
||||
abstract fun save()
|
||||
@@ -46,211 +15,4 @@ abstract class SavingThread(private val errorHandler: (Throwable) -> Unit) : Run
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2021-09-14.
|
||||
*/
|
||||
class WorldSavingThread(
|
||||
val time_t: Long,
|
||||
val disk: VirtualDisk,
|
||||
val outFile: File,
|
||||
val ingame: TerrarumIngame,
|
||||
val isAuto: Boolean,
|
||||
val callback: () -> Unit,
|
||||
val errorHandler: (Throwable) -> Unit
|
||||
) : SavingThread(errorHandler) {
|
||||
|
||||
override fun save() {
|
||||
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
disk.saveKind = VDSaveKind.WORLD_DATA
|
||||
|
||||
while (!IngameRenderer.fboRGBexportedLatch) {
|
||||
Thread.sleep(1L)
|
||||
}
|
||||
|
||||
val allTheActors = ingame.actorContainerActive.cloneToList() + ingame.actorContainerInactive.cloneToList()
|
||||
|
||||
val playersList: List<IngamePlayer> = allTheActors.filterIsInstance<IngamePlayer>()
|
||||
val actorsList = allTheActors.filter { WriteWorld.actorAcceptable(it) }
|
||||
val layers = intArrayOf(0,1).map { ingame.world.getLayer(it) }
|
||||
val cw = ingame.world.width / LandUtil.CHUNK_W
|
||||
val ch = ingame.world.height / LandUtil.CHUNK_H
|
||||
|
||||
WriteSavegame.saveProgress = 0f
|
||||
WriteSavegame.saveProgressMax = 3f + (cw * ch * layers.size) + actorsList.size
|
||||
|
||||
|
||||
val tgaout = ByteArray64GrowableOutputStream()
|
||||
val gzout = GZIPOutputStream(tgaout)
|
||||
|
||||
printdbg(this, "Writing metadata...")
|
||||
|
||||
val creation_t = ingame.world.creationTime
|
||||
|
||||
|
||||
// Write subset of Ingame.ItemCodex
|
||||
// The existing ItemCodex must be rewritten to clear out obsolete records
|
||||
|
||||
// We're assuming the dynamic item generated by players does exist in the world, and it's recorded
|
||||
// into the world's dynamicToStaticTable, therefore every item recorded into the world's dynamicToStaticTable
|
||||
// can be found in this world without need to look up the players
|
||||
ingame.world.dynamicToStaticTable.clear()
|
||||
ingame.world.dynamicItemInventory.clear()
|
||||
actorsList.filterIsInstance<Pocketed>().forEach { actor ->
|
||||
actor.inventory.forEach { (itemid, _) ->
|
||||
|
||||
printdbg(this, "World side dynamicitem: $itemid contained in $actor")
|
||||
|
||||
if (itemid.startsWith("$PREFIX_DYNAMICITEM:")) {
|
||||
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
|
||||
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
actorsList.filterIsInstance<FixtureBase>().forEach { fixture ->
|
||||
fixture.inventory?.forEach { (itemid, _) ->
|
||||
|
||||
printdbg(this, "World side dynamicitem: $itemid contained in $fixture")
|
||||
|
||||
if (itemid.startsWith("$PREFIX_DYNAMICITEM:")) {
|
||||
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
|
||||
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||
IngameRenderer.fboRGBexport.dispose()
|
||||
|
||||
val thumbContent = EntryFile(tgaout.toByteArray64())
|
||||
val thumb = DiskEntry(THUMBNAIL, ROOT, creation_t, time_t, thumbContent)
|
||||
addFile(disk, thumb)
|
||||
|
||||
|
||||
|
||||
WriteSavegame.saveProgress += 1f
|
||||
|
||||
// Write World //
|
||||
|
||||
val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t, actorsList, playersList))
|
||||
val world = DiskEntry(SAVEGAMEINFO, ROOT, creation_t, time_t, worldMeta)
|
||||
addFile(disk, world)
|
||||
|
||||
WriteSavegame.saveProgress += 1f
|
||||
|
||||
|
||||
for (layer in layers.indices) {
|
||||
for (cx in 0 until cw) {
|
||||
for (cy in 0 until ch) {
|
||||
val chunkNumber = LandUtil.chunkXYtoChunkNum(ingame.world, cx, cy).toLong()
|
||||
|
||||
// Echo("Writing chunks... ${(cw*ch*layer) + chunkNumber + 1}/${cw*ch*layers.size}")
|
||||
|
||||
val chunkBytes = WriteWorld.encodeChunk(layers[layer]!!, cx, cy)
|
||||
val entryID = 0x1_0000_0000L or layer.toLong().shl(24) or chunkNumber
|
||||
|
||||
val entryContent = EntryFile(chunkBytes)
|
||||
val entry = DiskEntry(entryID, ROOT, creation_t, time_t, entryContent)
|
||||
// "W1L0-92,15"
|
||||
addFile(disk, entry)
|
||||
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write Actors //
|
||||
actorsList.forEachIndexed { count, it ->
|
||||
// Echo("Writing actors... ${count+1}/${actorsList.size}")
|
||||
|
||||
val actorContent = EntryFile(WriteActor.encodeToByteArray64(it))
|
||||
val actor = DiskEntry(it.referenceID.toLong(), ROOT, creation_t, time_t, actorContent)
|
||||
addFile(disk, actor)
|
||||
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
|
||||
|
||||
// write loadorder //
|
||||
val loadOrderBa64Writer = ByteArray64Writer(Common.CHARSET)
|
||||
loadOrderBa64Writer.write(ModMgr.loadOrder.joinToString("\n"))
|
||||
loadOrderBa64Writer.flush(); loadOrderBa64Writer.close()
|
||||
val loadOrderText = loadOrderBa64Writer.toByteArray64()
|
||||
val loadOrderContents = EntryFile(loadOrderText)
|
||||
addFile(disk, DiskEntry(LOADORDER, ROOT, creation_t, time_t, loadOrderContents))
|
||||
|
||||
|
||||
|
||||
// Echo("Writing file to disk...")
|
||||
|
||||
disk.entries[0]!!.modificationDate = time_t
|
||||
// entry zero MUST NOT be used to get lastPlayDate, but we'll update it anyway
|
||||
// use entry -1 for that purpose!
|
||||
disk.capacity = 0
|
||||
VDUtil.dumpToRealMachine(disk, outFile)
|
||||
|
||||
|
||||
|
||||
printdbg(this, "Game saved with size of ${outFile.length()} bytes")
|
||||
|
||||
|
||||
IngameRenderer.fboRGBexportedLatch = false
|
||||
WriteSavegame.savingStatus = 255
|
||||
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function called means the "Avatar" was not externally created and thus has no sprite-bodypart-name-to-entry-number-map
|
||||
*
|
||||
* Created by minjaesong on 2021-10-08
|
||||
*/
|
||||
class PlayerSavingThread(
|
||||
val time_t: Long,
|
||||
val disk: VirtualDisk,
|
||||
val outFile: File,
|
||||
val ingame: TerrarumIngame,
|
||||
val isAuto: Boolean,
|
||||
val callback: () -> Unit,
|
||||
val errorHandler: (Throwable) -> Unit
|
||||
) : SavingThread(errorHandler) {
|
||||
|
||||
override fun save() {
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
disk.saveKind = VDSaveKind.PLAYER_DATA
|
||||
disk.capacity = 0L
|
||||
|
||||
WriteSavegame.saveProgress = 0f
|
||||
|
||||
// wait for screencap
|
||||
while (!IngameRenderer.fboRGBexportedLatch) {
|
||||
Thread.sleep(1L)
|
||||
}
|
||||
|
||||
// write screencap
|
||||
val tgaout = ByteArray64GrowableOutputStream()
|
||||
val gzout = GZIPOutputStream(tgaout)
|
||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||
IngameRenderer.fboRGBexport.dispose()
|
||||
val thumbContent = EntryFile(tgaout.toByteArray64())
|
||||
val thumb = DiskEntry(PLAYER_SCREENSHOT, ROOT, ingame.world.creationTime, time_t, thumbContent)
|
||||
addFile(disk, thumb)
|
||||
|
||||
|
||||
|
||||
printdbg(this, "Writing The Player...")
|
||||
WritePlayer(ingame.actorGamer, disk, ingame, time_t)
|
||||
disk.entries[0]!!.modificationDate = time_t
|
||||
VDUtil.dumpToRealMachine(disk, outFile)
|
||||
|
||||
|
||||
IngameRenderer.fboRGBexportedLatch = false
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const val SCREENCAP_WAIT_TRY_MAX = 256
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package net.torvald.terrarum.modulebasegame.serialise
|
||||
|
||||
import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.savegame.*
|
||||
import net.torvald.terrarum.toInt
|
||||
import java.io.File
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
/**
|
||||
* This function called means the "Avatar" was not externally created and thus has no sprite-bodypart-name-to-entry-number-map
|
||||
*
|
||||
* Created by minjaesong on 2021-10-08
|
||||
*/
|
||||
class PlayerSavingThread(
|
||||
val time_t: Long,
|
||||
val disk: VirtualDisk,
|
||||
val outFile: File,
|
||||
val ingame: TerrarumIngame,
|
||||
val isAuto: Boolean,
|
||||
val callback: () -> Unit,
|
||||
val errorHandler: (Throwable) -> Unit
|
||||
) : SavingThread(errorHandler) {
|
||||
/**
|
||||
* Will happily overwrite existing entry
|
||||
*/
|
||||
private fun addFile(disk: VirtualDisk, file: DiskEntry) {
|
||||
disk.entries[file.entryID] = file
|
||||
file.parentEntryID = 0
|
||||
val dir = VDUtil.getAsDirectory(disk, 0)
|
||||
if (!dir.contains(file.entryID)) dir.add(file.entryID)
|
||||
}
|
||||
|
||||
|
||||
override fun save() {
|
||||
App.printdbg(this, "outFile: ${outFile.path}")
|
||||
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
disk.saveKind = VDSaveKind.PLAYER_DATA
|
||||
disk.capacity = 0L
|
||||
|
||||
WriteSavegame.saveProgress = 0f
|
||||
|
||||
// wait for screencap
|
||||
var emergencyStopCnt = 0
|
||||
while (IngameRenderer.screencapBusy) {
|
||||
// printdbg(this, "spinning for screencap to be taken")
|
||||
Thread.sleep(4L)
|
||||
emergencyStopCnt += 1
|
||||
if (emergencyStopCnt >= SCREENCAP_WAIT_TRY_MAX) throw InterruptedException("Waiting screencap to be taken for too long")
|
||||
}
|
||||
|
||||
// write screencap
|
||||
val tgaout = ByteArray64GrowableOutputStream()
|
||||
val gzout = GZIPOutputStream(tgaout)
|
||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||
IngameRenderer.fboRGBexport.dispose()
|
||||
val thumbContent = EntryFile(tgaout.toByteArray64())
|
||||
val thumb =
|
||||
DiskEntry(VDFileID.PLAYER_SCREENSHOT, VDFileID.ROOT, ingame.world.creationTime, time_t, thumbContent)
|
||||
addFile(disk, thumb)
|
||||
|
||||
|
||||
|
||||
App.printdbg(this, "Writing The Player...")
|
||||
WritePlayer(ingame.actorGamer, disk, ingame, time_t)
|
||||
disk.entries[0]!!.modificationDate = time_t
|
||||
VDUtil.dumpToRealMachine(disk, outFile)
|
||||
|
||||
|
||||
// IngameRenderer.screencapBusy = false
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
@@ -45,10 +45,17 @@ class QuickSingleplayerWorldSavingThread(
|
||||
|
||||
|
||||
override fun save() {
|
||||
printdbg(this, "outFile: ${outFile.path}")
|
||||
|
||||
val skimmer = DiskSkimmer(outFile)
|
||||
|
||||
while (!IngameRenderer.fboRGBexportedLatch) {
|
||||
Thread.sleep(1L)
|
||||
// wait for screencap
|
||||
var emergencyStopCnt = 0
|
||||
while (IngameRenderer.screencapBusy) {
|
||||
// printdbg(this, "spinning for screencap to be taken")
|
||||
Thread.sleep(4L)
|
||||
emergencyStopCnt += 1
|
||||
if (emergencyStopCnt >= SCREENCAP_WAIT_TRY_MAX) throw InterruptedException("Waiting screencap to be taken for too long")
|
||||
}
|
||||
|
||||
val allTheActors = ingame.actorContainerActive.cloneToList() + ingame.actorContainerInactive.cloneToList()
|
||||
@@ -147,7 +154,7 @@ class QuickSingleplayerWorldSavingThread(
|
||||
printdbg(this, "Game saved with size of ${outFile.length()} bytes")
|
||||
|
||||
|
||||
IngameRenderer.fboRGBexportedLatch = false
|
||||
// IngameRenderer.screencapBusy = false
|
||||
WriteSavegame.savingStatus = 255
|
||||
ingame.clearModifiedChunks()
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
package net.torvald.terrarum.modulebasegame.serialise
|
||||
|
||||
import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.savegame.*
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import java.io.File
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2021-09-14.
|
||||
*/
|
||||
class WorldSavingThread(
|
||||
val time_t: Long,
|
||||
val disk: VirtualDisk,
|
||||
val outFile: File,
|
||||
val ingame: TerrarumIngame,
|
||||
val isAuto: Boolean,
|
||||
val callback: () -> Unit,
|
||||
val errorHandler: (Throwable) -> Unit
|
||||
) : SavingThread(errorHandler) {
|
||||
/**
|
||||
* Will happily overwrite existing entry
|
||||
*/
|
||||
private fun addFile(disk: VirtualDisk, file: DiskEntry) {
|
||||
disk.entries[file.entryID] = file
|
||||
file.parentEntryID = 0
|
||||
val dir = VDUtil.getAsDirectory(disk, 0)
|
||||
if (!dir.contains(file.entryID)) dir.add(file.entryID)
|
||||
}
|
||||
|
||||
|
||||
override fun save() {
|
||||
App.printdbg(this, "outFile: ${outFile.path}")
|
||||
|
||||
disk.saveMode = 2 * isAuto.toInt() // no quick
|
||||
disk.saveKind = VDSaveKind.WORLD_DATA
|
||||
|
||||
// wait for screencap
|
||||
var emergencyStopCnt = 0
|
||||
while (IngameRenderer.screencapBusy) {
|
||||
// printdbg(this, "spinning for screencap to be taken")
|
||||
Thread.sleep(4L)
|
||||
emergencyStopCnt += 1
|
||||
if (emergencyStopCnt >= SCREENCAP_WAIT_TRY_MAX) throw InterruptedException("Waiting screencap to be taken for too long")
|
||||
}
|
||||
|
||||
val allTheActors = ingame.actorContainerActive.cloneToList() + ingame.actorContainerInactive.cloneToList()
|
||||
|
||||
val playersList: List<IngamePlayer> = allTheActors.filterIsInstance<IngamePlayer>()
|
||||
val actorsList = allTheActors.filter { WriteWorld.actorAcceptable(it) }
|
||||
val layers = intArrayOf(0,1).map { ingame.world.getLayer(it) }
|
||||
val cw = ingame.world.width / LandUtil.CHUNK_W
|
||||
val ch = ingame.world.height / LandUtil.CHUNK_H
|
||||
|
||||
WriteSavegame.saveProgress = 0f
|
||||
WriteSavegame.saveProgressMax = 3f + (cw * ch * layers.size) + actorsList.size
|
||||
|
||||
|
||||
val tgaout = ByteArray64GrowableOutputStream()
|
||||
val gzout = GZIPOutputStream(tgaout)
|
||||
|
||||
App.printdbg(this, "Writing metadata...")
|
||||
|
||||
val creation_t = ingame.world.creationTime
|
||||
|
||||
|
||||
// Write subset of Ingame.ItemCodex
|
||||
// The existing ItemCodex must be rewritten to clear out obsolete records
|
||||
|
||||
// We're assuming the dynamic item generated by players does exist in the world, and it's recorded
|
||||
// into the world's dynamicToStaticTable, therefore every item recorded into the world's dynamicToStaticTable
|
||||
// can be found in this world without need to look up the players
|
||||
ingame.world.dynamicToStaticTable.clear()
|
||||
ingame.world.dynamicItemInventory.clear()
|
||||
actorsList.filterIsInstance<Pocketed>().forEach { actor ->
|
||||
actor.inventory.forEach { (itemid, _) ->
|
||||
|
||||
App.printdbg(this, "World side dynamicitem: $itemid contained in $actor")
|
||||
|
||||
if (itemid.startsWith("${ReferencingRanges.PREFIX_DYNAMICITEM}:")) {
|
||||
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
|
||||
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
actorsList.filterIsInstance<FixtureBase>().forEach { fixture ->
|
||||
fixture.inventory?.forEach { (itemid, _) ->
|
||||
|
||||
App.printdbg(this, "World side dynamicitem: $itemid contained in $fixture")
|
||||
|
||||
if (itemid.startsWith("${ReferencingRanges.PREFIX_DYNAMICITEM}:")) {
|
||||
ingame.world.dynamicToStaticTable[itemid] = ItemCodex.dynamicToStaticID(itemid)
|
||||
ingame.world.dynamicItemInventory[itemid] = ItemCodex[itemid]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
PixmapIO2._writeTGA(gzout, IngameRenderer.fboRGBexport, true, true)
|
||||
IngameRenderer.fboRGBexport.dispose()
|
||||
|
||||
val thumbContent = EntryFile(tgaout.toByteArray64())
|
||||
val thumb = DiskEntry(VDFileID.THUMBNAIL, VDFileID.ROOT, creation_t, time_t, thumbContent)
|
||||
addFile(disk, thumb)
|
||||
|
||||
|
||||
|
||||
WriteSavegame.saveProgress += 1f
|
||||
|
||||
// Write World //
|
||||
|
||||
val worldMeta = EntryFile(WriteWorld.encodeToByteArray64(ingame, time_t, actorsList, playersList))
|
||||
val world = DiskEntry(VDFileID.SAVEGAMEINFO, VDFileID.ROOT, creation_t, time_t, worldMeta)
|
||||
addFile(disk, world)
|
||||
|
||||
WriteSavegame.saveProgress += 1f
|
||||
|
||||
|
||||
for (layer in layers.indices) {
|
||||
for (cx in 0 until cw) {
|
||||
for (cy in 0 until ch) {
|
||||
val chunkNumber = LandUtil.chunkXYtoChunkNum(ingame.world, cx, cy).toLong()
|
||||
|
||||
// Echo("Writing chunks... ${(cw*ch*layer) + chunkNumber + 1}/${cw*ch*layers.size}")
|
||||
|
||||
val chunkBytes = WriteWorld.encodeChunk(layers[layer]!!, cx, cy)
|
||||
val entryID = 0x1_0000_0000L or layer.toLong().shl(24) or chunkNumber
|
||||
|
||||
val entryContent = EntryFile(chunkBytes)
|
||||
val entry = DiskEntry(entryID, VDFileID.ROOT, creation_t, time_t, entryContent)
|
||||
// "W1L0-92,15"
|
||||
addFile(disk, entry)
|
||||
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write Actors //
|
||||
actorsList.forEachIndexed { count, it ->
|
||||
// Echo("Writing actors... ${count+1}/${actorsList.size}")
|
||||
|
||||
val actorContent = EntryFile(WriteActor.encodeToByteArray64(it))
|
||||
val actor = DiskEntry(it.referenceID.toLong(), VDFileID.ROOT, creation_t, time_t, actorContent)
|
||||
addFile(disk, actor)
|
||||
|
||||
WriteSavegame.saveProgress += 1
|
||||
}
|
||||
|
||||
|
||||
// write loadorder //
|
||||
val loadOrderBa64Writer = ByteArray64Writer(Common.CHARSET)
|
||||
loadOrderBa64Writer.write(ModMgr.loadOrder.joinToString("\n"))
|
||||
loadOrderBa64Writer.flush(); loadOrderBa64Writer.close()
|
||||
val loadOrderText = loadOrderBa64Writer.toByteArray64()
|
||||
val loadOrderContents = EntryFile(loadOrderText)
|
||||
addFile(disk, DiskEntry(VDFileID.LOADORDER, VDFileID.ROOT, creation_t, time_t, loadOrderContents))
|
||||
|
||||
|
||||
|
||||
// Echo("Writing file to disk...")
|
||||
|
||||
disk.entries[0]!!.modificationDate = time_t
|
||||
// entry zero MUST NOT be used to get lastPlayDate, but we'll update it anyway
|
||||
// use entry -1 for that purpose!
|
||||
disk.capacity = 0
|
||||
VDUtil.dumpToRealMachine(disk, outFile)
|
||||
|
||||
|
||||
|
||||
App.printdbg(this, "Game saved with size of ${outFile.length()} bytes")
|
||||
|
||||
|
||||
// IngameRenderer.screencapBusy = false
|
||||
WriteSavegame.savingStatus = 255
|
||||
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
@@ -43,10 +43,7 @@ object WriteSavegame {
|
||||
else -> throw IllegalArgumentException("$mode")
|
||||
}
|
||||
|
||||
operator fun invoke(time_t: Long, mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, errorHandler: (Throwable) -> Unit, callback: () -> Unit) {
|
||||
savingStatus = 0
|
||||
printdbg(this, "Save queued")
|
||||
|
||||
private fun installScreencap() {
|
||||
IngameRenderer.screencapExportCallback = { fb ->
|
||||
printdbg(this, "Generating thumbnail...")
|
||||
|
||||
@@ -63,11 +60,19 @@ object WriteSavegame {
|
||||
IngameRenderer.fboRGBexport = p
|
||||
//PixmapIO2._writeTGA(gzout, p, true, true)
|
||||
//p.dispose()
|
||||
IngameRenderer.fboRGBexportedLatch = true
|
||||
|
||||
printdbg(this, "Done thumbnail generation")
|
||||
}
|
||||
IngameRenderer.screencapRequested = true
|
||||
}
|
||||
|
||||
operator fun invoke(time_t: Long, mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, errorHandler: (Throwable) -> Unit, callback: () -> Unit) {
|
||||
savingStatus = 0
|
||||
printdbg(this, "Save queued")
|
||||
|
||||
installScreencap()
|
||||
try { printdbg(this, "ScreencapExport installed: ${IngameRenderer.screencapExportCallback}") }
|
||||
catch (e: UninitializedPropertyAccessException) { printdbg(this, "ScreencapExport installed: no") }
|
||||
IngameRenderer.requestScreencap()
|
||||
|
||||
val savingThread = Thread(getSaveThread(time_t, mode, disk, outFile, ingame, isAuto, errorHandler, callback), "TerrarumBasegameGameSaveThread")
|
||||
savingThread.start()
|
||||
@@ -78,11 +83,14 @@ object WriteSavegame {
|
||||
|
||||
|
||||
fun immediate(time_t: Long, mode: SaveMode, disk: VirtualDisk, outFile: File, ingame: TerrarumIngame, isAuto: Boolean, errorHandler: (Throwable) -> Unit, callback: () -> Unit) {
|
||||
|
||||
savingStatus = 0
|
||||
|
||||
printdbg(this, "Immediate save fired")
|
||||
|
||||
installScreencap()
|
||||
try { printdbg(this, "ScreencapExport installed: ${IngameRenderer.screencapExportCallback}") }
|
||||
catch (e: UninitializedPropertyAccessException) { printdbg(this, "ScreencapExport installed: no") }
|
||||
IngameRenderer.requestScreencap()
|
||||
|
||||
val savingThread = Thread(getSaveThread(time_t, mode, disk, outFile, ingame, isAuto, errorHandler, callback), "TerrarumBasegameGameSaveThread")
|
||||
savingThread.start()
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
private val MODE_SAVE_MULTIPLE_CHOICES = 2
|
||||
private val MODE_LOAD_DA_SHIT_ALREADY = 255
|
||||
private val MODE_SAVE_DAMAGED = 256
|
||||
private val MODE_SAVE_DELETE = 512
|
||||
|
||||
private lateinit var loadables: SavegameCollectionPair
|
||||
|
||||
@@ -229,7 +230,7 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
MODE_SAVE_DAMAGED
|
||||
}
|
||||
else {
|
||||
val (p, w) = loadables.getManualSave()!!
|
||||
val (p, w) = loadables.getLoadableSave()!!
|
||||
UILoadGovernor.playerDisk = p; UILoadGovernor.worldDisk = w
|
||||
|
||||
if (loadables.newerSaveIsDamaged) {
|
||||
@@ -329,10 +330,25 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
private var oldMode = -1
|
||||
|
||||
private val mode1Node = Yaml(UITitleRemoConYaml.injectedMenuSingleCharSel).parse()
|
||||
private val mode2Node = Yaml(UITitleRemoConYaml.injectedMenuSingleWorldSel).parse()
|
||||
// private val mode2Node = Yaml(UITitleRemoConYaml.injectedMenuSingleWorldSel).parse()
|
||||
|
||||
private val menus = listOf(mode1Node, mode2Node)
|
||||
private val titles = listOf("CONTEXT_CHARACTER", "MENU_LABEL_WORLD")
|
||||
// private val menus = listOf(mode1Node, mode2Node)
|
||||
|
||||
private val deleteCharacterButton = UIItemTextButton(
|
||||
this, "CONTEXT_CHARACTER_DELETE",
|
||||
UIRemoCon.menubarOffX - UIRemoCon.UIRemoConElement.paddingLeft + 11,
|
||||
UIRemoCon.menubarOffY - UIRemoCon.UIRemoConElement.lineHeight * 3 + 16,
|
||||
remoCon.width + UIRemoCon.UIRemoConElement.paddingLeft,
|
||||
true,
|
||||
inactiveCol = Toolkit.Theme.COL_RED,
|
||||
activeCol = Toolkit.Theme.COL_REDD,
|
||||
hitboxSize = UIRemoCon.UIRemoConElement.lineHeight - 2
|
||||
).also {
|
||||
it.clickOnceListener = { _,_ ->
|
||||
mode = MODE_SAVE_DELETE
|
||||
it.highlighted = true
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
// this UI will NOT persist; the parent of the mode1Node must be set using an absolute value (e.g. treeRoot, not remoCon.currentRemoConContents)
|
||||
@@ -341,22 +357,25 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
//printStackTrace(this)
|
||||
|
||||
mode1Node.parent = remoCon.treeRoot
|
||||
mode2Node.parent = mode1Node
|
||||
// mode2Node.parent = mode1Node
|
||||
|
||||
mode1Node.data = "MENU_MODE_SINGLEPLAYER : net.torvald.terrarum.modulebasegame.ui.UILoadSavegame"
|
||||
mode2Node.data = "MENU_MODE_SINGLEPLAYER : net.torvald.terrarum.modulebasegame.ui.UILoadSavegame"
|
||||
// mode2Node.data = "MENU_MODE_SINGLEPLAYER : net.torvald.terrarum.modulebasegame.ui.UILoadSavegame"
|
||||
|
||||
// printdbg(this, "mode1Node parent: ${mode1Node.parent?.data}") // will be 'null' because the parent is the root node
|
||||
// printdbg(this, "mode1Node data: ${mode1Node.data}")
|
||||
// printdbg(this, "mode2Node data: ${mode2Node.data}")
|
||||
|
||||
}
|
||||
|
||||
private fun modeChangedHandler(mode: Int) {
|
||||
remoCon.setNewRemoConContents(menus[mode])
|
||||
printdbg(this, "Change mode: $oldMode -> $mode")
|
||||
// remoCon.setNewRemoConContents(menus[mode])
|
||||
remoCon.setNewRemoConContents(mode1Node)
|
||||
}
|
||||
|
||||
override fun updateUI(delta: Float) {
|
||||
if (mode == MODE_SELECT) {
|
||||
if (mode == MODE_SELECT || mode == MODE_SAVE_DELETE) {
|
||||
|
||||
if (oldMode != mode) {
|
||||
modeChangedHandler(mode)
|
||||
@@ -413,7 +432,7 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
LoadSavegame(UILoadGovernor.playerDisk!!, UILoadGovernor.worldDisk)
|
||||
}
|
||||
}
|
||||
else if (mode == MODE_SELECT) {
|
||||
else if (mode == MODE_SELECT || mode == MODE_SAVE_DELETE) {
|
||||
batch.end()
|
||||
|
||||
val cells = getCells()
|
||||
@@ -474,11 +493,6 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
val saveTex = TextureRegion(Texture(savePixmap)); saveTex.flip(false, true)
|
||||
batch.inUse {
|
||||
batch.draw(saveTex, (width - uiWidth - 10) / 2f, 0f)
|
||||
|
||||
// draw texts
|
||||
val loadGameTitleStr = Lang[titles[mode]]// + "$EMDASH$hash"
|
||||
// "Game Load"
|
||||
App.fontUITitle.draw(batch, loadGameTitleStr, (width - App.fontUITitle.getWidth(loadGameTitleStr)).div(2).toFloat(), titleTextPosY.toFloat())
|
||||
// Control help
|
||||
App.fontGame.draw(batch, controlHelp, uiX.toFloat(), controlHelperY.toFloat())
|
||||
}
|
||||
@@ -506,11 +520,16 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
loadAutoThumbButton.render(batch, camera)
|
||||
loadManualThumbButton.render(batch, camera)
|
||||
}
|
||||
|
||||
|
||||
if (mode == MODE_SELECT || mode == MODE_SAVE_DELETE) {
|
||||
deleteCharacterButton.render(batch, camera)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun keyDown(keycode: Int): Boolean {
|
||||
if (this.isVisible) {
|
||||
if (this.isVisible && (mode == MODE_SELECT || mode == MODE_SAVE_DELETE)) {
|
||||
val cells = getCells()
|
||||
|
||||
if ((keycode == Input.Keys.UP || keycode == App.getConfigInt("control_key_up")) && scrollTarget > 0) {
|
||||
@@ -531,6 +550,7 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
if (mode == MODE_SELECT) getCells().forEach { it.touchDown(screenX, screenY, pointer, button) }
|
||||
if (::loadAutoThumbButton.isInitialized && mode == MODE_SAVE_MULTIPLE_CHOICES) { loadAutoThumbButton.touchDown(screenX, screenY, pointer, button) }
|
||||
if (::loadManualThumbButton.isInitialized && mode == MODE_SAVE_MULTIPLE_CHOICES) { loadManualThumbButton.touchDown(screenX, screenY, pointer, button) }
|
||||
if (mode == MODE_SELECT || mode == MODE_SAVE_DELETE) deleteCharacterButton.touchDown(screenX, screenY, pointer, button)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -538,11 +558,12 @@ class UILoadSavegame(val remoCon: UIRemoCon) : Advanceable() {
|
||||
if (mode == MODE_SELECT) getCells().forEach { it.touchUp(screenX, screenY, pointer, button) }
|
||||
if (::loadAutoThumbButton.isInitialized && mode == MODE_SAVE_MULTIPLE_CHOICES) { loadAutoThumbButton.touchUp(screenX, screenY, pointer, button) }
|
||||
if (::loadManualThumbButton.isInitialized && mode == MODE_SAVE_MULTIPLE_CHOICES) { loadManualThumbButton.touchUp(screenX, screenY, pointer, button) }
|
||||
if (mode == MODE_SELECT || mode == MODE_SAVE_DELETE) deleteCharacterButton.touchDown(screenX, screenY, pointer, button)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun scrolled(amountX: Float, amountY: Float): Boolean {
|
||||
if (this.isVisible && mode == MODE_SELECT) {
|
||||
if (this.isVisible && mode == MODE_SELECT || mode == MODE_SAVE_DELETE) {
|
||||
val cells = getCells()
|
||||
|
||||
if (amountY <= -1f && scrollTarget > 0) {
|
||||
|
||||
@@ -4,6 +4,7 @@ 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.App.printdbg
|
||||
import net.torvald.terrarum.Second
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gameactors.AVKey
|
||||
@@ -64,6 +65,7 @@ class UINewCharacter(val remoCon: UIRemoCon) : UICanvas() {
|
||||
|
||||
|
||||
val savingThread = Thread({
|
||||
printdbg(this, "Player saving thread fired")
|
||||
|
||||
disk.saveMode = 2 // auto, no quick
|
||||
disk.capacity = 0L
|
||||
@@ -79,9 +81,11 @@ class UINewCharacter(val remoCon: UIRemoCon) : UICanvas() {
|
||||
UILoadGovernor.playerDisk = DiskSkimmer(outFile)
|
||||
// comment above if chargen must send gamers back to the charcters list
|
||||
|
||||
printdbg(this, "playerdisk: ${UILoadGovernor.playerDisk?.diskFile?.path}")
|
||||
|
||||
}, "TerrarumBasegameNewCharcterSaveThread")
|
||||
|
||||
// savingThread.start()
|
||||
// savingThread.join()
|
||||
|
||||
remoCon.openUI(UINewWorld(remoCon, savingThread)) // let UINewWorld handle the character file generation
|
||||
|
||||
@@ -95,10 +95,11 @@ class UINewWorld(val remoCon: UIRemoCon) : UICanvas() {
|
||||
goButton.clickOnceListener = { _, _ ->
|
||||
|
||||
// after the save is complete, proceed to new world generation
|
||||
newPlayerCreationThread.start()
|
||||
newPlayerCreationThread.join()
|
||||
|
||||
|
||||
// printdbg(this, "generate! Size=${sizeSelector.selection}, Name=${nameInput.getTextOrPlaceholder()}, Seed=${seedInput.getTextOrPlaceholder()}")
|
||||
printdbg(this, "generate! Size=${sizeSelector.selection}, Name=${nameInput.getTextOrPlaceholder()}, Seed=${seedInput.getTextOrPlaceholder()}")
|
||||
|
||||
val ingame = TerrarumIngame(App.batch)
|
||||
val player = ReadActor.invoke(UILoadGovernor.playerDisk!!, ByteArray64Reader(UILoadGovernor.playerDisk!!.getFile(SAVEGAMEINFO)!!.bytes, Common.CHARSET)) as IngamePlayer
|
||||
|
||||
@@ -28,6 +28,8 @@ object Toolkit : Disposable {
|
||||
val COL_SELECTED = Color(0x00f8ff_ff) // cyan, HIGHLY SATURATED
|
||||
val COL_MOUSE_UP = Color(0xfff066_ff.toInt()) // yellow (all yellows are of low saturation according to the colour science)
|
||||
val COL_DISABLED = Color(0xaaaaaaff.toInt())
|
||||
val COL_RED = Color(0xff8888ff.toInt())
|
||||
val COL_REDD = Color(0xff4448ff.toInt())
|
||||
|
||||
/*
|
||||
Try this for alt colour set:
|
||||
|
||||
@@ -32,7 +32,7 @@ class UIAutosaveNotifier : UICanvas() {
|
||||
private var errored = false
|
||||
|
||||
private var normalCol = Color.WHITE
|
||||
private var errorCol = Color(0xFF8888FF.toInt())
|
||||
private var errorCol = Toolkit.Theme.COL_RED
|
||||
|
||||
override fun updateUI(delta: Float) {
|
||||
spinnerTimer += delta
|
||||
|
||||
@@ -80,7 +80,7 @@ class UIItemTextLineInput(
|
||||
|
||||
companion object {
|
||||
val TEXTINPUT_COL_TEXT = Color.WHITE
|
||||
val TEXTINPUT_COL_TEXT_NOMORE = Color(0xFF8888FF.toInt())
|
||||
val TEXTINPUT_COL_TEXT_NOMORE = Toolkit.Theme.COL_RED
|
||||
val TEXTINPUT_COL_TEXT_DISABLED = Toolkit.Theme.COL_DISABLED
|
||||
val TEXTINPUT_COL_BACKGROUND = Toolkit.Theme.COL_CELL_FILL
|
||||
val TEXTINPUT_COL_BACKGROUND2 = Toolkit.Theme.COL_CELL_FILL.cpy()
|
||||
@@ -155,7 +155,7 @@ class UIItemTextLineInput(
|
||||
|
||||
private var textColours = arrayOf(
|
||||
Color.WHITE,
|
||||
Color(0xff8888ff.toInt()),
|
||||
Toolkit.Theme.COL_RED,
|
||||
Color(0x888888ff.toInt())
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user