mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
fixes, bits and pieces, changes in ID referencing, terrain and wall takes damage, working test pickaxe, and a new issue
This commit is contained in:
@@ -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|
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "자갈",
|
||||
|
||||
@@ -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)) })
|
||||
|
||||
@@ -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<String, Any>()
|
||||
constructor() {
|
||||
hashMap = HashMap<String, Any>()
|
||||
}
|
||||
|
||||
private constructor(newMap: HashMap<String, Any>) {
|
||||
hashMap = newMap
|
||||
}
|
||||
|
||||
private val hashMap: HashMap<String, Any>
|
||||
|
||||
/**
|
||||
* 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<String, Any>
|
||||
return KVHashMap(cloneOfMap)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
})
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,9 +50,9 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, 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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 :)
|
||||
|
||||
@@ -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 {
|
||||
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
|
||||
// TODO place this Actor to the world
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 <tile_item>.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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -10,17 +10,12 @@ import org.newdawn.slick.GameContainer
|
||||
/**
|
||||
* Created by minjaesong on 16-01-16.
|
||||
*/
|
||||
abstract class InventoryItem : Comparable<InventoryItem> {
|
||||
/**
|
||||
* 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<InventoryItem>, 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<InventoryItem> {
|
||||
|
||||
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<InventoryItem> {
|
||||
/**
|
||||
* 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<InventoryItem> {
|
||||
* @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<InventoryItem> {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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<TileAddress, TileDamage>()
|
||||
val terrainDamages = HashMap<TileAddress, TileDamage>()
|
||||
|
||||
//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<ByteArray>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Int, InventoryItem>()
|
||||
private val dynamicItemDescription = HashMap<Int, KVHashMap>()
|
||||
|
||||
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
|
||||
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,
|
||||
<power calculation using ForceMod (ref. Pickaxe Power.xlsx) and other shits>
|
||||
)*/
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
61
src/net/torvald/terrarum/itemproperties/ItemEffectsLuaAPI.kt
Normal file
61
src/net/torvald/terrarum/itemproperties/ItemEffectsLuaAPI.kt
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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}"]
|
||||
|
||||
@@ -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) ||
|
||||
|
||||
@@ -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<Int, Int> =
|
||||
fun resolveAbsoluteTileNumber(t: TileAddress): Pair<Int, Int> =
|
||||
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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ object TileCodex {
|
||||
|
||||
const val TILE_UNIQUE_MAX = MapLayer.RANGE * PairedMapLayer.RANGE
|
||||
|
||||
private val nullProp = TileProp()
|
||||
|
||||
init {
|
||||
tileProps = Array<TileProp>(TILE_UNIQUE_MAX + 1, { i -> TileProp() })
|
||||
tileProps = Array<TileProp>(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) {
|
||||
|
||||
@@ -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 ##
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ object VDUtil {
|
||||
throw IllegalArgumentException("The entry is not directory")
|
||||
|
||||
val entriesList = ArrayList<DiskEntry>()
|
||||
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 <The file, Parent file>, or null if not found
|
||||
*/
|
||||
fun getFile(disk: VirtualDisk, path: VDPath): EntrySearchResult? {
|
||||
fun getFile(disk: VirtualDisk, path: VDPath): DiskEntry? {
|
||||
val searchHierarchy = ArrayList<DiskEntry>()
|
||||
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]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,7 +341,7 @@ object VDUtil {
|
||||
* 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<EntryID, EntryID>> {
|
||||
// Pair<DirectoryID, ID of phantom in the directory>
|
||||
val phantoms = ArrayList<Pair<EntryID, EntryID>>()
|
||||
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)
|
||||
|
||||
@@ -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<EntryID> = ArrayList<EntryID>()) : DiskEntryContent {
|
||||
class EntryDirectory(private val entries: ArrayList<EntryID> = ArrayList<EntryID>()) : 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())
|
||||
|
||||
BIN
work_files/Attack momentum calculator.xlsx
Normal file
BIN
work_files/Attack momentum calculator.xlsx
Normal file
Binary file not shown.
BIN
work_files/Pickaxe Power.xlsx
Normal file
BIN
work_files/Pickaxe Power.xlsx
Normal file
Binary file not shown.
BIN
work_files/phys penetration compensation.pdf
Normal file
BIN
work_files/phys penetration compensation.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user