diff --git a/REFERENCING.md b/REFERENCING.md index f1b29dfcc..8a4369819 100644 --- a/REFERENCING.md +++ b/REFERENCING.md @@ -1,7 +1,9 @@ |Range|Description| |-----|-----------| |0..4095|Tiles| -|4096..32767|Items (static)| +|4096..8191|Walls| +|8192..8447|Wires| +|8448..32767|Items (static)| |32768..1048575|Items (dynamic\*)| |1048576..0x7FFF_FFFF|Actors| |0x8000_0000..0xFFFF_FFFF (all negative numbers)|Faction| diff --git a/assets/locales/en/tiles.json b/assets/locales/en/tiles.json index ddfc515a3..e603fd9a1 100644 --- a/assets/locales/en/tiles.json +++ b/assets/locales/en/tiles.json @@ -26,10 +26,15 @@ "TILE_SAND": "Sand", "TILE_SAND_PLURAL": "Sands", "TILE_SAND_WHITE": "White sand", + "TILE_SAND_WHITE_PLURAL": "White sands", "TILE_SAND_RED": "Red sand", + "TILE_SAND_RED_PLURAL": "Red sands", "TILE_SAND_DESERT": "Sand", + "TILE_SAND_DESERT_PLURAL": "Sands", "TILE_SAND_BLACK": "Black sand", + "TILE_SAND_BLACK_PLURAL": "Black sands", "TILE_SAND_GREEN": "Green sand", + "TILE_SAND_GREEN_PLURAL": "Green sands", "TILE_GRAVEL": "Gravel", "TILE_GRAVEL_PLURAL": "Gravels", "TILE_ORE_MALACHITE": "Malachite", @@ -77,11 +82,17 @@ "TILE_TORCH": "Torch", "TILE_TORCH_PLURAL": "Torches", "TILE_SANDSTONE": "Sandstone", + "TILE_SANDSTONE_PLURAL": "Sandstones", "TILE_SANDSTONE_WHITE": "White sandstone", + "TILE_SANDSTONE_WHITE_PLURAL": "White sandstones", "TILE_SANDSTONE_RED": "Red sandstone", + "TILE_SANDSTONE_RED_PLURAL": "Red sandstones", "TILE_SANDSTONE_DESERT": "Sandstone", + "TILE_SANDSTONE_DESERT_PLURAL": "Sandstones", "TILE_SANDSTONE_BLACK": "Black sandstone", + "TILE_SANDSTONE_BLACK_PLURAL": "Black sandstones", "TILE_SANDSTONE_GREEN": "Green sandstone", + "TILE_SANDSTONE_GREEN_PLURAL": "Green sandstones", "TILE_WATER": "Water", "TILE_WATER_PLURAL": "Waters", "TILE_LAVA": "Lava", diff --git a/assets/locales/koKR/tiles.json b/assets/locales/koKR/tiles.json index 45fcfbea9..9cd5c0dfb 100644 --- a/assets/locales/koKR/tiles.json +++ b/assets/locales/koKR/tiles.json @@ -7,22 +7,22 @@ "TILE_GRAS_PLURALS": "잔디", "TILE_PLANK_NORMAL": "나무판자", "TILE_PLANK_NORMAL_PLURAL": "나무판자", - "TILE_PLANK_EBONY": "흑단", - "TILE_PLANK_EBONY_PLURAL": "흑단", - "TILE_PLANK_BIRCH": "백단", - "TILE_PLANK_BIRCH_PLURAL": "백단", - "TILE_PLANK_BLOODROSE": "자단", - "TILE_PLANK_BLOODROSE_PLURAL": "자단", + "TILE_PLANK_EBONY": "검정 나무판자", + "TILE_PLANK_EBONY_PLURAL": "검정 나무판자", + "TILE_PLANK_BIRCH": "하양 나무판자", + "TILE_PLANK_BIRCH_PLURAL": "하양 나무판자", + "TILE_PLANK_BLOODROSE": "빨강 나무판자", + "TILE_PLANK_BLOODROSE_PLURAL": "빨강 나무판자", "TILE_TRUNK_NORMAL": "통나무", "TILE_TRUNK_NORMAL_PLURAL": "통나무", "TILE_TRUNK_EBONY": "흑단나무", "TILE_TRUNK_EBONY_PLURAL": "흑단나무", - "TILE_TRUNK_BIRCH": "백단나무", - "TILE_TRUNK_BIRCH_PLURAL": "백단나무", + "TILE_TRUNK_BIRCH": "자작나무", + "TILE_TRUNK_BIRCH_PLURAL": "자작나무", "TILE_TRUNK_BLOODROSE": "자단나무", "TILE_TRUNK_BLOODROSE_PLURAL": "자단나무", - "TILE_STONE_QUARRIED": "캔 돌", - "TILE_STONE_QUARRIED_PLURAL": "캔 돌", + "TILE_STONE_QUARRIED": "석재", + "TILE_STONE_QUARRIED_PLURAL": "석재", "TILE_SAND": "모래", "TILE_SAND_PLURAL": "모래", "TILE_GRAVEL": "자갈", diff --git a/src/net/torvald/serialise/WriteGameMapData.kt b/src/net/torvald/serialise/WriteGameMapData.kt index aef54ef5b..8d8d32194 100644 --- a/src/net/torvald/serialise/WriteGameMapData.kt +++ b/src/net/torvald/serialise/WriteGameMapData.kt @@ -43,9 +43,9 @@ object WriteGameMapData { { b -> Files.write(tempPath, byteArrayOf(b)) }) map.layerWall.forEach( { b -> Files.write(tempPath, byteArrayOf(b)) }) - map.terrainDamage.forEach( + map.layerTerrainLowBits.forEach( { b -> Files.write(tempPath, byteArrayOf(b)) }) - map.wallDamage.forEach( + map.layerWallLowBits.forEach( { b -> Files.write(tempPath, byteArrayOf(b)) }) map.layerWire.forEach( { b -> Files.write(tempPath, byteArrayOf(b)) }) diff --git a/src/net/torvald/terrarum/KVHashMap.kt b/src/net/torvald/terrarum/KVHashMap.kt index 99d5069a5..6a8dc6c1f 100644 --- a/src/net/torvald/terrarum/KVHashMap.kt +++ b/src/net/torvald/terrarum/KVHashMap.kt @@ -3,6 +3,7 @@ package net.torvald.terrarum import com.google.gson.JsonPrimitive import java.util.* import java.util.function.Consumer +import kotlin.collections.HashMap typealias ActorValue = KVHashMap typealias ItemValue = KVHashMap @@ -13,7 +14,15 @@ typealias GameConfig = KVHashMap */ class KVHashMap { - private val hashMap = HashMap() + constructor() { + hashMap = HashMap() + } + + private constructor(newMap: HashMap) { + hashMap = newMap + } + + private val hashMap: HashMap /** * Add key-value pair to the configuration table. @@ -108,4 +117,9 @@ class KVHashMap { hashMap.remove(key, hashMap[key]!!) } + fun clone(): KVHashMap { + val cloneOfMap = hashMap.clone() as HashMap + return KVHashMap(cloneOfMap) + } + } \ No newline at end of file diff --git a/src/net/torvald/terrarum/StateUITest.kt b/src/net/torvald/terrarum/StateUITest.kt index a933e9517..c1566d4dc 100644 --- a/src/net/torvald/terrarum/StateUITest.kt +++ b/src/net/torvald/terrarum/StateUITest.kt @@ -52,9 +52,9 @@ class StateUITest : BasicGameState() { override var originalName: String = "Test tool" override var baseMass: Double = 12.0 override var baseToolSize: Double? = 8.0 - override var category: String = InventoryItem.Category.TOOL - override var maxDurability: Double = 10.0 - override var durability: Double = 6.43 + override var inventoryCategory: String = InventoryItem.Category.TOOL + override var maxDurability: Int = 143 + override var durability: Float = 64f override var consumable = false }) actor.inventory.getByID(5656)!!.item.name = "Test tool" @@ -68,7 +68,7 @@ class StateUITest : BasicGameState() { override var originalName: String = "CONTEXT_ITEM_QUEST_NOUN" override var baseMass: Double = 1.4 override var baseToolSize: Double? = null - override var category: String = InventoryItem.Category.MISC + override var inventoryCategory: String = InventoryItem.Category.MISC override var consumable = false }) diff --git a/src/net/torvald/terrarum/UIItemInventoryElem.kt b/src/net/torvald/terrarum/UIItemInventoryElem.kt index 7b29d992e..8a14773bd 100644 --- a/src/net/torvald/terrarum/UIItemInventoryElem.kt +++ b/src/net/torvald/terrarum/UIItemInventoryElem.kt @@ -106,7 +106,7 @@ class UIItemInventoryElem( g.lineWidth = 3f g.drawLine(barOffset, posY + durabilityBarOffY, barOffset + barFullLen, posY + durabilityBarOffY) g.color = durabilityCol - g.drawLine(barOffset, posY + durabilityBarOffY, barOffset + barFullLen * (item!!.durability / item!!.maxDurability).toFloat(), posY + durabilityBarOffY) + g.drawLine(barOffset, posY + durabilityBarOffY, barOffset + barFullLen * (item!!.durability / item!!.maxDurability), posY + durabilityBarOffY) } diff --git a/src/net/torvald/terrarum/gameactors/Actor.kt b/src/net/torvald/terrarum/gameactors/Actor.kt index 121baa0f4..6f8876acf 100644 --- a/src/net/torvald/terrarum/gameactors/Actor.kt +++ b/src/net/torvald/terrarum/gameactors/Actor.kt @@ -50,9 +50,9 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable, Runnable fun hasCollision(value: Int) = try { Terrarum.ingame!!.theGameHasActor(value) || - value < ItemCodex.ITEM_COUNT_MAX || + value < ItemCodex.ACTOR_ID_MIN || value < when (renderOrder) { - RenderOrder.BEHIND -> ItemCodex.ITEM_COUNT_MAX + RenderOrder.BEHIND -> ItemCodex.ACTOR_ID_MIN RenderOrder.MIDDLE -> 0x10000000 RenderOrder.MIDTOP -> 0x60000000 RenderOrder.FRONT -> 0x70000000 diff --git a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt index 3584cdbfe..d065fcd22 100644 --- a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt +++ b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt @@ -138,7 +138,7 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) override val isUnique: Boolean = false override var baseMass: Double = 0.0 override var baseToolSize: Double? = null - override var category = "should_not_be_seen" + override var inventoryCategory = "should_not_be_seen" override val originalName: String = actorValue.getAsString(AVKey.NAME) ?: "(no name)" override var consumable = false } diff --git a/src/net/torvald/terrarum/gameactors/ActorInventory.kt b/src/net/torvald/terrarum/gameactors/ActorInventory.kt index df70a005c..468a88203 100644 --- a/src/net/torvald/terrarum/gameactors/ActorInventory.kt +++ b/src/net/torvald/terrarum/gameactors/ActorInventory.kt @@ -126,7 +126,9 @@ class ActorInventory(val actor: Pocketed, var maxCapacity: Int, var capacityMode remove(item, 1) } else { - // TODO decrement durability + item.durability -= 1f + if (item.durability <= 0) + remove(item, 1) } } diff --git a/src/net/torvald/terrarum/gameactors/DroppedItem.kt b/src/net/torvald/terrarum/gameactors/DroppedItem.kt index a4f00d899..0c1a045fc 100644 --- a/src/net/torvald/terrarum/gameactors/DroppedItem.kt +++ b/src/net/torvald/terrarum/gameactors/DroppedItem.kt @@ -12,7 +12,7 @@ import org.newdawn.slick.Graphics class DroppedItem(private val item: InventoryItem) : ActorWithSprite(Actor.RenderOrder.MIDTOP) { init { - if (item.id >= ItemCodex.ITEM_COUNT_MAX) + if (item.id >= ItemCodex.ACTOR_ID_MIN) throw RuntimeException("Attempted to create DroppedItem actor of a real actor; the real actor must be dropped instead.") isVisible = true diff --git a/src/net/torvald/terrarum/gameactors/HistoricalFigure.kt b/src/net/torvald/terrarum/gameactors/HistoricalFigure.kt index c6b6f037a..9f78b3dce 100644 --- a/src/net/torvald/terrarum/gameactors/HistoricalFigure.kt +++ b/src/net/torvald/terrarum/gameactors/HistoricalFigure.kt @@ -3,6 +3,8 @@ package net.torvald.terrarum.gameactors import net.torvald.terrarum.gameworld.WorldTime import org.newdawn.slick.Input +typealias AnyPlayer = HistoricalFigure + /** * An actor (NPC) which has life and death, * though death might not exist if it has achieved immortality :) diff --git a/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt b/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt index 84c0bcdb4..371c4c266 100644 --- a/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt +++ b/src/net/torvald/terrarum/gameactors/HumanoidNPC.kt @@ -1,9 +1,12 @@ package net.torvald.terrarum.gameactors +import net.torvald.terrarum.Terrarum import net.torvald.terrarum.gameactors.ActorHumanoid import net.torvald.terrarum.gameactors.ai.AILuaAPI import net.torvald.terrarum.gameactors.ai.ActorAI import net.torvald.terrarum.gameactors.ai.LuaAIWrapper +import net.torvald.terrarum.gamecontroller.mouseX +import net.torvald.terrarum.gamecontroller.mouseY import net.torvald.terrarum.gameitem.InventoryItem import org.luaj.vm2.* import org.luaj.vm2.compiler.LuaC @@ -51,13 +54,22 @@ open class HumanoidNPC( set(value) { actorValue[AVKey.SCALE] = value } - override var category = "npc" + override var inventoryCategory = "npc" override val originalName: String = actorValue.getAsString(AVKey.NAME) ?: "NPC" - override var consumable = false + override var consumable = true override fun secondaryUse(gc: GameContainer, delta: Int): Boolean { - return false - // TODO place this Actor to the world + try { + // place the actor to the world + this@HumanoidNPC.setPosition(gc.mouseX, gc.mouseY) + Terrarum.ingame!!.addNewActor(this@HumanoidNPC) + // successful + return true + } + catch (e: Exception) { + e.printStackTrace() + return false + } } } diff --git a/src/net/torvald/terrarum/gameactors/InjectCreatureRaw.kt b/src/net/torvald/terrarum/gameactors/InjectCreatureRaw.kt index 00c75dd21..1862ac106 100644 --- a/src/net/torvald/terrarum/gameactors/InjectCreatureRaw.kt +++ b/src/net/torvald/terrarum/gameactors/InjectCreatureRaw.kt @@ -15,8 +15,6 @@ import java.security.SecureRandom */ object InjectCreatureRaw { - // FIXME strength not injected properly? - const val JSONPATH = "./assets/raw/creatures/" private const val JSONMULT = "mult" // one appears in JSON files diff --git a/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt b/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt index e2c34f99f..446529b55 100644 --- a/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt +++ b/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt @@ -58,6 +58,7 @@ object PlayerBuilderSigrid { p.actorValue[AVKey.INTELLIGENT] = true p.actorValue[AVKey.LUMINOSITY] = Color(0x434aff).to10bit() + //p.actorValue[AVKey.LUMINOSITY] = 214127943 // bright purple p.actorValue[AVKey.BASEDEFENCE] = 141 @@ -65,7 +66,7 @@ object PlayerBuilderSigrid { //p.actorValue["__selectedtile"] = 147 // test code; replace with .primaryUse(gc, delta) p.actorValue["__aimhelper"] = true // TODO when you'll gonna implement it? - p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 11, 0) // FIXME offsetY of -2: Have no idea about the error; it's just supposed to be zero + p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 11, 0) p.inventory = ActorInventory(p, 0, ActorInventory.CAPACITY_MODE_NO_ENCUMBER) @@ -85,6 +86,7 @@ object PlayerBuilderSigrid { Tile.STONE_QUARRIED, Tile.STONE_TILE_WHITE, Tile.TORCH ) tiles.forEach { p.inventory.add(it, 999) } + p.inventory.add(ItemCodex.ITEM_STATIC.first) diff --git a/src/net/torvald/terrarum/gameactors/Pocketed.kt b/src/net/torvald/terrarum/gameactors/Pocketed.kt index 0d59517da..bdd7cdc77 100644 --- a/src/net/torvald/terrarum/gameactors/Pocketed.kt +++ b/src/net/torvald/terrarum/gameactors/Pocketed.kt @@ -3,7 +3,6 @@ package net.torvald.terrarum.gameactors import net.torvald.terrarum.Terrarum import net.torvald.terrarum.gameitem.InventoryItem import net.torvald.terrarum.itemproperties.ItemCodex -import java.util.* /** * Created by minjaesong on 16-01-15. @@ -17,10 +16,13 @@ interface Pocketed { */ fun unequipItem(item: InventoryItem) { if (item.equipPosition == InventoryItem.EquipPosition.NULL) - throw Error("Unequipping the item that cannot be equipped") + throw Error("Unequipping the item that cannot be equipped in the first place") - if (!inventory.contains(item)) - throw Error("Unequipping the item that does not exist in inventory") + if (!inventory.contains(item)) { + //throw Error("Unequipping the item that does not exist in inventory") + System.err.println("[Pocketed] Warning -- Unequipping the item that does not exist in inventory") + return // just do nothing + } inventory.itemEquipped[item.equipPosition] = null item.effectOnUnequip(Terrarum.appgc, Terrarum.UPDATE_DELTA) diff --git a/src/net/torvald/terrarum/gameactors/ai/AILuaAPI.kt b/src/net/torvald/terrarum/gameactors/ai/AILuaAPI.kt index 2b640845d..336c784cb 100644 --- a/src/net/torvald/terrarum/gameactors/ai/AILuaAPI.kt +++ b/src/net/torvald/terrarum/gameactors/ai/AILuaAPI.kt @@ -239,7 +239,7 @@ internal class AILuaAPI(g: Globals, actor: ActorWithSprite) { luatable[y - feetTilePos[1]] = LuaTable() for (x in feetTilePos[0] - radius..feetTilePos[0] + radius) { - val tile = TileCodex[Terrarum.ingame!!.world.getTileFromTerrain(x, y) ?: 4096] + val tile = TileCodex[Terrarum.ingame!!.world.getTileFromTerrain(x, y) ?: Tile.NULL] val solidity = tile.isSolid.toInt() val liquidity = tile.isFluid.toInt() val gravity = tile.isFallable.toInt() diff --git a/src/net/torvald/terrarum/gameitem/DynamicItem.kt b/src/net/torvald/terrarum/gameitem/DynamicItem.kt index d18427d5f..a5583d60e 100644 --- a/src/net/torvald/terrarum/gameitem/DynamicItem.kt +++ b/src/net/torvald/terrarum/gameitem/DynamicItem.kt @@ -16,13 +16,6 @@ import org.newdawn.slick.GameContainer open abstract class DynamicItem(val baseItemID: Int?, newMass: Double? = null, newScale: Double? = null) : InventoryItem() { /* - /** - * Internal ID of an Item, Long - * 0-4096: Tiles - * 4097-32767: Static items - * 32768-16777215: Dynamic items - * >= 16777216: Actor RefID - */ override val id: Int = generateUniqueDynamicItemID() private fun generateUniqueDynamicItemID(): Int { diff --git a/src/net/torvald/terrarum/gameitem/IVKey.kt b/src/net/torvald/terrarum/gameitem/IVKey.kt index 47802b791..98129d76e 100644 --- a/src/net/torvald/terrarum/gameitem/IVKey.kt +++ b/src/net/torvald/terrarum/gameitem/IVKey.kt @@ -7,6 +7,9 @@ object IVKey { const val ITEMTYPE = "itemtype" // "sword1h", "sword2h", "pick", "hammer", "tile", "wall", etc const val UUID = "uuid" // some items need UUID to be stored + const val BASE_WEAPON_POWER = "baseweaponpower" + const val BASE_PICK_POWER = "basepickpower" + object ItemType { const val BLOCK = "tile" diff --git a/src/net/torvald/terrarum/gameitem/InventoryItem.kt b/src/net/torvald/terrarum/gameitem/InventoryItem.kt index a37b5acae..031a9f4c7 100644 --- a/src/net/torvald/terrarum/gameitem/InventoryItem.kt +++ b/src/net/torvald/terrarum/gameitem/InventoryItem.kt @@ -10,17 +10,12 @@ import org.newdawn.slick.GameContainer /** * Created by minjaesong on 16-01-16. */ -abstract class InventoryItem : Comparable { - /** - * Internal ID of an Item, - * 0-4095: Tiles - * 4096-32767: Unique items (isUnique = true), brand-new tools - * 32768-16777215: Dynamic items (e.g. tools with damage) - * >= 16777216: Actor RefID - */ +abstract class InventoryItem : Comparable, Cloneable { + abstract val id: Int /** + * * e.g. Key Items (in a Pokémon sense), floppies */ abstract val isUnique: Boolean @@ -47,11 +42,11 @@ abstract class InventoryItem : Comparable { abstract var baseToolSize: Double? - abstract var category: String // "weapon", "tool", "armor", etc. (all smallcaps) + abstract var inventoryCategory: String // "weapon", "tool", "armor", etc. (all smallcaps) var itemProperties = ItemValue() - /** Single-use then destroyed (e.g. Tiles) */ + /** Single-use then destroyed (e.g. Tiles), aka negation of "stackable" */ abstract var consumable: Boolean /** @@ -94,9 +89,12 @@ abstract class InventoryItem : Comparable { /** * Set to zero if durability not applicable */ - open var maxDurability: Double = 0.0 + open var maxDurability: Int = 0 - open var durability: Double = 0.0 + /** + * Float. NOT A MISTAKE + */ + open var durability: Float = 0f /** * Effects applied continuously while in pocket @@ -115,6 +113,9 @@ abstract class InventoryItem : Comparable { * @return true when used successfully, false otherwise * * note: DO NOT super(gc, g) this! + * + * Consumption function is executed in net.torvald.terrarum.gamecontroller.GameController, + * in which the function itself is defined in net.torvald.terrarum.gameactors.ActorInventory */ open fun primaryUse(gc: GameContainer, delta: Int): Boolean = false @@ -212,4 +213,12 @@ abstract class InventoryItem : Comparable { const val WALL = "wall" const val MISC = "misc" } + + override public fun clone(): InventoryItem { + val clonedItem = super.clone() + // properly clone ItemValue + (clonedItem as InventoryItem).itemProperties = this.itemProperties.clone() + + return clonedItem + } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameworld/GameWorld.kt b/src/net/torvald/terrarum/gameworld/GameWorld.kt index 17fe7fa34..dcc09c852 100644 --- a/src/net/torvald/terrarum/gameworld/GameWorld.kt +++ b/src/net/torvald/terrarum/gameworld/GameWorld.kt @@ -1,35 +1,30 @@ package net.torvald.terrarum.gameworld +import net.torvald.terrarum.realestate.RealEstateUtility import org.dyn4j.geometry.Vector2 import org.newdawn.slick.SlickException -class GameWorld -/** - * @param width - * * - * @param height - * * - * @throws SlickException - */ -@Throws(SlickException::class) -constructor(//properties - val width: Int, val height: Int) { +typealias TileAddress = Long +typealias TileDamage = Int + +class GameWorld(val width: Int, val height: Int) { + //layers val layerWall: MapLayer - /** - * Get MapLayer object of terrain - - * @return MapLayer terrain layer - */ val layerTerrain: MapLayer val layerWire: MapLayer - val wallDamage: PairedMapLayer - val terrainDamage: PairedMapLayer + + val layerWallLowBits: PairedMapLayer + val layerTerrainLowBits: PairedMapLayer + val spawnX: Int val spawnY: Int + val wallDamages = HashMap() + val terrainDamages = HashMap() + //public World physWorld = new World( new Vec2(0, -TerrarumMain.game.gravitationalAccel) ); //physics /** Meter per second squared. Currently only the downward gravity is supported. No reverse gravity :p */ @@ -47,8 +42,8 @@ constructor(//properties layerTerrain = MapLayer(width, height) layerWall = MapLayer(width, height) layerWire = MapLayer(width, height) - terrainDamage = PairedMapLayer(width, height) - wallDamage = PairedMapLayer(width, height) + layerTerrainLowBits = PairedMapLayer(width, height) + layerWallLowBits = PairedMapLayer(width, height) time = WorldTime( 71 * WorldTime.DAY_LENGTH + @@ -87,11 +82,11 @@ constructor(//properties * @return byte[][] damage code pair */ val damageDataArray: Array - get() = terrainDamage.dataPair + get() = layerTerrainLowBits.dataPair fun getTileFromWall(x: Int, y: Int): Int? { val wall: Int? = layerWall.getTile(x fmod width, y) - val wallDamage: Int? = getWallDamage(x fmod width, y) + val wallDamage: Int? = getWallLowBits(x fmod width, y) return if (wall == null || wallDamage == null) null else @@ -100,7 +95,7 @@ constructor(//properties fun getTileFromTerrain(x: Int, y: Int): Int? { val terrain: Int? = layerTerrain.getTile(x fmod width, y) - val terrainDamage: Int? = getTerrainDamage(x fmod width, y) + val terrainDamage: Int? = getTerrainLowBits(x fmod width, y) return if (terrain == null || terrainDamage == null) null else @@ -111,12 +106,12 @@ constructor(//properties return layerWire.getTile(x fmod width, y) } - fun getWallDamage(x: Int, y: Int): Int? { - return wallDamage.getData(x fmod width, y) + fun getWallLowBits(x: Int, y: Int): Int? { + return layerWallLowBits.getData(x fmod width, y) } - fun getTerrainDamage(x: Int, y: Int): Int? { - return terrainDamage.getData(x fmod width, y) + fun getTerrainLowBits(x: Int, y: Int): Int? { + return layerTerrainLowBits.getData(x fmod width, y) } /** @@ -145,12 +140,12 @@ constructor(//properties fun setTileWall(x: Int, y: Int, tile: Byte, damage: Int) { layerWall.setTile(x fmod width, y, tile) - wallDamage.setData(x fmod width, y, damage) + layerWallLowBits.setData(x fmod width, y, damage) } fun setTileTerrain(x: Int, y: Int, tile: Byte, damage: Int) { layerTerrain.setTile(x fmod width, y, tile) - terrainDamage.setData(x fmod width, y, damage) + layerTerrainLowBits.setData(x fmod width, y, damage) } fun setTileWire(x: Int, y: Int, tile: Byte) { @@ -216,6 +211,32 @@ constructor(//properties } } + fun inflctTerrainDamage(x: Int, y: Int, damage: Int) { + val addr = RealEstateUtility.getAbsoluteTileNumber(x, y) + + if (terrainDamages[addr] == null) { + terrainDamages[addr] = damage + } + else { + terrainDamages[addr] = terrainDamages[addr]!! + damage + } + } + fun getTerrainDamage(x: Int, y: Int) = + terrainDamages[RealEstateUtility.getAbsoluteTileNumber(x, y)] ?: 0 + + fun inflctWallDamage(x: Int, y: Int, damage: Int) { + val addr = RealEstateUtility.getAbsoluteTileNumber(x, y) + + if (wallDamages[addr] == null) { + wallDamages[addr] = damage + } + else { + wallDamages[addr] = wallDamages[addr]!! + damage + } + } + fun getWallDamage(x: Int, y: Int) = + wallDamages[RealEstateUtility.getAbsoluteTileNumber(x, y)] ?: 0 + companion object { @Transient val WALL = 0 @@ -224,7 +245,7 @@ constructor(//properties @Transient val TILES_SUPPORTED = MapLayer.RANGE * PairedMapLayer.RANGE @Transient val SIZEOF: Byte = MapLayer.SIZEOF - @Transient val LAYERS: Byte = 4 // terrain, wall (terrainDamage + wallDamage), wire + @Transient val LAYERS: Byte = 4 // terrain, wall (layerTerrainLowBits + layerWallLowBits), wire } } diff --git a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt index cf2d5fa4e..2140e9648 100644 --- a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt +++ b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt @@ -2,6 +2,7 @@ package net.torvald.terrarum.gameworld import net.torvald.random.HQRNG import net.torvald.terrarum.Terrarum +import net.torvald.terrarum.gameactors.AnyPlayer import net.torvald.terrarum.gameactors.HistoricalFigure import net.torvald.terrarum.gameactors.Player import net.torvald.terrarum.gameactors.roundInt @@ -40,8 +41,7 @@ object WorldSimulator { private val world = Terrarum.ingame!!.world - // TODO future Kotlin feature -- typealias AnyPlayer: HistoricalFigure - operator fun invoke(p: HistoricalFigure?, delta: Int) { + operator fun invoke(p: AnyPlayer?, delta: Int) { if (p != null) { updateXFrom = p.hitbox.centeredX.div(FeaturesDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt() updateYFrom = p.hitbox.centeredY.div(FeaturesDrawer.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt() diff --git a/src/net/torvald/terrarum/gameworld/WorldTime.kt b/src/net/torvald/terrarum/gameworld/WorldTime.kt index 6c161dcf5..be201d0af 100644 --- a/src/net/torvald/terrarum/gameworld/WorldTime.kt +++ b/src/net/torvald/terrarum/gameworld/WorldTime.kt @@ -98,8 +98,6 @@ class WorldTime(initTime: Long = 0L) { ) val DAY_NAMES_SHORT = arrayOf("Mon", "Tys", "Mid", "Tor", "Fre", "Lau", "Sun", "Ver") - // FIXME Next to Granite is Felsite - val MONTH_NAMES = arrayOf( "Opal", "Obsidian", "Granite", "Slate", "Felsite", "Hematite", "Malachite", "Galena", "Limestone", "Sandstone", "Timber", "Moonstone" diff --git a/src/net/torvald/terrarum/gameworld/WorldTime_old.kt b/src/net/torvald/terrarum/gameworld/WorldTime_old.kt index 8a7a5623c..3cd6f287c 100644 --- a/src/net/torvald/terrarum/gameworld/WorldTime_old.kt +++ b/src/net/torvald/terrarum/gameworld/WorldTime_old.kt @@ -16,8 +16,8 @@ import net.torvald.terrarum.gameactors.GameDate * * Created by minjaesong on 16-01-24. */ +@Deprecated("Are you even reading the name?") class YeOldeWorldTime { - internal var TIME_T = 0L // TODO use it! Epoch: Year 125, 1st Granite, 0h00:00 internal var seconds: Int // 0 - 59 internal var minutes: Int // 0 - 59 diff --git a/src/net/torvald/terrarum/itemproperties/ItemCodex.kt b/src/net/torvald/terrarum/itemproperties/ItemCodex.kt index ea49d7857..5f6040360 100644 --- a/src/net/torvald/terrarum/itemproperties/ItemCodex.kt +++ b/src/net/torvald/terrarum/itemproperties/ItemCodex.kt @@ -11,6 +11,8 @@ import net.torvald.terrarum.gamecontroller.mouseTileY import net.torvald.terrarum.gameitem.IVKey import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.mapdrawer.TilesDrawer +import net.torvald.terrarum.mapdrawer.TilesDrawer.wallOverlayColour +import net.torvald.terrarum.tileproperties.Tile import net.torvald.terrarum.tileproperties.TileCodex import org.newdawn.slick.GameContainer import org.newdawn.slick.Image @@ -28,31 +30,35 @@ object ItemCodex { private val itemCodex = HashMap() private val dynamicItemDescription = HashMap() - val ITEM_TILE_MAX = GameWorld.TILES_SUPPORTED - 1 // 4095 - val ITEM_COUNT_MAX = 1048576 - val ITEM_DYNAMIC_MAX = ITEM_COUNT_MAX - 1 - val ITEM_STATIC_MAX = 32767 - val ITEM_DYNAMIC_MIN = ITEM_STATIC_MAX + 1 - val ITEM_STATIC_MIN = ITEM_TILE_MAX + 1 // 4096 + val ITEM_TILES = 0..GameWorld.TILES_SUPPORTED - 1 + val ITEM_WALLS = GameWorld.TILES_SUPPORTED..GameWorld.TILES_SUPPORTED * 2 - 1 + val ITEM_WIRES = GameWorld.TILES_SUPPORTED * 2..GameWorld.TILES_SUPPORTED * 2 + 255 + val ITEM_STATIC = ITEM_WIRES.endInclusive + 1..32767 + val ITEM_DYNAMIC = 32768..1048575 + val ACTOR_ID_MIN = ITEM_DYNAMIC.endInclusive + 1 + private val itemImagePlaceholder = Image("./assets/item_kari_24.tga") init { // tile items (blocks and walls are the same thing basically) - for (i in 0..ITEM_TILE_MAX) { + for (i in ITEM_TILES + ITEM_WALLS) { itemCodex[i] = object : InventoryItem() { override val id: Int = i override val isUnique: Boolean = false override var baseMass: Double = TileCodex[i].density / 1000.0 override var baseToolSize: Double? = null override var equipPosition = EquipPosition.HAND_GRIP - override var category = "block" - override val originalName = TileCodex[i].nameKey + override val originalName = TileCodex[i % ITEM_WALLS.first].nameKey override var consumable = true + override var inventoryCategory = Category.BLOCK init { - itemProperties[IVKey.ITEMTYPE] = IVKey.ItemType.BLOCK + itemProperties[IVKey.ITEMTYPE] = if (i in ITEM_TILES) + IVKey.ItemType.BLOCK + else + IVKey.ItemType.WALL } override fun primaryUse(gc: GameContainer, delta: Int): Boolean { @@ -74,26 +80,81 @@ object ItemCodex { // filter passed, do the job // FIXME this is only useful for Player - Terrarum.ingame!!.world.setTileTerrain( - gc.mouseTileX, - gc.mouseTileY, - i - ) + if (i in ITEM_TILES) { + Terrarum.ingame!!.world.setTileTerrain( + gc.mouseTileX, + gc.mouseTileY, + i + ) + } + else { + Terrarum.ingame!!.world.setTileWall( + gc.mouseTileX, + gc.mouseTileY, + i + ) + } return true } } } - // read prop in csv and fill itemCodex + // test copper pickaxe + itemCodex[ITEM_STATIC.first] = object : InventoryItem() { + override val id = ITEM_STATIC.first + override val isUnique = false + override val originalName = "Test Pick" + override var baseMass = 10.0 + override var baseToolSize: Double? = 10.0 + override var consumable = false + override var maxDurability = 200 // this much tiles before breaking + override var durability = maxDurability.toFloat() + override var equipPosition = EquipPosition.HAND_GRIP + override var inventoryCategory = Category.TOOL + + init { + itemProperties[IVKey.ITEMTYPE] = IVKey.ItemType.PICK + } + + override fun primaryUse(gc: GameContainer, delta: Int): Boolean { + val mousePoint = Point2d(gc.mouseTileX.toDouble(), gc.mouseTileY.toDouble()) + // linear search filter (check for intersection with tilewise mouse point and tilewise hitbox) + Terrarum.ingame!!.actorContainer.forEach { + if (it is ActorWithSprite && it.tilewiseHitbox.intersects(mousePoint)) + return false + } + + // return false if the tile is already there + if (this.id == Terrarum.ingame!!.world.getTileFromTerrain(gc.mouseTileX, gc.mouseTileY)) + return false + + // filter passed, do the job + Terrarum.ingame!!.world.setTileTerrain( + gc.mouseTileX, + gc.mouseTileY, + Tile.AIR + ) + /*Terrarum.ingame!!.world.inflctTerrainDamage( + gc.mouseTileX, + gc.mouseTileY, + + )*/ + + + return true + } + } + + // TODO read prop in Lua and fill itemCodex // read from save (if applicable) and fill dynamicItemDescription } operator fun get(code: Int): InventoryItem { - if (code < ITEM_STATIC_MAX) // generic item - return itemCodex[code]!! // from CSV - else if (code < ITEM_DYNAMIC_MAX) { + if (code <= ITEM_STATIC.endInclusive) // generic item + return itemCodex[code]!!.clone() // from CSV + else if (code <= ITEM_DYNAMIC.endInclusive) { TODO("read from dynamicitem description (JSON)") } else { @@ -105,8 +166,15 @@ object ItemCodex { } fun getItemImage(code: Int): Image { - if (code <= ITEM_TILE_MAX) + if (code <= ITEM_TILES.endInclusive) return TilesDrawer.tilesTerrain.getSubImage((code % 16) * 16, code / 16) + else if (code <= ITEM_WALLS.endInclusive) { + val img = TilesDrawer.tilesTerrain.getSubImage((code % 16) * 16, code / 16) + img.setImageColor(wallOverlayColour.r, wallOverlayColour.g, wallOverlayColour.b) + return img + } + else if (code <= ITEM_WIRES.endInclusive) + return TilesDrawer.tilesWire.getSubImage((code % 16) * 16, code / 16) else return itemImagePlaceholder } diff --git a/src/net/torvald/terrarum/itemproperties/ItemEffectsLuaAPI.kt b/src/net/torvald/terrarum/itemproperties/ItemEffectsLuaAPI.kt new file mode 100644 index 000000000..33572eafc --- /dev/null +++ b/src/net/torvald/terrarum/itemproperties/ItemEffectsLuaAPI.kt @@ -0,0 +1,61 @@ +package net.torvald.terrarum.itemproperties + +import net.torvald.terrarum.Terrarum +import net.torvald.terrarum.gameactors.ai.toLua +import net.torvald.terrarum.gamecontroller.mouseTileX +import net.torvald.terrarum.gamecontroller.mouseTileY +import net.torvald.terrarum.gamecontroller.mouseX +import net.torvald.terrarum.gamecontroller.mouseY +import org.luaj.vm2.Globals +import org.luaj.vm2.LuaTable +import org.luaj.vm2.LuaValue +import org.luaj.vm2.lib.ThreeArgFunction +import org.luaj.vm2.lib.ZeroArgFunction + +/** + * Created by SKYHi14 on 2017-04-16. + */ +class ItemEffectsLuaAPI(g: Globals) { + + init { + g["getMouseTile"] = GetMouseTile() + g["getMousePos"] = GetMousePos() + + + + g["world"] = LuaTable() + + g["world"]["strikeEarth"] = StrikeEarth() + g["world"]["strikeWall"] = StrikeWall() + + + + g["actor"] = LuaTable() + } + + + class GetMouseTile : ZeroArgFunction() { + override fun call(): LuaValue { + return LuaValue.tableOf(arrayOf(Terrarum.appgc.mouseTileX.toLua(), Terrarum.appgc.mouseTileY.toLua())) + } + } + class GetMousePos : ZeroArgFunction() { + override fun call(): LuaValue { + return LuaValue.tableOf(arrayOf(Terrarum.appgc.mouseX.toLua(), Terrarum.appgc.mouseY.toLua())) + } + } + + class StrikeEarth : ThreeArgFunction() { + override fun call(x: LuaValue, y: LuaValue, power: LuaValue): LuaValue { + Terrarum.ingame!!.world.inflctTerrainDamage(x.checkint(), y.checkint(), power.checkint()) + return LuaValue.NONE + } + } + class StrikeWall : ThreeArgFunction() { + override fun call(x: LuaValue, y: LuaValue, power: LuaValue): LuaValue { + Terrarum.ingame!!.world.inflctWallDamage(x.checkint(), y.checkint(), power.checkint()) + return LuaValue.NONE + } + } + +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/langpack/Lang.kt b/src/net/torvald/terrarum/langpack/Lang.kt index 495f42083..84dbe13b3 100644 --- a/src/net/torvald/terrarum/langpack/Lang.kt +++ b/src/net/torvald/terrarum/langpack/Lang.kt @@ -106,7 +106,7 @@ object Lang { } operator fun get(key: String): String { - fun fallback(): String = langpack["${key}_$FALLBACK_LANG_CODE"] ?: "ERRNULL:$key" + fun fallback(): String = langpack["${key}_$FALLBACK_LANG_CODE"] ?: "$$key" val ret = langpack["${key}_${Terrarum.gameLocale}"] diff --git a/src/net/torvald/terrarum/mapdrawer/TilesDrawer.kt b/src/net/torvald/terrarum/mapdrawer/TilesDrawer.kt index d7429fc4d..f07c781e7 100644 --- a/src/net/torvald/terrarum/mapdrawer/TilesDrawer.kt +++ b/src/net/torvald/terrarum/mapdrawer/TilesDrawer.kt @@ -401,10 +401,10 @@ object TilesDrawer { */ fun getNearbyTilesInfo(x: Int, y: Int, mode: Int, mark: Int?): Int { val nearbyTiles = IntArray(4) - nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(mode, x - 1, y) ?: 4096 - nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(mode, x + 1, y) ?: 4096 + nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(mode, x - 1, y) ?: Tile.NULL + nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(mode, x + 1, y) ?: Tile.NULL nearbyTiles[NEARBY_TILE_KEY_UP] = world.getTileFrom(mode, x , y - 1) ?: 4906 - nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(mode, x , y + 1) ?: 4096 + nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(mode, x , y + 1) ?: Tile.NULL // try for var ret = 0 @@ -419,10 +419,10 @@ object TilesDrawer { fun getNearbyTilesInfoNonSolid(x: Int, y: Int, mode: Int): Int { val nearbyTiles = IntArray(4) - nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(mode, x - 1, y) ?: 4096 - nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(mode, x + 1, y) ?: 4096 + nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(mode, x - 1, y) ?: Tile.NULL + nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(mode, x + 1, y) ?: Tile.NULL nearbyTiles[NEARBY_TILE_KEY_UP] = world.getTileFrom(mode, x , y - 1) ?: 4906 - nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(mode, x , y + 1) ?: 4096 + nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(mode, x , y + 1) ?: Tile.NULL // try for var ret = 0 @@ -443,10 +443,10 @@ object TilesDrawer { fun getNearbyTilesInfoWallSticker(x: Int, y: Int): Int { val nearbyTiles = IntArray(4) val NEARBY_TILE_KEY_BACK = NEARBY_TILE_KEY_UP - nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: 4096 - nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y) ?: 4096 - nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(TERRAIN, x , y + 1) ?: 4096 - nearbyTiles[NEARBY_TILE_KEY_BACK] = world.getTileFrom(WALL, x , y) ?: 4096 + nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: Tile.NULL + nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y) ?: Tile.NULL + nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(TERRAIN, x , y + 1) ?: Tile.NULL + nearbyTiles[NEARBY_TILE_KEY_BACK] = world.getTileFrom(WALL, x , y) ?: Tile.NULL try { if (TileCodex[nearbyTiles[NEARBY_TILE_KEY_DOWN]].isSolid) @@ -476,8 +476,8 @@ object TilesDrawer { fun getNearbyTilesInfoPlatform(x: Int, y: Int): Int { val nearbyTiles = IntArray(4) - nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: 4096 - nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y) ?: 4096 + nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: Tile.NULL + nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y) ?: Tile.NULL if ((TileCodex[nearbyTiles[NEARBY_TILE_KEY_LEFT]].isSolid && TileCodex[nearbyTiles[NEARBY_TILE_KEY_RIGHT]].isSolid) || diff --git a/src/net/torvald/terrarum/realestate/RealEstateUtility.kt b/src/net/torvald/terrarum/realestate/RealEstateUtility.kt index accb20635..0d1755840 100644 --- a/src/net/torvald/terrarum/realestate/RealEstateUtility.kt +++ b/src/net/torvald/terrarum/realestate/RealEstateUtility.kt @@ -2,21 +2,22 @@ package net.torvald.terrarum.realestate import net.torvald.terrarum.Terrarum import net.torvald.terrarum.gameactors.faction.FactionCodex +import net.torvald.terrarum.gameworld.TileAddress /** * Created by minjaesong on 16-03-27. */ object RealEstateUtility { - fun getAbsoluteTileNumber(x: Int, y: Int): Long = + fun getAbsoluteTileNumber(x: Int, y: Int): TileAddress = (Terrarum.ingame!!.world.width * y).toLong() + x - fun resolveAbsoluteTileNumber(t: Long): Pair = + fun resolveAbsoluteTileNumber(t: TileAddress): Pair = Pair((t % Terrarum.ingame!!.world.width).toInt(), (t / Terrarum.ingame!!.world.width).toInt()) /** * Get owner ID as an Actor/Faction */ - fun resolveOwner(id: Long): Any = + fun resolveOwner(id: TileAddress): Any = if (id < 0x80000000L) Terrarum.ingame!!.getActorByID(id.toInt()) else diff --git a/src/net/torvald/terrarum/tileproperties/Tile.kt b/src/net/torvald/terrarum/tileproperties/Tile.kt index 892038fdd..10c891072 100644 --- a/src/net/torvald/terrarum/tileproperties/Tile.kt +++ b/src/net/torvald/terrarum/tileproperties/Tile.kt @@ -150,5 +150,5 @@ object Tile { val LAVA_15 = TileCodex.idDamageToIndex(254, 14) val LAVA = TileCodex.idDamageToIndex(254, 15) - val NULL = 4096 + val NULL = -1 } diff --git a/src/net/torvald/terrarum/tileproperties/TileCodex.kt b/src/net/torvald/terrarum/tileproperties/TileCodex.kt index ac9cd5700..f94561b7b 100644 --- a/src/net/torvald/terrarum/tileproperties/TileCodex.kt +++ b/src/net/torvald/terrarum/tileproperties/TileCodex.kt @@ -18,8 +18,10 @@ object TileCodex { const val TILE_UNIQUE_MAX = MapLayer.RANGE * PairedMapLayer.RANGE + private val nullProp = TileProp() + init { - tileProps = Array(TILE_UNIQUE_MAX + 1, { i -> TileProp() }) + tileProps = Array(TILE_UNIQUE_MAX * 2, { i -> TileProp() }) for (i in tileProps.indices) { tileProps[i] = TileProp() @@ -31,8 +33,15 @@ object TileCodex { println("[TileCodex] Building tile properties table") - records.forEach { setProp( - tileProps[idDamageToIndex(intVal(it, "id"), intVal(it, "dmg"))], it) + records.forEach { + if (intVal(it, "dmg") == -1) { + setProp(nullProp, it) + } + else { + setProp( + tileProps[idDamageToIndex(intVal(it, "id"), intVal(it, "dmg"))], it + ) + } } } catch (e: IOException) { @@ -53,14 +62,16 @@ object TileCodex { } operator fun get(rawIndex: Int?): TileProp { + if (rawIndex == null || rawIndex == Tile.NULL) { + return nullProp + } + try { - tileProps[rawIndex ?: Tile.NULL].id + return tileProps[rawIndex] } catch (e: NullPointerException) { throw NullPointerException("Tile prop with raw id $rawIndex does not exist.") } - - return tileProps[rawIndex ?: Tile.NULL] } private fun setProp(prop: TileProp, record: CSVRecord) { diff --git a/src/net/torvald/terrarum/tileproperties/TilePropCSV.kt b/src/net/torvald/terrarum/tileproperties/TilePropCSV.kt index 65486f011..bd9a5a81e 100644 --- a/src/net/torvald/terrarum/tileproperties/TilePropCSV.kt +++ b/src/net/torvald/terrarum/tileproperties/TilePropCSV.kt @@ -135,7 +135,7 @@ object TilePropCSV { "255"; "13";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16" "255"; "14";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16" "255"; "15";"TILE_WATER" ; "27282445"; "100";"1000";"watr"; "1"; "0"; "0"; "0"; "N/A"; "N/A"; "0"; "0"; "16"; "0";"16" -"256"; "0";"TILE_NULL" ;"1073741823"; "-1";"2600";"null"; "0"; "0"; "1"; "0"; "N/A"; "N/A"; "0"; "0"; "N/A"; "0";"16" + "0"; "-1";"TILE_NULL" ;"1073741823"; "-1";"2600";"null"; "0"; "0"; "1"; "0"; "N/A"; "N/A"; "0"; "0"; "N/A"; "0";"16" ## Notes ## diff --git a/src/net/torvald/terrarum/ui/UICanvas.kt b/src/net/torvald/terrarum/ui/UICanvas.kt index be3591270..145260fca 100644 --- a/src/net/torvald/terrarum/ui/UICanvas.kt +++ b/src/net/torvald/terrarum/ui/UICanvas.kt @@ -1,6 +1,9 @@ package net.torvald.terrarum.ui +import net.torvald.point.Point2d import net.torvald.terrarum.Millisec +import net.torvald.terrarum.Terrarum +import net.torvald.terrarum.gameactors.roundInt import org.newdawn.slick.GameContainer import org.newdawn.slick.Graphics import org.newdawn.slick.Input @@ -57,21 +60,86 @@ interface UICanvas { fun doOpeningFade(handler: UIHandler?, openCloseTime: Int) { handler!!.opacity = handler.openCloseCounter.toFloat() / openCloseTime } - fun doClosingFade(handler: UIHandler?, openCloseTime: Int) { handler!!.opacity = (openCloseTime - handler.openCloseCounter.toFloat()) / openCloseTime } - fun endOpeningFade(handler: UIHandler?) { handler!!.opacity = 1f } - fun endClosingFade(handler: UIHandler?) { handler!!.opacity = 0f } - // TODO add drawer slide in/out (quadratic) + + fun doOpeningPopOut(handler: UIHandler?, openCloseTime: Int, position: Position) { + when (position) { + Position.LEFT -> handler!!.posX = Movement.fastPullOut( + handler.openCloseCounter.toFloat() / openCloseTime, + -handler.UI.width.toFloat(), + 0f + ).roundInt() + Position.TOP -> handler!!.posY = Movement.fastPullOut( + handler.openCloseCounter.toFloat() / openCloseTime, + -handler.UI.height.toFloat(), + 0f + ).roundInt() + Position.RIGHT -> handler!!.posX = Movement.fastPullOut( + handler.openCloseCounter.toFloat() / openCloseTime, + Terrarum.WIDTH.toFloat(), + Terrarum.WIDTH - handler.UI.width.toFloat() + ).roundInt() + Position.BOTTOM -> handler!!.posY = Movement.fastPullOut( + handler.openCloseCounter.toFloat() / openCloseTime, + Terrarum.HEIGHT.toFloat(), + Terrarum.HEIGHT - handler.UI.height.toFloat() + ).roundInt() + } + } + fun doClosingPopOut(handler: UIHandler?, openCloseTime: Int, position: Position) { + when (position) { + Position.LEFT -> handler!!.posX = Movement.fastPullOut( + handler.openCloseCounter.toFloat() / openCloseTime, + 0f, + -handler.UI.width.toFloat() + ).roundInt() + Position.TOP -> handler!!.posY = Movement.fastPullOut( + handler.openCloseCounter.toFloat() / openCloseTime, + 0f, + -handler.UI.height.toFloat() + ).roundInt() + Position.RIGHT -> handler!!.posX = Movement.fastPullOut( + handler.openCloseCounter.toFloat() / openCloseTime, + Terrarum.WIDTH - handler.UI.width.toFloat(), + Terrarum.WIDTH.toFloat() + ).roundInt() + Position.BOTTOM -> handler!!.posY = Movement.fastPullOut( + handler.openCloseCounter.toFloat() / openCloseTime, + Terrarum.HEIGHT - handler.UI.height.toFloat(), + Terrarum.HEIGHT.toFloat() + ).roundInt() + } + } + fun endOpeningPopOut(handler: UIHandler?, position: Position) { + when (position) { + Position.LEFT -> handler!!.posX = 0 + Position.TOP -> handler!!.posY = 0 + Position.RIGHT -> handler!!.posX = Terrarum.WIDTH - handler.UI.width + Position.BOTTOM -> handler!!.posY = Terrarum.HEIGHT - handler.UI.height + } + } + fun endClosingPopOut(handler: UIHandler?, position: Position) { + when (position) { + Position.LEFT -> handler!!.posX = -handler.UI.width + Position.TOP -> handler!!.posY = -handler.UI.height + Position.RIGHT -> handler!!.posX = Terrarum.WIDTH + Position.BOTTOM -> handler!!.posY = Terrarum.HEIGHT + } + } // TODO add blackboard take in/out (sinusoidal) + + enum class Position { + LEFT, RIGHT, TOP, BOTTOM + } } } diff --git a/src/net/torvald/terrarum/ui/UIInventory.kt b/src/net/torvald/terrarum/ui/UIInventory.kt index df1280c14..701aaf859 100644 --- a/src/net/torvald/terrarum/ui/UIInventory.kt +++ b/src/net/torvald/terrarum/ui/UIInventory.kt @@ -158,7 +158,7 @@ class UIInventory( // filter items inventory?.forEach { - if (it.item.category == filter || filter == "__all__") + if (it.item.inventoryCategory == filter || filter == "__all__") inventorySortList.add(it) } @@ -295,27 +295,20 @@ class UIInventory( } override fun doOpening(gc: GameContainer, delta: Int) { - handler!!.posX = Movement.fastPullOut( - handler!!.openCloseCounter.toFloat() / openCloseTime, - -width.toFloat(), - 0f - ).roundInt() + UICanvas.doOpeningPopOut(handler, openCloseTime, UICanvas.Companion.Position.LEFT) } override fun doClosing(gc: GameContainer, delta: Int) { - handler!!.posX = Movement.fastPullOut( - handler!!.openCloseCounter.toFloat() / openCloseTime, - 0f, - -width.toFloat() - ).roundInt() + UICanvas.doClosingPopOut(handler, openCloseTime, UICanvas.Companion.Position.LEFT) + } override fun endOpening(gc: GameContainer, delta: Int) { - handler!!.posX = 0 + UICanvas.endOpeningPopOut(handler, UICanvas.Companion.Position.LEFT) } override fun endClosing(gc: GameContainer, delta: Int) { - handler!!.posX = -width + UICanvas.endClosingPopOut(handler, UICanvas.Companion.Position.LEFT) } override fun keyPressed(key: Int, c: Char) { diff --git a/src/net/torvald/terrarum/virtualcomputer/luaapi/FilesystemTEVD.kt b/src/net/torvald/terrarum/virtualcomputer/luaapi/FilesystemTEVD.kt index da17e7f97..05bda243d 100644 --- a/src/net/torvald/terrarum/virtualcomputer/luaapi/FilesystemTEVD.kt +++ b/src/net/torvald/terrarum/virtualcomputer/luaapi/FilesystemTEVD.kt @@ -94,7 +94,7 @@ internal class Filesystem(globals: Globals, computer: TerrarumComputer) { path.dropMount() - return VDUtil.getFile(disk, path)?.file + return VDUtil.getFile(disk, path) } /** @@ -201,7 +201,7 @@ internal class Filesystem(globals: Globals, computer: TerrarumComputer) { if (file!!.contents is EntryFile) return LuaValue.valueOf(file.contents.getSizePure().toInt()) else if (file.contents is EntryDirectory) - return LuaValue.valueOf(file.contents.entries.size) + return LuaValue.valueOf(file.contents.entryCount) } catch (e: KotlinNullPointerException) { } @@ -279,12 +279,12 @@ internal class Filesystem(globals: Globals, computer: TerrarumComputer) { val file = VDUtil.getFile(disk1, pathFrom)!! try { - VDUtil.addFile(disk2, pathTo.getParent(), file.file) + VDUtil.addFile(disk2, pathTo.getParent(), file) } catch (e: FileNotFoundException) { // roll back delete on disk2 if (oldFile != null) { - VDUtil.addFile(disk2, oldFile.parent.entryID, oldFile.file) + VDUtil.addFile(disk2, oldFile.parentEntryID, oldFile) throw FileNotFoundException("No such destination") } } diff --git a/src/net/torvald/terrarum/virtualcomputer/tvd/VDUtil.kt b/src/net/torvald/terrarum/virtualcomputer/tvd/VDUtil.kt index 84c42fc2c..1f242d19b 100644 --- a/src/net/torvald/terrarum/virtualcomputer/tvd/VDUtil.kt +++ b/src/net/torvald/terrarum/virtualcomputer/tvd/VDUtil.kt @@ -41,7 +41,7 @@ object VDUtil { unsanitisedHierarchy.removeAt(0) // removes tail slash if (unsanitisedHierarchy.size > 0 && - unsanitisedHierarchy[unsanitisedHierarchy.lastIndex].isEmpty()) + unsanitisedHierarchy[unsanitisedHierarchy.lastIndex].isEmpty()) unsanitisedHierarchy.removeAt(unsanitisedHierarchy.lastIndex) unsanitisedHierarchy.forEach { @@ -202,7 +202,7 @@ object VDUtil { val calculatedCRC = diskEntry.hashCode() val crcMsg = "CRC failed: expected ${entryCRC.toHex()}, got ${calculatedCRC.toHex()}\n" + - "at file \"${diskEntry.getFilenameString(charset)}\" (entry ID ${diskEntry.entryID})" + "at file \"${diskEntry.getFilenameString(charset)}\" (entry ID ${diskEntry.entryID})" if (calculatedCRC != entryCRC) { if (crcWarnLevel == Level.SEVERE) @@ -243,7 +243,7 @@ object VDUtil { throw IllegalArgumentException("The entry is not directory") val entriesList = ArrayList() - dirToSearch.contents.entries.forEach { + dirToSearch.contents.forEach { val entry = disk.entries[it] if (entry != null) entriesList.add(entry) } @@ -267,7 +267,7 @@ object VDUtil { * Search a entry using path * @return Pair of , or null if not found */ - fun getFile(disk: VirtualDisk, path: VDPath): EntrySearchResult? { + fun getFile(disk: VirtualDisk, path: VDPath): DiskEntry? { val searchHierarchy = ArrayList() fun getCurrentEntry(): DiskEntry = searchHierarchy.last() //var currentDirectory = disk.root @@ -276,10 +276,7 @@ object VDUtil { // path of root if (path.hierarchy.size == 0) { - return EntrySearchResult( - disk.entries[0]!!, - disk.entries[0]!! - ) + return disk.entries[0]!! } try { @@ -310,10 +307,7 @@ object VDUtil { } // file found - return EntrySearchResult( - searchHierarchy[searchHierarchy.lastIndex], - searchHierarchy[searchHierarchy.lastIndex - 1] - ) + return searchHierarchy[searchHierarchy.lastIndex] } /** @@ -323,12 +317,12 @@ object VDUtil { */ private fun DiskEntry.getAsNormalFile(disk: VirtualDisk): EntryFile = this.contents as? EntryFile ?: - if (this.contents is EntryDirectory) - throw RuntimeException("this is directory") - else if (this.contents is EntrySymlink) - disk.entries[this.contents.target]!!.getAsNormalFile(disk) - else - throw RuntimeException("Unknown entry type") + if (this.contents is EntryDirectory) + throw RuntimeException("this is directory") + else if (this.contents is EntrySymlink) + disk.entries[this.contents.target]!!.getAsNormalFile(disk) + else + throw RuntimeException("Unknown entry type") /** * SYNOPSIS disk.getFile("bin/msh.lua")!!.first.getAsNormalFile(disk) * @@ -336,18 +330,18 @@ object VDUtil { */ private fun DiskEntry.getAsDirectory(disk: VirtualDisk): EntryDirectory = this.contents as? EntryDirectory ?: - if (this.contents is EntrySymlink) - disk.entries[this.contents.target]!!.getAsDirectory(disk) - else if (this.contents is EntryFile) - throw RuntimeException("this is not directory") - else - throw RuntimeException("Unknown entry type") + if (this.contents is EntrySymlink) + disk.entries[this.contents.target]!!.getAsDirectory(disk) + else if (this.contents is EntryFile) + throw RuntimeException("this is not directory") + else + throw RuntimeException("Unknown entry type") /** * Search for the file and returns a instance of normal file. */ fun getAsNormalFile(disk: VirtualDisk, path: VDPath) = - getFile(disk, path)!!.file.getAsNormalFile(disk) + getFile(disk, path)!!.getAsNormalFile(disk) /** * Fetch the file and returns a instance of normal file. */ @@ -357,7 +351,7 @@ object VDUtil { * Search for the file and returns a instance of directory. */ fun getAsDirectory(disk: VirtualDisk, path: VDPath) = - getFile(disk, path)!!.file.getAsDirectory(disk) + getFile(disk, path)!!.getAsDirectory(disk) /** * Fetch the file and returns a instance of directory. */ @@ -367,11 +361,8 @@ object VDUtil { * Deletes file on the disk safely. */ fun deleteFile(disk: VirtualDisk, path: VDPath) { - disk.checkReadOnly() - val fileSearchResult = getFile(disk, path)!! - - return deleteFile(disk, fileSearchResult.file.entryID) + return deleteFile(disk, fileSearchResult.entryID) } /** * Deletes file on the disk safely. @@ -386,29 +377,25 @@ object VDUtil { } val parentID = file.parentEntryID - val parentDir = disk.entries[parentID] + val parentDir = getAsDirectory(disk, parentID) fun rollback() { if (!disk.entries.contains(targetID)) { disk.entries[targetID] = file } - if (!(parentDir!!.contents as EntryDirectory).entries.contains(targetID)) { - (parentDir.contents as EntryDirectory).entries.add(targetID) + if (!parentDir.contains(targetID)) { + parentDir.add(targetID) } } - if (parentDir == null || parentDir.contents !is EntryDirectory) { - throw FileNotFoundException("No such parent directory") - } // check if directory "parentID" has "targetID" in the first place - else if (!directoryContains(disk, parentID, targetID)) { + if (!directoryContains(disk, parentID, targetID)) { throw FileNotFoundException("No such file to delete") } else if (targetID == 0) { throw IOException("Cannot delete root file system") } - else if (file.contents is EntryDirectory && file.contents.entries.size > 0) { - //throw IOException("Cannot delete directory that contains something") + else if (file.contents is EntryDirectory && file.contents.entryCount > 0) { deleteDirRecurse(disk, targetID) } else { @@ -416,7 +403,7 @@ object VDUtil { // delete file record disk.entries.remove(targetID) // unlist file from parent directly - (disk.entries[parentID]!!.contents as EntryDirectory).entries.remove(targetID) + parentDir.remove(targetID) } catch (e: Exception) { rollback() @@ -428,7 +415,7 @@ object VDUtil { * Changes the name of the entry. */ fun renameFile(disk: VirtualDisk, path: VDPath, newName: String, charset: Charset) { - val file = getFile(disk, path)?.file + val file = getFile(disk, path) if (file != null) { file.filename = newName.sanitisePath().toEntryName(DiskEntry.NAME_LENGTH, charset) @@ -451,23 +438,12 @@ object VDUtil { } } /** - * Add file to the specified directory. ParentID of the file will be overwritten. + * Add file to the specified directory. + * The file will get new EntryID and its ParentID will be overwritten. */ fun addFile(disk: VirtualDisk, parentPath: VDPath, file: DiskEntry) { - disk.checkReadOnly() - disk.checkCapacity(file.serialisedSize) - - try { - val parentID = getFile(disk, parentPath)!!.file.entryID - // add record to the directory - getAsDirectory(disk, parentPath).entries.add(file.entryID) - // add entry on the disk - disk.entries[file.entryID] = file - file.parentEntryID = parentID - } - catch (e: KotlinNullPointerException) { - throw FileNotFoundException("No such directory") - } + val targetDirID = getFile(disk, parentPath)!!.entryID + return addFile(disk, targetDirID, file) } /** * Add file to the specified directory. ParentID of the file will be overwritten. @@ -477,10 +453,13 @@ object VDUtil { disk.checkCapacity(file.serialisedSize) try { + // generate new ID for the file + file.entryID = disk.generateUniqueID() // add record to the directory - getAsDirectory(disk, directoryID).entries.add(file.entryID) + getAsDirectory(disk, directoryID).add(file.entryID) // add entry on the disk disk.entries[file.entryID] = file + // make this boy recognise his new parent file.parentEntryID = directoryID } catch (e: KotlinNullPointerException) { @@ -491,28 +470,8 @@ object VDUtil { * Add subdirectory to the specified directory. */ fun addDir(disk: VirtualDisk, parentPath: VDPath, name: ByteArray) { - disk.checkReadOnly() - disk.checkCapacity(EntryDirectory.NEW_ENTRY_SIZE) - - val newID = disk.generateUniqueID() - - try { - val parentID = getFile(disk, parentPath)!!.file.entryID - // add record to the directory - getAsDirectory(disk, parentPath).entries.add(newID) - // add entry on the disk - disk.entries[newID] = DiskEntry( - newID, - parentID, - name, - currentUnixtime, - currentUnixtime, - EntryDirectory() - ) - } - catch (e: KotlinNullPointerException) { - throw FileNotFoundException("No such directory") - } + val parentID = getFile(disk, parentPath)!!.entryID + return addDir(disk, parentID, name) } /** * Add file to the specified directory. @@ -525,7 +484,7 @@ object VDUtil { try { // add record to the directory - getAsDirectory(disk, directoryID).entries.add(newID) + getAsDirectory(disk, directoryID).add(newID) // add entry on the disk disk.entries[newID] = DiskEntry( newID, @@ -553,7 +512,7 @@ object VDUtil { } // recurse else { - entry.contents.entries.forEach { + entry.contents.forEach { entriesToDelete.add(entry.entryID) recurse1(disk.entries[it]) } @@ -562,7 +521,7 @@ object VDUtil { val entry = disk.entries[directoryID] if (entry != null && entry.contents is EntryDirectory) { - entry.contents.entries.forEach { + entry.contents.forEach { entriesToDelete.add(directoryID) recurse1(disk.entries[it]) } @@ -630,12 +589,10 @@ object VDUtil { fun moveFile(disk1: VirtualDisk, fromPath: VDPath, disk2: VirtualDisk, toPath: VDPath) { val file = getFile(disk1, fromPath) - if (file != null) { - if (file.file.contents is EntryDirectory) { - throw IOException("Cannot move directory") - } + // checking readOnly is redundant here - disk2.checkCapacity(file.file.contents.getSizeEntry()) + if (file != null) { + disk2.checkCapacity(file.contents.getSizeEntry()) try { deleteFile(disk2, toPath) @@ -644,11 +601,11 @@ object VDUtil { deleteFile(disk1, fromPath) // any uncaught no_from_file will be caught here try { - addFile(disk2, toPath.getParent(), file.file) + addFile(disk2, toPath.getParent(), file) } catch (e: FileNotFoundException) { // roll back delete on disk1 - addFile(disk1, file.parent.entryID, file.file) + addFile(disk1, file.parentEntryID, file) throw FileNotFoundException("No such destination") } } @@ -740,7 +697,6 @@ object VDUtil { val path1 = this.replace('\\', '/') return path1 } - data class EntrySearchResult(val file: DiskEntry, val parent: DiskEntry) fun resolveIfSymlink(disk: VirtualDisk, indexNumber: EntryID, recurse: Boolean = false): DiskEntry { var entry: DiskEntry? = disk.entries[indexNumber] @@ -769,7 +725,7 @@ object VDUtil { throw FileNotFoundException("Not a directory") } else { - return dir.contents.entries.contains(targetID) + return dir.contents.contains(targetID) } } @@ -784,11 +740,16 @@ object VDUtil { return disk.entries.filter { disk.entries[it.value.parentEntryID] == null }.keys.toList() } + /** + * Searches for null-pointing entries (phantoms) within every directory. + * + * @return List of search results, which is Pair(directory that contains null pointer, null pointer) + */ fun gcSearchPhantomBaby(disk: VirtualDisk): List> { // Pair val phantoms = ArrayList>() disk.entries.filter { it.value.contents is EntryDirectory }.values.forEach { directory -> - (directory.contents as EntryDirectory).entries.forEach { dirEntryID -> + (directory.contents as EntryDirectory).forEach { dirEntryID -> if (disk.entries[dirEntryID] == null) { phantoms.add(Pair(directory.entryID, dirEntryID)) } @@ -811,7 +772,7 @@ object VDUtil { fun gcDumpAll(disk: VirtualDisk) { try { gcSearchPhantomBaby(disk).forEach { - getAsDirectory(disk, it.first).entries.remove(it.second) + getAsDirectory(disk, it.first).remove(it.second) } gcSearchOrphan(disk).forEach { disk.entries.remove(it) diff --git a/src/net/torvald/terrarum/virtualcomputer/tvd/VirtualDisk.kt b/src/net/torvald/terrarum/virtualcomputer/tvd/VirtualDisk.kt index f062d23f5..0fa599e70 100644 --- a/src/net/torvald/terrarum/virtualcomputer/tvd/VirtualDisk.kt +++ b/src/net/torvald/terrarum/virtualcomputer/tvd/VirtualDisk.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.virtualcomputer.tvd +import java.io.IOException import java.nio.charset.Charset import java.util.* import java.util.function.Consumer @@ -182,10 +183,30 @@ class EntryFile(var bytes: ByteArray64) : DiskEntryContent { return buffer } } -class EntryDirectory(val entries: ArrayList = ArrayList()) : DiskEntryContent { +class EntryDirectory(private val entries: ArrayList = ArrayList()) : DiskEntryContent { override fun getSizePure() = entries.size * 4L override fun getSizeEntry() = getSizePure() + 2 + private fun checkCapacity(toAdd: Int = 1) { + if (entries.size + toAdd > 65535) + throw IOException("Directory entries limit exceeded.") + } + + fun add(entryID: EntryID) { + checkCapacity() + entries.add(entryID) + } + + fun remove(entryID: EntryID) { + entries.removeAt(entryID) + } + + fun contains(entryID: EntryID) = entries.contains(entryID) + + fun forEach(consumer: (EntryID) -> Unit) = entries.forEach(consumer) + + val entryCount: Int + get() = entries.size override fun serialize(): AppendableByteBuffer { val buffer = AppendableByteBuffer(getSizeEntry()) diff --git a/work_files/Attack momentum calculator.xlsx b/work_files/Attack momentum calculator.xlsx new file mode 100644 index 000000000..e8cf48424 Binary files /dev/null and b/work_files/Attack momentum calculator.xlsx differ diff --git a/work_files/Pickaxe Power.xlsx b/work_files/Pickaxe Power.xlsx new file mode 100644 index 000000000..d3735172d Binary files /dev/null and b/work_files/Pickaxe Power.xlsx differ diff --git a/work_files/phys penetration compensation.pdf b/work_files/phys penetration compensation.pdf new file mode 100644 index 000000000..f64bfd5ad Binary files /dev/null and b/work_files/phys penetration compensation.pdf differ