mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-09 18:14:06 +09:00
fixed a bug where storagechest would not show anything on the item slot; changed inventory UI so that it would sync with the Toolkit.Theme
This commit is contained in:
@@ -23,6 +23,7 @@ import org.khelekore.prtree.*
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.locks.Lock
|
import java.util.concurrent.locks.Lock
|
||||||
|
|
||||||
@@ -360,37 +361,38 @@ open class IngameInstance(val batch: SpriteBatch, val isMultiplayer: Boolean = f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun makeSavegameBackupCopy() {
|
|
||||||
System.err.println("This function is deleteh")
|
|
||||||
printStackTrace(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies most recent `save` to `save.1`, leaving `save` for overwriting, previous `save.1` will be copied to `save.2`
|
* Copies most recent `save` to `save.1`, leaving `save` for overwriting, previous `save.1` will be copied to `save.2`
|
||||||
*/
|
*/
|
||||||
fun makeSavegameBackupCopy(file: File) {
|
fun makeSavegameBackupCopy(file: File) {
|
||||||
|
if (!file.exists()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val file1 = File("${file.absolutePath}.1")
|
||||||
|
val file2 = File("${file.absolutePath}.2")
|
||||||
|
val file3 = File("${file.absolutePath}.3")
|
||||||
|
|
||||||
|
try {
|
||||||
|
// do not overwrite clean .2 with dirty .1
|
||||||
|
val flags3 = FileInputStream(file3).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
|
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
|
if (!(flags3 == 0 && flags2 != 0) || !file3.exists()) file2.copyTo(file3, true)
|
||||||
|
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
||||||
try {
|
try {
|
||||||
// do not overwrite clean .2 with dirty .1
|
// do not overwrite clean .2 with dirty .1
|
||||||
val file2 = File("${file.absolutePath}.3")
|
|
||||||
val file1 = File("${file.absolutePath}.2")
|
|
||||||
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
val flags1 = FileInputStream(file1).let { it.skip(49L); val r = it.read(); it.close(); r }
|
val flags1 = FileInputStream(file1).let { it.skip(49L); val r = it.read(); it.close(); r }
|
||||||
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) file1.copyTo(file2, true)
|
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) file1.copyTo(file2, true)
|
||||||
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
||||||
try {
|
try {
|
||||||
// do not overwrite clean .2 with dirty .1
|
if (file2.exists() && !file3.exists())
|
||||||
val file2 = File("${file.absolutePath}.2")
|
file2.copyTo(file3, true)
|
||||||
val file1 = File("${file.absolutePath}.1")
|
if (file1.exists() && !file2.exists())
|
||||||
val flags2 = FileInputStream(file2).let { it.skip(49L); val r = it.read(); it.close(); r }
|
file1.copyTo(file2, true)
|
||||||
val flags1 = FileInputStream(file1).let { it.skip(49L); val r = it.read(); it.close(); r }
|
|
||||||
if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) file1.copyTo(file2, true)
|
file.copyTo(file1, true)
|
||||||
} catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {}
|
} catch (e: IOException) {}
|
||||||
try {
|
|
||||||
file.copyTo(
|
|
||||||
File("${file.absolutePath}.1"), // don't use .bak as it's used by the savecracker
|
|
||||||
true
|
|
||||||
)
|
|
||||||
} catch (e: NoSuchFileException) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.ScreenAdapter
|
import com.badlogic.gdx.ScreenAdapter
|
||||||
import com.badlogic.gdx.graphics.OrthographicCamera
|
import com.badlogic.gdx.graphics.OrthographicCamera
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.util.CircularArray
|
import net.torvald.util.CircularArray
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ open class LoadScreenBase : ScreenAdapter(), Disposable {
|
|||||||
screenToLoad!!.show()
|
screenToLoad!!.show()
|
||||||
}
|
}
|
||||||
catch (e: Exception) {
|
catch (e: Exception) {
|
||||||
addMessage("$ccR$e")
|
addMessage("$ccR${Lang["ERROR_SAVE_CORRUPTED"].replace(".","")}: $e")
|
||||||
errorTrapped = true
|
errorTrapped = true
|
||||||
|
|
||||||
System.err.println("Error while loading:")
|
System.err.println("Error while loading:")
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellBase
|
|||||||
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes
|
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.toItemCountText
|
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.toItemCountText
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import net.torvald.terrarum.ui.Toolkit.Theme.COL_INVENTORY_CELL_BORDER
|
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@@ -23,13 +22,6 @@ class UIItemInventoryElemSimple(
|
|||||||
override var item: GameItem?,
|
override var item: GameItem?,
|
||||||
override var amount: Int,
|
override var amount: Int,
|
||||||
override var itemImage: TextureRegion?,
|
override var itemImage: TextureRegion?,
|
||||||
val mouseOverTextCol: Color = Toolkit.Theme.COL_ACTIVE,
|
|
||||||
val mouseoverBackCol: Color = Color(0),
|
|
||||||
val mouseoverBackBlendMode: String = BlendMode.NORMAL,
|
|
||||||
val inactiveTextCol: Color = Toolkit.Theme.COL_LIST_DEFAULT,
|
|
||||||
val backCol: Color = Color(0),
|
|
||||||
val backBlendMode: String = BlendMode.NORMAL,
|
|
||||||
val highlightCol: Color = Toolkit.Theme.COL_HIGHLIGHT,
|
|
||||||
override var quickslot: Int? = null,
|
override var quickslot: Int? = null,
|
||||||
override var equippedSlot: Int? = null,
|
override var equippedSlot: Int? = null,
|
||||||
val drawBackOnNull: Boolean = true,
|
val drawBackOnNull: Boolean = true,
|
||||||
@@ -54,22 +46,17 @@ class UIItemInventoryElemSimple(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(batch: SpriteBatch, camera: Camera) {
|
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
// mouseover background
|
blendNormal(batch)
|
||||||
|
|
||||||
|
// cell background
|
||||||
if (item != null || drawBackOnNull) {
|
if (item != null || drawBackOnNull) {
|
||||||
// do not highlight even if drawBackOnNull is true
|
batch.color = Toolkit.Theme.COL_CELL_FILL
|
||||||
if (mouseUp && item != null || equippedSlot != null) { // "equippedSlot != null": also highlight back if equipped
|
|
||||||
BlendMode.resolve(mouseoverBackBlendMode, batch)
|
|
||||||
batch.color = mouseoverBackCol
|
|
||||||
}
|
|
||||||
// if drawBackOnNull, just draw background
|
|
||||||
else {
|
|
||||||
BlendMode.resolve(backBlendMode, batch)
|
|
||||||
batch.color = backCol
|
|
||||||
}
|
|
||||||
Toolkit.fillArea(batch, posX, posY, width, height)
|
Toolkit.fillArea(batch, posX, posY, width, height)
|
||||||
}
|
}
|
||||||
batch.color = COL_INVENTORY_CELL_BORDER
|
// cell border
|
||||||
//blendNormal(batch)
|
batch.color = if (equippedSlot != null) Toolkit.Theme.COL_HIGHLIGHT
|
||||||
|
else if (mouseUp) Toolkit.Theme.COL_ACTIVE
|
||||||
|
else Toolkit.Theme.COL_INVENTORY_CELL_BORDER
|
||||||
Toolkit.drawBoxBorder(batch, posX, posY, width, height)
|
Toolkit.drawBoxBorder(batch, posX, posY, width, height)
|
||||||
|
|
||||||
|
|
||||||
@@ -77,15 +64,11 @@ class UIItemInventoryElemSimple(
|
|||||||
// and you can clearly see the quickslot UI anyway
|
// and you can clearly see the quickslot UI anyway
|
||||||
|
|
||||||
if (item != null && itemImage != null) {
|
if (item != null && itemImage != null) {
|
||||||
blendNormal(batch)
|
|
||||||
|
|
||||||
// item image
|
// item image
|
||||||
batch.color = Color.WHITE
|
batch.color = Color.WHITE
|
||||||
batch.draw(itemImage, posX + imgOffsetX, posY + imgOffsetY)
|
batch.draw(itemImage, posX + imgOffsetX, posY + imgOffsetY)
|
||||||
|
|
||||||
// if mouse is over, text lights up
|
|
||||||
// this one-liner sets color
|
|
||||||
batch.color = item!!.nameColour mul if (mouseUp) mouseOverTextCol else inactiveTextCol
|
|
||||||
|
|
||||||
|
|
||||||
// if item has durability, draw that and don't draw count; durability and itemCount cannot coexist
|
// if item has durability, draw that and don't draw count; durability and itemCount cannot coexist
|
||||||
@@ -108,11 +91,13 @@ class UIItemInventoryElemSimple(
|
|||||||
else if (item!!.stackable) {
|
else if (item!!.stackable) {
|
||||||
val amountString = amount.toItemCountText()
|
val amountString = amount.toItemCountText()
|
||||||
|
|
||||||
|
// if mouse is over, text lights up
|
||||||
// highlight item count (blocks/walls) if the item is equipped
|
// highlight item count (blocks/walls) if the item is equipped
|
||||||
if (equippedSlot != null) {
|
batch.color = item!!.nameColour mul (
|
||||||
batch.color = highlightCol
|
if (equippedSlot != null) Toolkit.Theme.COL_HIGHLIGHT
|
||||||
}
|
else if (mouseUp) Toolkit.Theme.COL_ACTIVE
|
||||||
|
else Color.WHITE
|
||||||
|
)
|
||||||
|
|
||||||
App.fontSmallNumbers.draw(batch,
|
App.fontSmallNumbers.draw(batch,
|
||||||
amountString,
|
amountString,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellBase
|
|||||||
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes
|
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.toItemCountText
|
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.toItemCountText
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import net.torvald.terrarum.ui.Toolkit.Theme.COL_INVENTORY_CELL_BORDER
|
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@@ -27,12 +26,6 @@ class UIItemInventoryElemWide(
|
|||||||
override var item: GameItem?,
|
override var item: GameItem?,
|
||||||
override var amount: Int,
|
override var amount: Int,
|
||||||
override var itemImage: TextureRegion?,
|
override var itemImage: TextureRegion?,
|
||||||
val mouseOverTextCol: Color = Toolkit.Theme.COL_ACTIVE,
|
|
||||||
val mouseoverBackCol: Color = Color(0),
|
|
||||||
val mouseoverBackBlendMode: String = BlendMode.NORMAL,
|
|
||||||
val inactiveTextCol: Color = Toolkit.Theme.COL_LIST_DEFAULT,
|
|
||||||
val backCol: Color = Color(0),
|
|
||||||
val backBlendMode: String = BlendMode.NORMAL,
|
|
||||||
override var quickslot: Int? = null,
|
override var quickslot: Int? = null,
|
||||||
override var equippedSlot: Int? = null,
|
override var equippedSlot: Int? = null,
|
||||||
val drawBackOnNull: Boolean = true,
|
val drawBackOnNull: Boolean = true,
|
||||||
@@ -72,23 +65,17 @@ class UIItemInventoryElemWide(
|
|||||||
private val fwsp = 0x3000.toChar()
|
private val fwsp = 0x3000.toChar()
|
||||||
|
|
||||||
override fun render(batch: SpriteBatch, camera: Camera) {
|
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
|
blendNormal(batch)
|
||||||
|
|
||||||
// mouseover background
|
// cell background
|
||||||
if (item != null || drawBackOnNull) {
|
if (item != null || drawBackOnNull) {
|
||||||
// do not highlight even if drawBackOnNull is true
|
batch.color = Toolkit.Theme.COL_CELL_FILL
|
||||||
if (mouseUp && item != null) {
|
|
||||||
BlendMode.resolve(mouseoverBackBlendMode, batch)
|
|
||||||
batch.color = mouseoverBackCol
|
|
||||||
}
|
|
||||||
// if drawBackOnNull, just draw background
|
|
||||||
else {
|
|
||||||
BlendMode.resolve(backBlendMode, batch)
|
|
||||||
batch.color = backCol
|
|
||||||
}
|
|
||||||
Toolkit.fillArea(batch, posX, posY, width, height)
|
Toolkit.fillArea(batch, posX, posY, width, height)
|
||||||
}
|
}
|
||||||
batch.color = COL_INVENTORY_CELL_BORDER
|
// cell border
|
||||||
//blendNormal(batch)
|
batch.color = if (equippedSlot != null) Toolkit.Theme.COL_HIGHLIGHT
|
||||||
|
else if (mouseUp) Toolkit.Theme.COL_ACTIVE
|
||||||
|
else Toolkit.Theme.COL_INVENTORY_CELL_BORDER
|
||||||
Toolkit.drawBoxBorder(batch, posX, posY, width, height)
|
Toolkit.drawBoxBorder(batch, posX, posY, width, height)
|
||||||
|
|
||||||
|
|
||||||
@@ -102,8 +89,13 @@ class UIItemInventoryElemWide(
|
|||||||
batch.draw(itemImage, posX + imgOffsetX, posY + imgOffsetY)
|
batch.draw(itemImage, posX + imgOffsetX, posY + imgOffsetY)
|
||||||
|
|
||||||
// if mouse is over, text lights up
|
// if mouse is over, text lights up
|
||||||
// this one-liner sets color
|
// highlight item name and count (blocks/walls) if the item is equipped
|
||||||
batch.color = item!!.nameColour mul if (mouseUp) mouseOverTextCol else inactiveTextCol
|
batch.color = item!!.nameColour mul (
|
||||||
|
if (equippedSlot != null) Toolkit.Theme.COL_HIGHLIGHT
|
||||||
|
else if (mouseUp) Toolkit.Theme.COL_ACTIVE
|
||||||
|
else Color.WHITE
|
||||||
|
)
|
||||||
|
|
||||||
// draw name of the item
|
// draw name of the item
|
||||||
if (INVEN_DEBUG_MODE) {
|
if (INVEN_DEBUG_MODE) {
|
||||||
App.fontGame.draw(batch,
|
App.fontGame.draw(batch,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import net.torvald.terrarum.modulebasegame.worldgenerator.WorldgenParams
|
|||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||||
import net.torvald.terrarum.savegame.VDUtil
|
import net.torvald.terrarum.savegame.VDUtil
|
||||||
|
import net.torvald.terrarum.savegame.VirtualDisk
|
||||||
import net.torvald.terrarum.serialise.Common
|
import net.torvald.terrarum.serialise.Common
|
||||||
import net.torvald.terrarum.serialise.LoadSavegame
|
import net.torvald.terrarum.serialise.LoadSavegame
|
||||||
import net.torvald.terrarum.serialise.ReadActor
|
import net.torvald.terrarum.serialise.ReadActor
|
||||||
@@ -259,7 +260,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class Codices(
|
data class Codices(
|
||||||
val disk: DiskSkimmer, // WORLD disk
|
val disk: VirtualDisk, // WORLD disk
|
||||||
val world: GameWorld,
|
val world: GameWorld,
|
||||||
// val meta: WriteMeta.WorldMeta,
|
// val meta: WriteMeta.WorldMeta,
|
||||||
// val block: BlockCodex,
|
// val block: BlockCodex,
|
||||||
@@ -349,7 +350,9 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
actorNowPlaying = codices.player
|
actorNowPlaying = codices.player
|
||||||
actorGamer = codices.player
|
actorGamer = codices.player
|
||||||
|
|
||||||
makeSavegameBackupCopy() // don't put it on the postInit() or render(); postInitForNewGame calls this function on the savegamewriter's callback
|
// don't put it on the postInit() or render(); postInitForNewGame calls this function on the savegamewriter's callback
|
||||||
|
makeSavegameBackupCopy(getWorldSaveFiledesc(worldSavefileName))
|
||||||
|
makeSavegameBackupCopy(getPlayerSaveFiledesc(playerSavefileName))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun postInitForNewGame() {
|
private fun postInitForNewGame() {
|
||||||
|
|||||||
@@ -43,21 +43,21 @@ open class FixtureInventory() {
|
|||||||
}
|
}
|
||||||
open fun add(item: GameItem, count: Int = 1) {
|
open fun add(item: GameItem, count: Int = 1) {
|
||||||
|
|
||||||
println("[ActorInventory] add-by-elem $item, $count")
|
// println("[ActorInventory] add-by-elem $item, $count")
|
||||||
|
|
||||||
// other invalid values
|
// other invalid values
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
throw IllegalArgumentException("Item count is zero.")
|
throw IllegalArgumentException("[${this.javaClass.canonicalName}] Item count is zero.")
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
throw IllegalArgumentException("Item count is negative number. If you intended removing items, use remove()\n" +
|
throw IllegalArgumentException("Item count is negative number. If you intended removing items, use remove()\n" +
|
||||||
"These commands are NOT INTERCHANGEABLE; they handle things differently according to the context.")
|
"These commands are NOT INTERCHANGEABLE; they handle things differently according to the context.")
|
||||||
if (item.originalID == "actor:${Terrarum.PLAYER_REF_ID}" || item.originalID == ("actor:${0x51621D}")) // do not delete this magic
|
if (item.originalID == "actor:${Terrarum.PLAYER_REF_ID}" || item.originalID == ("actor:${0x51621D}")) // do not delete this magic
|
||||||
throw IllegalArgumentException("Attempted to put human player into the inventory.")
|
throw IllegalArgumentException("[${this.javaClass.canonicalName}] Attempted to put human player into the inventory.")
|
||||||
if (((Terrarum.ingame as? TerrarumIngame)?.gameFullyLoaded ?: false) &&
|
if (((Terrarum.ingame as? TerrarumIngame)?.gameFullyLoaded == true) &&
|
||||||
(item.originalID == "actor:${(Terrarum.ingame as? TerrarumIngame)?.actorNowPlaying?.referenceID}"))
|
(item.originalID == "actor:${(Terrarum.ingame as? TerrarumIngame)?.actorNowPlaying?.referenceID}"))
|
||||||
throw IllegalArgumentException("Attempted to put active player into the inventory.")
|
throw IllegalArgumentException("[${this.javaClass.canonicalName}] Attempted to put active player into the inventory.")
|
||||||
if ((!item.stackable || item.dynamicID.startsWith("dyn:")) && count > 1)
|
if ((!item.stackable || item.dynamicID.startsWith("dyn:")) && count > 1)
|
||||||
throw IllegalArgumentException("Attempting to adding stack of item but the item is not stackable; item: $item, count: $count")
|
throw IllegalArgumentException("[${this.javaClass.canonicalName}] Attempted to adding stack of item but the item is not stackable; item: $item, count: $count")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -89,9 +89,9 @@ open class FixtureInventory() {
|
|||||||
println("[ActorInventory] remove $item, $count")
|
println("[ActorInventory] remove $item, $count")
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
throw IllegalArgumentException("Item count is zero.")
|
throw IllegalArgumentException("[${this.javaClass.canonicalName}] Item count is zero.")
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
throw IllegalArgumentException("Item count is negative number. If you intended adding items, use add()" +
|
throw IllegalArgumentException("[${this.javaClass.canonicalName}] Item count is negative number. If you intended adding items, use add()" +
|
||||||
"These commands are NOT INTERCHANGEABLE; they handle things differently according to the context.")
|
"These commands are NOT INTERCHANGEABLE; they handle things differently according to the context.")
|
||||||
|
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ open class FixtureInventory() {
|
|||||||
val newCount = existingItem.qty - count
|
val newCount = existingItem.qty - count
|
||||||
|
|
||||||
if (newCount < 0) {
|
if (newCount < 0) {
|
||||||
throw Error("Tried to remove $count of $item, but the inventory only contains ${existingItem.qty} of them.")
|
throw Error("[${this.javaClass.canonicalName}] Tried to remove $count of $item, but the inventory only contains ${existingItem.qty} of them.")
|
||||||
}
|
}
|
||||||
else if (newCount > 0) {
|
else if (newCount > 0) {
|
||||||
// decrement count
|
// decrement count
|
||||||
@@ -115,7 +115,7 @@ open class FixtureInventory() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw Error("Tried to remove $item, but the inventory does not have it.")
|
throw Error("[${this.javaClass.canonicalName}] Tried to remove $item, but the inventory does not have it.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,73 @@ internal class UIStorageChest : UICanvas(
|
|||||||
|
|
||||||
private var halfSlotOffset = (UIItemInventoryElemSimple.height + listGap) / 2
|
private var halfSlotOffset = (UIItemInventoryElemSimple.height + listGap) / 2
|
||||||
|
|
||||||
private var initialised = false
|
init {
|
||||||
|
catBar = UIItemInventoryCatBar(
|
||||||
|
this,
|
||||||
|
(App.scr.width - catBarWidth) / 2,
|
||||||
|
42 + (App.scr.height - internalHeight) / 2,
|
||||||
|
internalWidth,
|
||||||
|
catBarWidth,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
catBar.selectionChangeListener = { old, new -> itemListUpdate() }
|
||||||
|
itemListChest = UIItemInventoryItemGrid(
|
||||||
|
this,
|
||||||
|
catBar,
|
||||||
|
{ getFixtureInventory() },
|
||||||
|
INVENTORY_CELLS_OFFSET_X() - halfSlotOffset,
|
||||||
|
INVENTORY_CELLS_OFFSET_Y(),
|
||||||
|
6, CELLS_VRT,
|
||||||
|
drawScrollOnRightside = false,
|
||||||
|
drawWallet = false,
|
||||||
|
keyDownFun = { _, _, _ -> Unit },
|
||||||
|
touchDownFun = { gameItem, amount, _ ->
|
||||||
|
if (gameItem != null) {
|
||||||
|
negotiator.reject(getFixtureInventory(), getPlayerInventory(), gameItem, amount)
|
||||||
|
}
|
||||||
|
itemListUpdate()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
// make grid mode buttons work together
|
||||||
|
itemListChest.gridModeButtons[0].touchDownListener = { _,_,_,_ -> setCompact(false) }
|
||||||
|
itemListChest.gridModeButtons[1].touchDownListener = { _,_,_,_ -> setCompact(true) }
|
||||||
|
|
||||||
|
itemListPlayer = UIItemInventoryItemGrid(
|
||||||
|
this,
|
||||||
|
catBar,
|
||||||
|
{ INGAME.actorNowPlaying!!.inventory }, // literally a player's inventory
|
||||||
|
INVENTORY_CELLS_OFFSET_X() - halfSlotOffset + (listGap + UIItemInventoryElemWide.height) * 7,
|
||||||
|
INVENTORY_CELLS_OFFSET_Y(),
|
||||||
|
6, CELLS_VRT,
|
||||||
|
drawScrollOnRightside = true,
|
||||||
|
drawWallet = false,
|
||||||
|
keyDownFun = { _, _, _ -> Unit },
|
||||||
|
touchDownFun = { gameItem, amount, _ ->
|
||||||
|
if (gameItem != null) {
|
||||||
|
negotiator.accept(getPlayerInventory(), getFixtureInventory(), gameItem, amount)
|
||||||
|
}
|
||||||
|
itemListUpdate()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
itemListPlayer.gridModeButtons[0].touchDownListener = { _,_,_,_ -> setCompact(false) }
|
||||||
|
itemListPlayer.gridModeButtons[1].touchDownListener = { _,_,_,_ -> setCompact(true) }
|
||||||
|
|
||||||
|
handler.allowESCtoClose = true
|
||||||
|
|
||||||
|
addUIitem(catBar)
|
||||||
|
addUIitem(itemListChest)
|
||||||
|
addUIitem(itemListPlayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var openingClickLatched = false
|
||||||
|
|
||||||
|
override fun show() {
|
||||||
|
itemListPlayer.getInventory = { INGAME.actorNowPlaying!!.inventory }
|
||||||
|
|
||||||
|
itemListUpdate()
|
||||||
|
|
||||||
|
openingClickLatched = Terrarum.mouseDown
|
||||||
|
}
|
||||||
|
|
||||||
private fun itemListUpdate() {
|
private fun itemListUpdate() {
|
||||||
itemListChest.rebuild(catBar.catIconsMeaning[catBar.selectedIcon])
|
itemListChest.rebuild(catBar.catIconsMeaning[catBar.selectedIcon])
|
||||||
@@ -129,72 +195,19 @@ internal class UIStorageChest : UICanvas(
|
|||||||
itemListUpdate()
|
itemListUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateUI(delta: Float) {
|
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
if (!initialised) {
|
if (!openingClickLatched) {
|
||||||
initialised = true
|
return super.touchDown(screenX, screenY, pointer, button)
|
||||||
|
|
||||||
catBar = UIItemInventoryCatBar(
|
|
||||||
this,
|
|
||||||
(App.scr.width - catBarWidth) / 2,
|
|
||||||
42 + (App.scr.height - internalHeight) / 2,
|
|
||||||
internalWidth,
|
|
||||||
catBarWidth,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
catBar.selectionChangeListener = { old, new -> itemListUpdate() }
|
|
||||||
itemListChest = UIItemInventoryItemGrid(
|
|
||||||
this,
|
|
||||||
catBar,
|
|
||||||
{ getFixtureInventory() },
|
|
||||||
INVENTORY_CELLS_OFFSET_X() - halfSlotOffset,
|
|
||||||
INVENTORY_CELLS_OFFSET_Y(),
|
|
||||||
6, CELLS_VRT,
|
|
||||||
drawScrollOnRightside = false,
|
|
||||||
drawWallet = false,
|
|
||||||
keyDownFun = { _, _, _ -> Unit },
|
|
||||||
touchDownFun = { gameItem, amount, _ ->
|
|
||||||
if (gameItem != null) {
|
|
||||||
negotiator.reject(getFixtureInventory(), getPlayerInventory(), gameItem, amount)
|
|
||||||
}
|
|
||||||
itemListUpdate()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
itemListPlayer = UIItemInventoryItemGrid(
|
|
||||||
this,
|
|
||||||
catBar,
|
|
||||||
{ INGAME.actorNowPlaying!!.inventory }, // literally a player's inventory
|
|
||||||
INVENTORY_CELLS_OFFSET_X() - halfSlotOffset + (listGap + UIItemInventoryElemWide.height) * 7,
|
|
||||||
INVENTORY_CELLS_OFFSET_Y(),
|
|
||||||
6, CELLS_VRT,
|
|
||||||
drawScrollOnRightside = true,
|
|
||||||
drawWallet = false,
|
|
||||||
keyDownFun = { _, _, _ -> Unit },
|
|
||||||
touchDownFun = { gameItem, amount, _ ->
|
|
||||||
if (gameItem != null) {
|
|
||||||
negotiator.accept(getPlayerInventory(), getFixtureInventory(), gameItem, amount)
|
|
||||||
}
|
|
||||||
itemListUpdate()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
handler.allowESCtoClose = true
|
|
||||||
|
|
||||||
// make grid mode buttons work together
|
|
||||||
itemListChest.gridModeButtons[0].touchDownListener = { _,_,_,_ -> setCompact(false) }
|
|
||||||
itemListChest.gridModeButtons[1].touchDownListener = { _,_,_,_ -> setCompact(true) }
|
|
||||||
itemListPlayer.gridModeButtons[0].touchDownListener = { _,_,_,_ -> setCompact(false) }
|
|
||||||
itemListPlayer.gridModeButtons[1].touchDownListener = { _,_,_,_ -> setCompact(true) }
|
|
||||||
|
|
||||||
addUIitem(catBar)
|
|
||||||
addUIitem(itemListChest)
|
|
||||||
addUIitem(itemListPlayer)
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateUI(delta: Float) {
|
||||||
|
|
||||||
catBar.update(delta)
|
catBar.update(delta)
|
||||||
itemListChest.update(delta)
|
itemListChest.update(delta)
|
||||||
itemListPlayer.update(delta)
|
itemListPlayer.update(delta)
|
||||||
|
|
||||||
|
if (openingClickLatched && !Terrarum.mouseDown) openingClickLatched = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ class UIInventoryEscMenu(val full: UIInventoryFull) : UICanvas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun endOpening(delta: Float) {
|
override fun endOpening(delta: Float) {
|
||||||
|
INGAME.setTooltipMessage(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun endClosing(delta: Float) {
|
override fun endClosing(delta: Float) {
|
||||||
|
|||||||
@@ -5,13 +5,10 @@ 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_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
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
import net.torvald.terrarum.ui.Toolkit.Theme.COL_INVENTORY_CELL_BORDER
|
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import net.torvald.terrarum.ui.UIItem
|
import net.torvald.terrarum.ui.UIItem
|
||||||
|
|
||||||
@@ -32,7 +29,7 @@ class UIItemInventoryEquippedView(
|
|||||||
companion object {
|
companion object {
|
||||||
val WIDTH = 2 * UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap
|
val WIDTH = 2 * UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap
|
||||||
//val HEIGHT = UIItemInventoryDynamicList.HEIGHT
|
//val HEIGHT = UIItemInventoryDynamicList.HEIGHT
|
||||||
val SPRITE_DRAW_COL = Color(0xddddddff.toInt())
|
val SPRITE_DRAW_COL = Color(0xf2f2f2ff.toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
private val listGap = 8
|
private val listGap = 8
|
||||||
@@ -43,8 +40,6 @@ class UIItemInventoryEquippedView(
|
|||||||
lateinit var inventorySortList: Array<GameItem?>
|
lateinit var inventorySortList: Array<GameItem?>
|
||||||
private var rebuildList = true
|
private var rebuildList = true
|
||||||
|
|
||||||
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)
|
||||||
private val equipPosIconCol = Color(0xdddddd7f.toInt())
|
private val equipPosIconCol = Color(0xdddddd7f.toInt())
|
||||||
@@ -57,10 +52,6 @@ class UIItemInventoryEquippedView(
|
|||||||
item = null,
|
item = null,
|
||||||
amount = UIItemInventoryElemWide.UNIQUE_ITEM_HAS_NO_AMOUNT,
|
amount = UIItemInventoryElemWide.UNIQUE_ITEM_HAS_NO_AMOUNT,
|
||||||
itemImage = null,
|
itemImage = null,
|
||||||
mouseoverBackCol = Color(CELLCOLOUR_BLACK_ACTIVE),
|
|
||||||
mouseoverBackBlendMode = BlendMode.SCREEN,
|
|
||||||
backCol = CELL_COL,
|
|
||||||
backBlendMode = BlendMode.NORMAL,
|
|
||||||
drawBackOnNull = true,
|
drawBackOnNull = true,
|
||||||
keyDownFun = createInvCellGenericKeyDownFun(),
|
keyDownFun = createInvCellGenericKeyDownFun(),
|
||||||
touchDownFun = createInvCellGenericTouchDownFun(inventoryListRebuildFun) // to "unselect" the equipped item and main item grid would "untick" accordingly
|
touchDownFun = createInvCellGenericTouchDownFun(inventoryListRebuildFun) // to "unselect" the equipped item and main item grid would "untick" accordingly
|
||||||
@@ -73,16 +64,16 @@ class UIItemInventoryEquippedView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun render(batch: SpriteBatch, camera: Camera) {
|
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
|
blendNormal(batch)
|
||||||
|
|
||||||
val posXDelta = posX - oldPosX
|
val posXDelta = posX - oldPosX
|
||||||
itemGrid.forEach { it.posX += posXDelta }
|
itemGrid.forEach { it.posX += posXDelta }
|
||||||
|
|
||||||
|
// sprite cell background
|
||||||
|
batch.color = Toolkit.Theme.COL_CELL_FILL
|
||||||
// sprite background
|
|
||||||
blendNormal(batch)
|
|
||||||
batch.color = spriteViewBackCol
|
|
||||||
Toolkit.fillArea(batch, posX, posY, width, width)
|
Toolkit.fillArea(batch, posX, posY, width, width)
|
||||||
batch.color = COL_INVENTORY_CELL_BORDER
|
// sprite cell border
|
||||||
|
batch.color = Toolkit.Theme.COL_INVENTORY_CELL_BORDER
|
||||||
Toolkit.drawBoxBorder(batch, posX, posY, width, width)
|
Toolkit.drawBoxBorder(batch, posX, posY, width, width)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -55,8 +55,6 @@ 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 = CELL_COL
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
CommonResourcePool.addToLoadingList("inventory_walletnumberfont") {
|
CommonResourcePool.addToLoadingList("inventory_walletnumberfont") {
|
||||||
TextureRegionPack("./assets/graphics/fonts/inventory_wallet_numbers.tga", 20, 9)
|
TextureRegionPack("./assets/graphics/fonts/inventory_wallet_numbers.tga", 20, 9)
|
||||||
@@ -92,13 +90,10 @@ class UIItemInventoryItemGrid(
|
|||||||
var inventorySortList = ArrayList<InventoryPair>()
|
var inventorySortList = ArrayList<InventoryPair>()
|
||||||
private var rebuildList = true
|
private var rebuildList = true
|
||||||
|
|
||||||
val defaultTextColour = Color(0xeaeaea_ff.toInt())
|
|
||||||
|
|
||||||
private val walletFont = TextureRegionPack("./assets/graphics/fonts/inventory_wallet_numbers.tga", 20, 9)
|
private val walletFont = TextureRegionPack("./assets/graphics/fonts/inventory_wallet_numbers.tga", 20, 9)
|
||||||
private var walletText = ""
|
private var walletText = ""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val listGap = 8
|
const val listGap = 8
|
||||||
const val LIST_TO_CONTROL_GAP = 12
|
const val LIST_TO_CONTROL_GAP = 12
|
||||||
@@ -179,12 +174,7 @@ class UIItemInventoryItemGrid(
|
|||||||
item = null,
|
item = null,
|
||||||
amount = UIItemInventoryElemWide.UNIQUE_ITEM_HAS_NO_AMOUNT,
|
amount = UIItemInventoryElemWide.UNIQUE_ITEM_HAS_NO_AMOUNT,
|
||||||
itemImage = null,
|
itemImage = null,
|
||||||
mouseoverBackCol = Color(CELLCOLOUR_BLACK_ACTIVE),
|
|
||||||
mouseoverBackBlendMode = BlendMode.SCREEN,
|
|
||||||
backCol = backColour,
|
|
||||||
backBlendMode = BlendMode.NORMAL,
|
|
||||||
drawBackOnNull = true,
|
drawBackOnNull = true,
|
||||||
inactiveTextCol = defaultTextColour,
|
|
||||||
keyDownFun = keyDownFun,
|
keyDownFun = keyDownFun,
|
||||||
touchDownFun = touchDownFun
|
touchDownFun = touchDownFun
|
||||||
)
|
)
|
||||||
@@ -202,12 +192,7 @@ class UIItemInventoryItemGrid(
|
|||||||
item = null,
|
item = null,
|
||||||
amount = UIItemInventoryElemWide.UNIQUE_ITEM_HAS_NO_AMOUNT,
|
amount = UIItemInventoryElemWide.UNIQUE_ITEM_HAS_NO_AMOUNT,
|
||||||
itemImage = null,
|
itemImage = null,
|
||||||
mouseoverBackCol = Color(CELLCOLOUR_BLACK_ACTIVE),
|
|
||||||
mouseoverBackBlendMode = BlendMode.SCREEN,
|
|
||||||
backCol = backColour,
|
|
||||||
backBlendMode = BlendMode.NORMAL,
|
|
||||||
drawBackOnNull = true,
|
drawBackOnNull = true,
|
||||||
inactiveTextCol = defaultTextColour,
|
|
||||||
keyDownFun = keyDownFun,
|
keyDownFun = keyDownFun,
|
||||||
touchDownFun = touchDownFun
|
touchDownFun = touchDownFun
|
||||||
)
|
)
|
||||||
@@ -228,7 +213,7 @@ class UIItemInventoryItemGrid(
|
|||||||
posX - LIST_TO_CONTROL_GAP - catBar.catIcons.tileW + 2
|
posX - LIST_TO_CONTROL_GAP - catBar.catIcons.tileW + 2
|
||||||
|
|
||||||
private fun getIconPosY(index: Int) =
|
private fun getIconPosY(index: Int) =
|
||||||
posY - 2 + (4 + UIItemInventoryElemWide.height - catBar.catIcons.tileH) * index
|
posY - 1 + (4 + UIItemInventoryElemWide.height - catBar.catIcons.tileH) * index
|
||||||
|
|
||||||
/** Long/compact mode buttons */
|
/** Long/compact mode buttons */
|
||||||
internal val gridModeButtons = Array<UIItemImageButton>(2) { index ->
|
internal val gridModeButtons = Array<UIItemImageButton>(2) { index ->
|
||||||
@@ -350,7 +335,7 @@ class UIItemInventoryItemGrid(
|
|||||||
batch.draw(
|
batch.draw(
|
||||||
walletFont.get(0, it - '0'),
|
walletFont.get(0, it - '0'),
|
||||||
gridModeButtons[0].posX.toFloat(), // scroll button size: 20px, font width: 20 px
|
gridModeButtons[0].posX.toFloat(), // scroll button size: 20px, font width: 20 px
|
||||||
gridModeButtons[0].posY + height - index * walletFont.tileH.toFloat()
|
gridModeButtons[0].posY + height - index * walletFont.tileH - 1f
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,115 +82,123 @@ object VDUtil {
|
|||||||
val entryModifyTime = inbytes.sliceArray64(entryOffset + 26..entryOffset + 31).toInt48Big()
|
val entryModifyTime = inbytes.sliceArray64(entryOffset + 26..entryOffset + 31).toInt48Big()
|
||||||
val entryCRC = inbytes.sliceArray64(entryOffset + 32..entryOffset + 35).toIntBig() // to check with completed entry
|
val entryCRC = inbytes.sliceArray64(entryOffset + 32..entryOffset + 35).toIntBig() // to check with completed entry
|
||||||
|
|
||||||
val entryData = when (entryTypeFlag and 127) {
|
try {
|
||||||
DiskEntry.NORMAL_FILE -> {
|
val entryData = when (entryTypeFlag and 127) {
|
||||||
val filesize = inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE..entryOffset + DiskEntry.HEADER_SIZE + 5).toInt48Big()
|
DiskEntry.NORMAL_FILE -> {
|
||||||
//println("[VDUtil] --> is file; filesize = $filesize")
|
val filesize = inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE..entryOffset + DiskEntry.HEADER_SIZE + 5).toInt48Big()
|
||||||
inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE + 6..entryOffset + DiskEntry.HEADER_SIZE + 5 + filesize)
|
//println("[VDUtil] --> is file; filesize = $filesize")
|
||||||
}
|
inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE + 6..entryOffset + DiskEntry.HEADER_SIZE + 5 + filesize)
|
||||||
DiskEntry.DIRECTORY -> {
|
|
||||||
val entryCount = inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE..entryOffset + DiskEntry.HEADER_SIZE + 3).toIntBig()
|
|
||||||
//println("[VDUtil] --> is directory; entryCount = $entryCount")
|
|
||||||
inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE + 4..entryOffset + DiskEntry.HEADER_SIZE + 3 + entryCount * 8)
|
|
||||||
}
|
|
||||||
DiskEntry.SYMLINK -> {
|
|
||||||
inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE..entryOffset + DiskEntry.HEADER_SIZE + 7)
|
|
||||||
}
|
|
||||||
else -> throw RuntimeException("Unknown entry with type $entryTypeFlag at entryOffset $entryOffset")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG_PRINT_READ) {
|
|
||||||
println("[savegame.VDUtil] == Entry deserialise debugprint for entry ID $entryID (child of $entryParentID)")
|
|
||||||
println("Entry type flag: ${entryTypeFlag and 127}${if (entryTypeFlag < 0) "*" else ""}")
|
|
||||||
println("Entry raw contents bytes: (len: ${entryData.size})")
|
|
||||||
entryData.forEachIndexed { i, it ->
|
|
||||||
if (i > 0 && i % 8 == 0L) print(" ")
|
|
||||||
else if (i > 0 && i % 4 == 0L) print("_")
|
|
||||||
print(it.toInt().toHex().substring(6))
|
|
||||||
}; println()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// update entryOffset so that we can fetch next entry in the binary
|
|
||||||
entryOffset += DiskEntry.HEADER_SIZE + entryData.size + when (entryTypeFlag and 127) {
|
|
||||||
DiskEntry.NORMAL_FILE -> 6 // PLEASE DO REFER TO Spec.md
|
|
||||||
DiskEntry.DIRECTORY -> 4 // PLEASE DO REFER TO Spec.md
|
|
||||||
DiskEntry.SYMLINK -> 0 // PLEASE DO REFER TO Spec.md
|
|
||||||
else -> throw RuntimeException("Unknown entry with type $entryTypeFlag")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// check for the discard bit
|
|
||||||
if (entryTypeFlag > 0) {
|
|
||||||
|
|
||||||
// create entry
|
|
||||||
val diskEntry = DiskEntry(
|
|
||||||
entryID = entryID,
|
|
||||||
parentEntryID = entryParentID,
|
|
||||||
creationDate = entryCreationTime,
|
|
||||||
modificationDate = entryModifyTime,
|
|
||||||
contents = if (entryTypeFlag == DiskEntry.NORMAL_FILE) {
|
|
||||||
EntryFile(entryData)
|
|
||||||
} else if (entryTypeFlag == DiskEntry.DIRECTORY) {
|
|
||||||
|
|
||||||
val entryList = ArrayList<EntryID>()
|
|
||||||
|
|
||||||
(0 until entryData.size / 8).forEach { cnt ->
|
|
||||||
entryList.add(entryData.sliceArray64(8 * cnt until 8 * (cnt+1)).toLongBig())
|
|
||||||
}
|
|
||||||
|
|
||||||
entryList.sort()
|
|
||||||
|
|
||||||
EntryDirectory(entryList)
|
|
||||||
} else if (entryTypeFlag == DiskEntry.SYMLINK) {
|
|
||||||
EntrySymlink(entryData.toLongBig())
|
|
||||||
} else
|
|
||||||
throw RuntimeException("Unknown entry with type $entryTypeFlag")
|
|
||||||
)
|
|
||||||
|
|
||||||
// check CRC of entry
|
|
||||||
if (crcWarnLevel == Level.SEVERE || crcWarnLevel == Level.WARNING) {
|
|
||||||
|
|
||||||
// test print
|
|
||||||
if (DEBUG_PRINT_READ) {
|
|
||||||
val testbytez = diskEntry.contents.serialize()
|
|
||||||
val testbytes = testbytez.array
|
|
||||||
(diskEntry.contents as? EntryDirectory)?.forEach {
|
|
||||||
println("entry: ${it.toHex()}")
|
|
||||||
}
|
|
||||||
println("[savegame.VDUtil] bytes to calculate crc against:")
|
|
||||||
testbytes.forEachIndexed { i, it ->
|
|
||||||
if (i % 4 == 0L) print(" ")
|
|
||||||
print(it.toInt().toHex().substring(6))
|
|
||||||
}
|
|
||||||
println("\nCRC: " + testbytez.getCRC32().toHex())
|
|
||||||
}
|
}
|
||||||
// end of test print
|
DiskEntry.DIRECTORY -> {
|
||||||
|
val entryCount = inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE..entryOffset + DiskEntry.HEADER_SIZE + 3).toIntBig()
|
||||||
val calculatedCRC = diskEntry.contents.serialize().getCRC32()
|
//println("[VDUtil] --> is directory; entryCount = $entryCount")
|
||||||
|
inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE + 4..entryOffset + DiskEntry.HEADER_SIZE + 3 + entryCount * 8)
|
||||||
val crcMsg =
|
|
||||||
"CRC failed: stored value is ${entryCRC.toHex()}, but calculated value is ${calculatedCRC.toHex()}\n" +
|
|
||||||
"at file \"${diskIDtoReadableFilename(diskEntry.entryID)}\" (entry ID ${diskEntry.entryID})"
|
|
||||||
|
|
||||||
if (calculatedCRC != entryCRC) {
|
|
||||||
|
|
||||||
println("[savegame.VDUtil] CRC failed; entry info:\n$diskEntry")
|
|
||||||
|
|
||||||
if (crcWarnLevel == Level.SEVERE)
|
|
||||||
throw IOException(crcMsg)
|
|
||||||
else if (warningFunc != null)
|
|
||||||
warningFunc(crcMsg)
|
|
||||||
}
|
}
|
||||||
|
DiskEntry.SYMLINK -> {
|
||||||
|
inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE..entryOffset + DiskEntry.HEADER_SIZE + 7)
|
||||||
|
}
|
||||||
|
else -> throw RuntimeException("Unknown entry with type $entryTypeFlag at entryOffset $entryOffset")
|
||||||
}
|
}
|
||||||
|
|
||||||
// add entry to disk
|
|
||||||
vdisk.entries[entryID] = diskEntry
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (DEBUG_PRINT_READ) {
|
if (DEBUG_PRINT_READ) {
|
||||||
println("[savegame.VDUtil] Discarding entry ${entryID.toHex()} (raw type flag: $entryTypeFlag)")
|
println("[savegame.VDUtil] == Entry deserialise debugprint for entry ID $entryID (child of $entryParentID)")
|
||||||
|
println("Entry type flag: ${entryTypeFlag and 127}${if (entryTypeFlag < 0) "*" else ""}")
|
||||||
|
println("Entry raw contents bytes: (len: ${entryData.size})")
|
||||||
|
entryData.forEachIndexed { i, it ->
|
||||||
|
if (i > 0 && i % 8 == 0L) print(" ")
|
||||||
|
else if (i > 0 && i % 4 == 0L) print("_")
|
||||||
|
print(it.toInt().toHex().substring(6))
|
||||||
|
}; println()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// update entryOffset so that we can fetch next entry in the binary
|
||||||
|
entryOffset += DiskEntry.HEADER_SIZE + entryData.size + when (entryTypeFlag and 127) {
|
||||||
|
DiskEntry.NORMAL_FILE -> 6 // PLEASE DO REFER TO Spec.md
|
||||||
|
DiskEntry.DIRECTORY -> 4 // PLEASE DO REFER TO Spec.md
|
||||||
|
DiskEntry.SYMLINK -> 0 // PLEASE DO REFER TO Spec.md
|
||||||
|
else -> throw RuntimeException("Unknown entry with type $entryTypeFlag")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// check for the discard bit
|
||||||
|
if (entryTypeFlag > 0) {
|
||||||
|
|
||||||
|
// create entry
|
||||||
|
val diskEntry = DiskEntry(
|
||||||
|
entryID = entryID,
|
||||||
|
parentEntryID = entryParentID,
|
||||||
|
creationDate = entryCreationTime,
|
||||||
|
modificationDate = entryModifyTime,
|
||||||
|
contents = if (entryTypeFlag == DiskEntry.NORMAL_FILE) {
|
||||||
|
EntryFile(entryData)
|
||||||
|
} else if (entryTypeFlag == DiskEntry.DIRECTORY) {
|
||||||
|
|
||||||
|
val entryList = ArrayList<EntryID>()
|
||||||
|
|
||||||
|
(0 until entryData.size / 8).forEach { cnt ->
|
||||||
|
entryList.add(entryData.sliceArray64(8 * cnt until 8 * (cnt+1)).toLongBig())
|
||||||
|
}
|
||||||
|
|
||||||
|
entryList.sort()
|
||||||
|
|
||||||
|
EntryDirectory(entryList)
|
||||||
|
} else if (entryTypeFlag == DiskEntry.SYMLINK) {
|
||||||
|
EntrySymlink(entryData.toLongBig())
|
||||||
|
} else
|
||||||
|
throw RuntimeException("Unknown entry with type $entryTypeFlag")
|
||||||
|
)
|
||||||
|
|
||||||
|
// check CRC of entry
|
||||||
|
if (crcWarnLevel == Level.SEVERE || crcWarnLevel == Level.WARNING) {
|
||||||
|
|
||||||
|
// test print
|
||||||
|
if (DEBUG_PRINT_READ) {
|
||||||
|
val testbytez = diskEntry.contents.serialize()
|
||||||
|
val testbytes = testbytez.array
|
||||||
|
(diskEntry.contents as? EntryDirectory)?.forEach {
|
||||||
|
println("entry: ${it.toHex()}")
|
||||||
|
}
|
||||||
|
println("[savegame.VDUtil] bytes to calculate crc against:")
|
||||||
|
testbytes.forEachIndexed { i, it ->
|
||||||
|
if (i % 4 == 0L) print(" ")
|
||||||
|
print(it.toInt().toHex().substring(6))
|
||||||
|
}
|
||||||
|
println("\nCRC: " + testbytez.getCRC32().toHex())
|
||||||
|
}
|
||||||
|
// end of test print
|
||||||
|
|
||||||
|
val calculatedCRC = diskEntry.contents.serialize().getCRC32()
|
||||||
|
|
||||||
|
val crcMsg =
|
||||||
|
"CRC failed: stored value is ${entryCRC.toHex()}, but calculated value is ${calculatedCRC.toHex()}\n" +
|
||||||
|
"at file \"${diskIDtoReadableFilename(diskEntry.entryID)}\" (entry ID ${diskEntry.entryID})"
|
||||||
|
|
||||||
|
if (calculatedCRC != entryCRC) {
|
||||||
|
|
||||||
|
println("[savegame.VDUtil] CRC failed; entry info:\n$diskEntry")
|
||||||
|
|
||||||
|
if (crcWarnLevel == Level.SEVERE)
|
||||||
|
throw IOException(crcMsg)
|
||||||
|
else if (warningFunc != null)
|
||||||
|
warningFunc(crcMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add entry to disk
|
||||||
|
vdisk.entries[entryID] = diskEntry
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (DEBUG_PRINT_READ) {
|
||||||
|
println("[savegame.VDUtil] Discarding entry ${entryID.toHex()} (raw type flag: $entryTypeFlag)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e: ArrayIndexOutOfBoundsException) {
|
||||||
|
System.err.println("An error occurred while reading a file (entryID: $entryID (${diskIDtoReadableFilename(entryID)}), typeFlag: $entryTypeFlag)")
|
||||||
|
System.err.println("Stack trace:")
|
||||||
|
e.printStackTrace()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import net.torvald.terrarum.realestate.LandUtil
|
|||||||
import net.torvald.terrarum.savegame.*
|
import net.torvald.terrarum.savegame.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
|
import java.util.logging.Level
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It's your responsibility to create a new VirtualDisk if your save is new, and create a backup for modifying existing save.
|
* It's your responsibility to create a new VirtualDisk if your save is new, and create a backup for modifying existing save.
|
||||||
@@ -152,12 +153,14 @@ object LoadSavegame {
|
|||||||
world.layerWall = BlockLayer(world.width, world.height)
|
world.layerWall = BlockLayer(world.width, world.height)
|
||||||
|
|
||||||
newIngame.world = world // must be set before the loadscreen, otherwise the loadscreen will try to read from the NullWorld which is already destroyed
|
newIngame.world = world // must be set before the loadscreen, otherwise the loadscreen will try to read from the NullWorld which is already destroyed
|
||||||
newIngame.worldDisk = worldDisk.sync()
|
newIngame.worldDisk = VDUtil.readDiskArchive(worldDisk.diskFile, Level.INFO)
|
||||||
newIngame.playerDisk = playerDisk.sync()
|
newIngame.playerDisk = VDUtil.readDiskArchive(playerDisk.diskFile, Level.INFO)
|
||||||
newIngame.savegameNickname = getSavegameNickname(worldDisk)
|
newIngame.savegameNickname = getSavegameNickname(worldDisk)
|
||||||
newIngame.worldSavefileName = getWorldSavefileName(newIngame.savegameNickname, world)
|
newIngame.worldSavefileName = getWorldSavefileName(newIngame.savegameNickname, world)
|
||||||
newIngame.playerSavefileName = getPlayerSavefileName(player)
|
newIngame.playerSavefileName = getPlayerSavefileName(player)
|
||||||
|
|
||||||
|
worldDisk.dispose()
|
||||||
|
playerDisk.dispose()
|
||||||
|
|
||||||
val loadJob = { it: LoadScreenBase ->
|
val loadJob = { it: LoadScreenBase ->
|
||||||
val loadscreen = it as ChunkLoadingLoadScreen
|
val loadscreen = it as ChunkLoadingLoadScreen
|
||||||
@@ -165,7 +168,7 @@ object LoadSavegame {
|
|||||||
|
|
||||||
|
|
||||||
val actors = world.actors.distinct()
|
val actors = world.actors.distinct()
|
||||||
val worldParam = TerrarumIngame.Codices(worldDisk, world, actors, player)
|
val worldParam = TerrarumIngame.Codices(newIngame.worldDisk, world, actors, player)
|
||||||
|
|
||||||
|
|
||||||
newIngame.gameLoadInfoPayload = worldParam
|
newIngame.gameLoadInfoPayload = worldParam
|
||||||
@@ -181,7 +184,7 @@ object LoadSavegame {
|
|||||||
for (layer in worldLayer.indices) {
|
for (layer in worldLayer.indices) {
|
||||||
loadscreen.addMessage("${Lang["MENU_IO_LOADING"]} ${chunk*worldLayer.size+layer+1}/${chunkCount*2}")
|
loadscreen.addMessage("${Lang["MENU_IO_LOADING"]} ${chunk*worldLayer.size+layer+1}/${chunkCount*2}")
|
||||||
|
|
||||||
val chunkFile = worldDisk.getFile(0x1_0000_0000L or layer.toLong().shl(24) or chunk)!!
|
val chunkFile = newIngame.worldDisk.getFile(0x1_0000_0000L or layer.toLong().shl(24) or chunk)!!
|
||||||
val chunkXY = LandUtil.chunkNumToChunkXY(world, chunk.toInt())
|
val chunkXY = LandUtil.chunkNumToChunkXY(world, chunk.toInt())
|
||||||
|
|
||||||
ReadWorld.decodeChunkToLayer(chunkFile.getContent(), worldLayer[layer]!!, chunkXY.x, chunkXY.y)
|
ReadWorld.decodeChunkToLayer(chunkFile.getContent(), worldLayer[layer]!!, chunkXY.x, chunkXY.y)
|
||||||
@@ -192,11 +195,10 @@ object LoadSavegame {
|
|||||||
world.renumberTilesAfterLoad()
|
world.renumberTilesAfterLoad()
|
||||||
|
|
||||||
|
|
||||||
Echo("${ccW}World loaded: $ccY${worldDisk.getDiskName(Common.CHARSET)}")
|
Echo("${ccW}World loaded: $ccY${newIngame.worldDisk.getDiskName(Common.CHARSET)}")
|
||||||
printdbg(this, "World loaded: ${worldDisk.getDiskName(Common.CHARSET)}")
|
printdbg(this, "World loaded: ${newIngame.worldDisk.getDiskName(Common.CHARSET)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val loadScreen = ChunkLoadingLoadScreen(newIngame, world.width, world.height, loadJob)
|
val loadScreen = ChunkLoadingLoadScreen(newIngame, world.width, world.height, loadJob)
|
||||||
Terrarum.setCurrentIngameInstance(newIngame)
|
Terrarum.setCurrentIngameInstance(newIngame)
|
||||||
App.setLoadScreen(loadScreen)
|
App.setLoadScreen(loadScreen)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.lwjgl.opengl.GL20
|
|||||||
object Toolkit : Disposable {
|
object Toolkit : Disposable {
|
||||||
|
|
||||||
object Theme {
|
object Theme {
|
||||||
val COL_INVENTORY_CELL_BORDER = Color(1f, 1f, 1f, 0.2f)
|
val COL_INVENTORY_CELL_BORDER = Color(1f, 1f, 1f, 0.25f)
|
||||||
val COL_CELL_FILL = Color(0x28282888)
|
val COL_CELL_FILL = Color(0x28282888)
|
||||||
|
|
||||||
val COL_LIST_DEFAULT = Color.WHITE
|
val COL_LIST_DEFAULT = Color.WHITE
|
||||||
|
|||||||
@@ -105,7 +105,9 @@ abstract class UICanvas(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** A function that is run ONCE when the UI is requested to be opened; will work identical to [endOpening] if [openCloseTime] is zero */
|
||||||
open fun show() {}
|
open fun show() {}
|
||||||
|
/** A function that is run ONCE when the UI is requested to be closed; will work identical to [endClosing] if [openCloseTime] is zero */
|
||||||
open fun hide() {}
|
open fun hide() {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user