diff --git a/src/net/torvald/terrarum/IngameInstance.kt b/src/net/torvald/terrarum/IngameInstance.kt index b8a5fe887..c28f501f9 100644 --- a/src/net/torvald/terrarum/IngameInstance.kt +++ b/src/net/torvald/terrarum/IngameInstance.kt @@ -23,6 +23,7 @@ import org.khelekore.prtree.* import java.io.File import java.io.FileInputStream import java.io.FileNotFoundException +import java.io.IOException import java.util.* 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` */ 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 { // 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 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) } catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {} try { - // do not overwrite clean .2 with dirty .1 - val file2 = File("${file.absolutePath}.2") - val file1 = File("${file.absolutePath}.1") - 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 } - if (!(flags2 == 0 && flags1 != 0) || !file2.exists()) file1.copyTo(file2, true) - } catch (e: NoSuchFileException) {} catch (e: FileNotFoundException) {} - try { - file.copyTo( - File("${file.absolutePath}.1"), // don't use .bak as it's used by the savecracker - true - ) - } catch (e: NoSuchFileException) {} + if (file2.exists() && !file3.exists()) + file2.copyTo(file3, true) + if (file1.exists() && !file2.exists()) + file1.copyTo(file2, true) + + file.copyTo(file1, true) + } catch (e: IOException) {} } diff --git a/src/net/torvald/terrarum/LoadScreenBase.kt b/src/net/torvald/terrarum/LoadScreenBase.kt index a06947ec5..9c5e604b1 100644 --- a/src/net/torvald/terrarum/LoadScreenBase.kt +++ b/src/net/torvald/terrarum/LoadScreenBase.kt @@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.ScreenAdapter import com.badlogic.gdx.graphics.OrthographicCamera import com.badlogic.gdx.utils.Disposable +import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.util.CircularArray @@ -38,7 +39,7 @@ open class LoadScreenBase : ScreenAdapter(), Disposable { screenToLoad!!.show() } catch (e: Exception) { - addMessage("$ccR$e") + addMessage("$ccR${Lang["ERROR_SAVE_CORRUPTED"].replace(".","")}: $e") errorTrapped = true System.err.println("Error while loading:") diff --git a/src/net/torvald/terrarum/UIItemInventoryElemSimple.kt b/src/net/torvald/terrarum/UIItemInventoryElemSimple.kt index f4f99170d..14108aab8 100644 --- a/src/net/torvald/terrarum/UIItemInventoryElemSimple.kt +++ b/src/net/torvald/terrarum/UIItemInventoryElemSimple.kt @@ -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.toItemCountText import net.torvald.terrarum.ui.Toolkit -import net.torvald.terrarum.ui.Toolkit.Theme.COL_INVENTORY_CELL_BORDER import net.torvald.terrarum.ui.UICanvas import kotlin.math.roundToInt @@ -23,13 +22,6 @@ class UIItemInventoryElemSimple( override var item: GameItem?, override var amount: Int, 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 equippedSlot: Int? = null, val drawBackOnNull: Boolean = true, @@ -54,22 +46,17 @@ class UIItemInventoryElemSimple( } override fun render(batch: SpriteBatch, camera: Camera) { - // mouseover background + blendNormal(batch) + + // cell background if (item != null || drawBackOnNull) { - // do not highlight even if drawBackOnNull is true - 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 - } + batch.color = Toolkit.Theme.COL_CELL_FILL Toolkit.fillArea(batch, posX, posY, width, height) } - batch.color = COL_INVENTORY_CELL_BORDER - //blendNormal(batch) + // cell border + 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) @@ -77,15 +64,11 @@ class UIItemInventoryElemSimple( // and you can clearly see the quickslot UI anyway if (item != null && itemImage != null) { - blendNormal(batch) // item image batch.color = Color.WHITE 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 @@ -108,11 +91,13 @@ class UIItemInventoryElemSimple( else if (item!!.stackable) { val amountString = amount.toItemCountText() + // if mouse is over, text lights up // highlight item count (blocks/walls) if the item is equipped - if (equippedSlot != null) { - batch.color = highlightCol - } - + batch.color = item!!.nameColour mul ( + if (equippedSlot != null) Toolkit.Theme.COL_HIGHLIGHT + else if (mouseUp) Toolkit.Theme.COL_ACTIVE + else Color.WHITE + ) App.fontSmallNumbers.draw(batch, amountString, diff --git a/src/net/torvald/terrarum/UIItemInventoryElemWide.kt b/src/net/torvald/terrarum/UIItemInventoryElemWide.kt index 5af1ff78d..a42a9b2af 100644 --- a/src/net/torvald/terrarum/UIItemInventoryElemWide.kt +++ b/src/net/torvald/terrarum/UIItemInventoryElemWide.kt @@ -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.toItemCountText import net.torvald.terrarum.ui.Toolkit -import net.torvald.terrarum.ui.Toolkit.Theme.COL_INVENTORY_CELL_BORDER import net.torvald.terrarum.ui.UICanvas import kotlin.math.roundToInt @@ -27,12 +26,6 @@ class UIItemInventoryElemWide( override var item: GameItem?, override var amount: Int, 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 equippedSlot: Int? = null, val drawBackOnNull: Boolean = true, @@ -72,23 +65,17 @@ class UIItemInventoryElemWide( private val fwsp = 0x3000.toChar() override fun render(batch: SpriteBatch, camera: Camera) { + blendNormal(batch) - // mouseover background + // cell background if (item != null || drawBackOnNull) { - // do not highlight even if drawBackOnNull is true - if (mouseUp && item != null) { - BlendMode.resolve(mouseoverBackBlendMode, batch) - batch.color = mouseoverBackCol - } - // if drawBackOnNull, just draw background - else { - BlendMode.resolve(backBlendMode, batch) - batch.color = backCol - } + batch.color = Toolkit.Theme.COL_CELL_FILL Toolkit.fillArea(batch, posX, posY, width, height) } - batch.color = COL_INVENTORY_CELL_BORDER - //blendNormal(batch) + // cell border + 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) @@ -102,8 +89,13 @@ class UIItemInventoryElemWide( 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 + // highlight item name and count (blocks/walls) if the item is equipped + 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 if (INVEN_DEBUG_MODE) { App.fontGame.draw(batch, diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index 87d957a85..b432de9e8 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -34,6 +34,7 @@ import net.torvald.terrarum.modulebasegame.worldgenerator.WorldgenParams import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.savegame.DiskSkimmer import net.torvald.terrarum.savegame.VDUtil +import net.torvald.terrarum.savegame.VirtualDisk import net.torvald.terrarum.serialise.Common import net.torvald.terrarum.serialise.LoadSavegame import net.torvald.terrarum.serialise.ReadActor @@ -259,7 +260,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { } data class Codices( - val disk: DiskSkimmer, // WORLD disk + val disk: VirtualDisk, // WORLD disk val world: GameWorld, // val meta: WriteMeta.WorldMeta, // val block: BlockCodex, @@ -349,7 +350,9 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { actorNowPlaying = 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() { diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt index 87ced083e..69858d9b5 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt @@ -43,21 +43,21 @@ open class FixtureInventory() { } 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 if (count == 0) - throw IllegalArgumentException("Item count is zero.") + throw IllegalArgumentException("[${this.javaClass.canonicalName}] Item count is zero.") if (count < 0) 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.") 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.") - if (((Terrarum.ingame as? TerrarumIngame)?.gameFullyLoaded ?: false) && + throw IllegalArgumentException("[${this.javaClass.canonicalName}] Attempted to put human player into the inventory.") + if (((Terrarum.ingame as? TerrarumIngame)?.gameFullyLoaded == true) && (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) - 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") if (count == 0) - throw IllegalArgumentException("Item count is zero.") + throw IllegalArgumentException("[${this.javaClass.canonicalName}] Item count is zero.") 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.") @@ -101,7 +101,7 @@ open class FixtureInventory() { val newCount = existingItem.qty - count 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) { // decrement count @@ -115,7 +115,7 @@ open class FixtureInventory() { } } 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.") } } diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureStorageChest.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureStorageChest.kt index 473576dc5..dbac0dd6b 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureStorageChest.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureStorageChest.kt @@ -103,7 +103,73 @@ internal class UIStorageChest : UICanvas( 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() { itemListChest.rebuild(catBar.catIconsMeaning[catBar.selectedIcon]) @@ -129,72 +195,19 @@ internal class UIStorageChest : UICanvas( itemListUpdate() } - override fun updateUI(delta: Float) { - if (!initialised) { - initialised = true - - 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) + override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean { + if (!openingClickLatched) { + return super.touchDown(screenX, screenY, pointer, button) } + return false + } - - + override fun updateUI(delta: Float) { catBar.update(delta) itemListChest.update(delta) itemListPlayer.update(delta) + + if (openingClickLatched && !Terrarum.mouseDown) openingClickLatched = false } override fun renderUI(batch: SpriteBatch, camera: Camera) { diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryEscMenu.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryEscMenu.kt index 22093da97..10a1c6361 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryEscMenu.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIInventoryEscMenu.kt @@ -212,6 +212,7 @@ class UIInventoryEscMenu(val full: UIInventoryFull) : UICanvas() { } override fun endOpening(delta: Float) { + INGAME.setTooltipMessage(null) } override fun endClosing(delta: Float) { diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIItemInventoryEquippedView.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIItemInventoryEquippedView.kt index cc691734f..d28350d75 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIItemInventoryEquippedView.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIItemInventoryEquippedView.kt @@ -5,13 +5,10 @@ import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.terrarum.* import net.torvald.terrarum.gameitem.GameItem -import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK_ACTIVE -import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELL_COL import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.itemListHeight import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.createInvCellGenericKeyDownFun import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.createInvCellGenericTouchDownFun 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.UIItem @@ -32,7 +29,7 @@ class UIItemInventoryEquippedView( companion object { val WIDTH = 2 * UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap //val HEIGHT = UIItemInventoryDynamicList.HEIGHT - val SPRITE_DRAW_COL = Color(0xddddddff.toInt()) + val SPRITE_DRAW_COL = Color(0xf2f2f2ff.toInt()) } private val listGap = 8 @@ -42,8 +39,6 @@ class UIItemInventoryEquippedView( lateinit var inventorySortList: Array private var rebuildList = true - - val spriteViewBackCol: Color = CELL_COL private val equipPosIcon = CommonResourcePool.getAsTextureRegionPack("inventory_category") private val cellToIcon = intArrayOf(0,1,2,3,4,5,6,7,6,7,6,7) @@ -57,10 +52,6 @@ class UIItemInventoryEquippedView( item = null, amount = UIItemInventoryElemWide.UNIQUE_ITEM_HAS_NO_AMOUNT, itemImage = null, - mouseoverBackCol = Color(CELLCOLOUR_BLACK_ACTIVE), - mouseoverBackBlendMode = BlendMode.SCREEN, - backCol = CELL_COL, - backBlendMode = BlendMode.NORMAL, drawBackOnNull = true, keyDownFun = createInvCellGenericKeyDownFun(), 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) { + blendNormal(batch) + val posXDelta = posX - oldPosX itemGrid.forEach { it.posX += posXDelta } - - - // sprite background - blendNormal(batch) - batch.color = spriteViewBackCol + // sprite cell background + batch.color = Toolkit.Theme.COL_CELL_FILL 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) diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIItemInventoryItemGrid.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIItemInventoryItemGrid.kt index 77934a6ed..8e43251b5 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIItemInventoryItemGrid.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIItemInventoryItemGrid.kt @@ -55,8 +55,6 @@ class UIItemInventoryItemGrid( override val width = horizontalCells * UIItemInventoryElemSimple.height + (horizontalCells - 1) * listGap override val height = verticalCells * UIItemInventoryElemSimple.height + (verticalCells - 1) * listGap - val backColour = CELL_COL - init { CommonResourcePool.addToLoadingList("inventory_walletnumberfont") { TextureRegionPack("./assets/graphics/fonts/inventory_wallet_numbers.tga", 20, 9) @@ -92,13 +90,10 @@ class UIItemInventoryItemGrid( var inventorySortList = ArrayList() private var rebuildList = true - val defaultTextColour = Color(0xeaeaea_ff.toInt()) - private val walletFont = TextureRegionPack("./assets/graphics/fonts/inventory_wallet_numbers.tga", 20, 9) private var walletText = "" - companion object { const val listGap = 8 const val LIST_TO_CONTROL_GAP = 12 @@ -179,12 +174,7 @@ class UIItemInventoryItemGrid( item = null, amount = UIItemInventoryElemWide.UNIQUE_ITEM_HAS_NO_AMOUNT, itemImage = null, - mouseoverBackCol = Color(CELLCOLOUR_BLACK_ACTIVE), - mouseoverBackBlendMode = BlendMode.SCREEN, - backCol = backColour, - backBlendMode = BlendMode.NORMAL, drawBackOnNull = true, - inactiveTextCol = defaultTextColour, keyDownFun = keyDownFun, touchDownFun = touchDownFun ) @@ -202,12 +192,7 @@ class UIItemInventoryItemGrid( item = null, amount = UIItemInventoryElemWide.UNIQUE_ITEM_HAS_NO_AMOUNT, itemImage = null, - mouseoverBackCol = Color(CELLCOLOUR_BLACK_ACTIVE), - mouseoverBackBlendMode = BlendMode.SCREEN, - backCol = backColour, - backBlendMode = BlendMode.NORMAL, drawBackOnNull = true, - inactiveTextCol = defaultTextColour, keyDownFun = keyDownFun, touchDownFun = touchDownFun ) @@ -228,7 +213,7 @@ class UIItemInventoryItemGrid( posX - LIST_TO_CONTROL_GAP - catBar.catIcons.tileW + 2 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 */ internal val gridModeButtons = Array(2) { index -> @@ -350,7 +335,7 @@ class UIItemInventoryItemGrid( batch.draw( walletFont.get(0, it - '0'), 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 ) } } diff --git a/src/net/torvald/terrarum/savegame/VDUtil.kt b/src/net/torvald/terrarum/savegame/VDUtil.kt index 045f41eb7..cdc3e0c90 100644 --- a/src/net/torvald/terrarum/savegame/VDUtil.kt +++ b/src/net/torvald/terrarum/savegame/VDUtil.kt @@ -82,115 +82,123 @@ object VDUtil { val entryModifyTime = inbytes.sliceArray64(entryOffset + 26..entryOffset + 31).toInt48Big() val entryCRC = inbytes.sliceArray64(entryOffset + 32..entryOffset + 35).toIntBig() // to check with completed entry - val entryData = when (entryTypeFlag and 127) { - DiskEntry.NORMAL_FILE -> { - val filesize = inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE..entryOffset + DiskEntry.HEADER_SIZE + 5).toInt48Big() - //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() - - (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()) + try { + val entryData = when (entryTypeFlag and 127) { + DiskEntry.NORMAL_FILE -> { + val filesize = inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE..entryOffset + DiskEntry.HEADER_SIZE + 5).toInt48Big() + //println("[VDUtil] --> is file; filesize = $filesize") + inbytes.sliceArray64(entryOffset + DiskEntry.HEADER_SIZE + 6..entryOffset + DiskEntry.HEADER_SIZE + 5 + filesize) } - // 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) + 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") } - // add entry to disk - vdisk.entries[entryID] = diskEntry - } - else { 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() + + (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 } } diff --git a/src/net/torvald/terrarum/serialise/WriteSavegame.kt b/src/net/torvald/terrarum/serialise/WriteSavegame.kt index 9a44b902e..1aaf1906e 100644 --- a/src/net/torvald/terrarum/serialise/WriteSavegame.kt +++ b/src/net/torvald/terrarum/serialise/WriteSavegame.kt @@ -16,6 +16,7 @@ import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.savegame.* import java.io.File 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. @@ -152,12 +153,14 @@ object LoadSavegame { 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.worldDisk = worldDisk.sync() - newIngame.playerDisk = playerDisk.sync() + newIngame.worldDisk = VDUtil.readDiskArchive(worldDisk.diskFile, Level.INFO) + newIngame.playerDisk = VDUtil.readDiskArchive(playerDisk.diskFile, Level.INFO) newIngame.savegameNickname = getSavegameNickname(worldDisk) newIngame.worldSavefileName = getWorldSavefileName(newIngame.savegameNickname, world) newIngame.playerSavefileName = getPlayerSavefileName(player) + worldDisk.dispose() + playerDisk.dispose() val loadJob = { it: LoadScreenBase -> val loadscreen = it as ChunkLoadingLoadScreen @@ -165,7 +168,7 @@ object LoadSavegame { 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 @@ -181,7 +184,7 @@ object LoadSavegame { for (layer in worldLayer.indices) { 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()) ReadWorld.decodeChunkToLayer(chunkFile.getContent(), worldLayer[layer]!!, chunkXY.x, chunkXY.y) @@ -192,11 +195,10 @@ object LoadSavegame { world.renumberTilesAfterLoad() - Echo("${ccW}World loaded: $ccY${worldDisk.getDiskName(Common.CHARSET)}") - printdbg(this, "World loaded: ${worldDisk.getDiskName(Common.CHARSET)}") + Echo("${ccW}World loaded: $ccY${newIngame.worldDisk.getDiskName(Common.CHARSET)}") + printdbg(this, "World loaded: ${newIngame.worldDisk.getDiskName(Common.CHARSET)}") } - val loadScreen = ChunkLoadingLoadScreen(newIngame, world.width, world.height, loadJob) Terrarum.setCurrentIngameInstance(newIngame) App.setLoadScreen(loadScreen) diff --git a/src/net/torvald/terrarum/ui/Toolkit.kt b/src/net/torvald/terrarum/ui/Toolkit.kt index f218f2290..f68807059 100644 --- a/src/net/torvald/terrarum/ui/Toolkit.kt +++ b/src/net/torvald/terrarum/ui/Toolkit.kt @@ -23,7 +23,7 @@ import org.lwjgl.opengl.GL20 object Toolkit : Disposable { 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_LIST_DEFAULT = Color.WHITE diff --git a/src/net/torvald/terrarum/ui/UICanvas.kt b/src/net/torvald/terrarum/ui/UICanvas.kt index bc12cf8c1..f1b5a38dc 100644 --- a/src/net/torvald/terrarum/ui/UICanvas.kt +++ b/src/net/torvald/terrarum/ui/UICanvas.kt @@ -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() {} + /** 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() {}