mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-12 11:34:05 +09:00
poi import wip
This commit is contained in:
@@ -17,6 +17,8 @@ import net.torvald.terrarum.gameitems.ItemID
|
|||||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||||
import net.torvald.terrarum.gameworld.BlockLayerI16
|
import net.torvald.terrarum.gameworld.BlockLayerI16
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
import net.torvald.terrarum.gameworld.WorldTime
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
|
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
|
||||||
@@ -717,7 +719,7 @@ class YamlCommandToolExportTest : YamlInvokable {
|
|||||||
var name = "test"
|
var name = "test"
|
||||||
|
|
||||||
// prepare POI
|
// prepare POI
|
||||||
val poi = PointOfInterest(name, maxX - minX + 1, maxY - minY + 1, ui.world.tileNumberToNameMap)
|
val poi = PointOfInterest(name, maxX - minX + 1, maxY - minY + 1, ui.world.tileNumberToNameMap, ui.world.tileNameToNumberMap)
|
||||||
val layer = POILayer(name)
|
val layer = POILayer(name)
|
||||||
val terr = BlockLayerI16(poi.w, poi.h)
|
val terr = BlockLayerI16(poi.w, poi.h)
|
||||||
val wall = BlockLayerI16(poi.w, poi.h)
|
val wall = BlockLayerI16(poi.w, poi.h)
|
||||||
@@ -804,6 +806,31 @@ class YamlCommandToolImportTest : YamlInvokable {
|
|||||||
|
|
||||||
val json = """{"genver":67108864,"id":"test","wlen":8,"w":6,"h":7,"lut":{"0":"basegame:0","1":"basegame:19","2":"basegame:-1"},"layers":[{"name":"test1","dat":["abZy8000000rlLp0S#Gh%Q1%XFDc>fH&5.j6G~zOdGxCG","abZy8000000rlLp0S#Gh38ntBemYv>C=*G~dGxCG"]},{"name":"test2","dat":["abZy8000000rlLp0S#Gh%Q1%XFDc>fH&5.j6G~zOdGxCG","abZy8000000rlLp0S#Gh38ntBemYv>C=*G~dGxCG"]}]}"""
|
val json = """{"genver":67108864,"id":"test","wlen":8,"w":6,"h":7,"lut":{"0":"basegame:0","1":"basegame:19","2":"basegame:-1"},"layers":[{"name":"test1","dat":["abZy8000000rlLp0S#Gh%Q1%XFDc>fH&5.j6G~zOdGxCG","abZy8000000rlLp0S#Gh38ntBemYv>C=*G~dGxCG"]},{"name":"test2","dat":["abZy8000000rlLp0S#Gh%Q1%XFDc>fH&5.j6G~zOdGxCG","abZy8000000rlLp0S#Gh38ntBemYv>C=*G~dGxCG"]}]}"""
|
||||||
|
|
||||||
val poi = Common.jsoner.fromJson(PointOfInterest().javaClass, json)
|
val poi = Common.jsoner.fromJson(PointOfInterest().javaClass, json).also {
|
||||||
|
it.getReadyToBeUsed(ui.world.tileNameToNumberMap)
|
||||||
|
|
||||||
|
println("==== Test print layer ====")
|
||||||
|
it.layers.forEach { layer ->
|
||||||
|
println("Layer ${layer.name}")
|
||||||
|
println(" Terrain:")
|
||||||
|
for (y in 0 until it.h) {
|
||||||
|
for (x in 0 until it.w) {
|
||||||
|
val tnum = layer.blockLayer[TERRAIN].unsafeGetTile(x, y).toLong()
|
||||||
|
print("$tnum(${ui.world.tileNumberToNameMap[tnum]?.replace("basegame:","b")})\t")
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
println(" Wall:")
|
||||||
|
for (y in 0 until it.h) {
|
||||||
|
for (x in 0 until it.w) {
|
||||||
|
val tnum = layer.blockLayer[WALL].unsafeGetTile(x, y).toLong()
|
||||||
|
print("$tnum(${ui.world.tileNumberToNameMap[tnum]?.replace("basegame:","b")})\t")
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Imported POI: $poi")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,7 +266,15 @@ class ByteArray64(initialSize: Long = BANK_SIZE.toLong()) {
|
|||||||
if (this.size > Integer.MAX_VALUE - 8) // according to OpenJDK; the size itself is VM-dependent
|
if (this.size > Integer.MAX_VALUE - 8) // according to OpenJDK; the size itself is VM-dependent
|
||||||
throw TypeCastException("Impossible cast; too large to fit")
|
throw TypeCastException("Impossible cast; too large to fit")
|
||||||
|
|
||||||
return ByteArray(this.size.toInt()) { this[it.toLong()] }
|
// TODO make it faster using chunks and memcpy
|
||||||
|
// return ByteArray(this.size.toInt()) { this[it.toLong()] }
|
||||||
|
return ByteArray(this.size.toInt()).also { out ->
|
||||||
|
var c = 0
|
||||||
|
this.forEachUsedBanks { usedCount, bytes ->
|
||||||
|
System.arraycopy(bytes, 0, out, c, usedCount)
|
||||||
|
c += usedCount
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeToFile(file: File) {
|
fun writeToFile(file: File) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
|||||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||||
import net.torvald.terrarum.linearSearchBy
|
import net.torvald.terrarum.linearSearchBy
|
||||||
import net.torvald.terrarum.utils.HashArray
|
import net.torvald.terrarum.utils.HashArray
|
||||||
|
import java.io.StringReader
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-10-17.
|
* Created by minjaesong on 2023-10-17.
|
||||||
@@ -20,17 +21,22 @@ class PointOfInterest(
|
|||||||
identifier: String,
|
identifier: String,
|
||||||
width: Int,
|
width: Int,
|
||||||
height: Int,
|
height: Int,
|
||||||
tileNumberToNameMap0: HashArray<ItemID>
|
tileNumberToNameMap0: HashArray<ItemID>,
|
||||||
|
tileNameToNumberMap0: HashMap<ItemID, Int>
|
||||||
) : Json.Serializable {
|
) : Json.Serializable {
|
||||||
|
|
||||||
constructor() : this("undefined", 0,0, HashArray())
|
constructor() : this("undefined", 0,0, HashArray(), HashMap())
|
||||||
|
|
||||||
|
constructor(numberToNameMap: HashArray<ItemID>, nameToNumberMap: HashMap<ItemID, Int>) : this("undefined", 0, 0, numberToNameMap, nameToNumberMap)
|
||||||
|
|
||||||
@Transient var w = width; private set
|
@Transient var w = width; private set
|
||||||
@Transient var h = height; private set
|
@Transient var h = height; private set
|
||||||
@Transient var layers = ArrayList<POILayer>(); private set
|
@Transient var layers = ArrayList<POILayer>(); private set
|
||||||
@Transient var id = identifier; private set
|
@Transient var id = identifier; private set
|
||||||
@Transient var tileNumberToNameMap: HashArray<ItemID> = tileNumberToNameMap0; private set
|
@Transient var tileNumberToNameMap: HashArray<ItemID> = tileNumberToNameMap0; private set
|
||||||
|
@Transient var tileNameToNumberMap: HashMap<ItemID, Int> = tileNameToNumberMap0; private set
|
||||||
|
@Transient lateinit var lutFromJson: HashArray<ItemID>
|
||||||
|
@Transient var wlenFromJson = 0
|
||||||
|
|
||||||
override fun write(json: Json) {
|
override fun write(json: Json) {
|
||||||
val tileSymbolToItemId = HashArray<ItemID>() // exported
|
val tileSymbolToItemId = HashArray<ItemID>() // exported
|
||||||
@@ -74,25 +80,33 @@ class PointOfInterest(
|
|||||||
this.id = jsonData["id"].asString()
|
this.id = jsonData["id"].asString()
|
||||||
this.w = jsonData["w"].asInt()
|
this.w = jsonData["w"].asInt()
|
||||||
this.h = jsonData["h"].asInt()
|
this.h = jsonData["h"].asInt()
|
||||||
this.tileNumberToNameMap = json.readValue(HashArray<ItemID>().javaClass, jsonData["lut"])
|
this.lutFromJson = json.readValue(HashArray<ItemID>().javaClass, jsonData["lut"])
|
||||||
val wlen = jsonData["wlen"].asInt()
|
this.wlenFromJson = jsonData["wlen"].asInt()
|
||||||
|
|
||||||
|
|
||||||
println("read test")
|
println("read test")
|
||||||
println("id: $id, w: $w, h: $h")
|
println("id: $id, w: $w, h: $h, wlen: $wlenFromJson")
|
||||||
println("lut: $tileNumberToNameMap")
|
println("lut: $lutFromJson")
|
||||||
println("==== layers ====")
|
|
||||||
jsonData["layers"].forEachIndexed { index, it ->
|
println("==== layers (bytes) ====")
|
||||||
|
|
||||||
|
// decompress layers
|
||||||
|
jsonData["layers"].forEachIndexed { index, jsonData ->
|
||||||
print("#${index+1}: ")
|
print("#${index+1}: ")
|
||||||
println(it["name"].asString())
|
POILayer().also {
|
||||||
println("layerdata:")
|
it.w = this.w; it.h = this.h; it.id = this.id
|
||||||
it["dat"].forEachIndexed { index, value ->
|
it.read(json, jsonData)
|
||||||
print(" L${if (index == TERRAIN) "terr" else if (index == WALL) "wall" else "unk$index"}: ")
|
layers.add(it)
|
||||||
println(value.asString())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getReadyToBeUsed(itemIDtoTileNum: Map<ItemID, Int>) {
|
||||||
|
layers.forEach {
|
||||||
|
it.getReadyToBeUsed(lutFromJson, itemIDtoTileNum, w, h, wlenFromJson / 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Place the specified layers onto the world. The name of the layers are case-insensitive.
|
* Place the specified layers onto the world. The name of the layers are case-insensitive.
|
||||||
*/
|
*/
|
||||||
@@ -114,10 +128,14 @@ class POILayer(
|
|||||||
) : Json.Serializable {
|
) : Json.Serializable {
|
||||||
constructor() : this("undefined")
|
constructor() : this("undefined")
|
||||||
|
|
||||||
@Transient val name = name
|
@Transient var name = name
|
||||||
@Transient internal lateinit var blockLayer: ArrayList<BlockLayerI16>
|
@Transient internal lateinit var blockLayer: ArrayList<BlockLayerI16>
|
||||||
@Transient internal lateinit var dat: Array<ByteArray>
|
@Transient internal lateinit var dat: Array<ByteArray>
|
||||||
|
|
||||||
|
@Deprecated("Used for debug print", ReplaceWith("name")) @Transient internal var id = ""
|
||||||
|
@Deprecated("Used for debug print") @Transient internal var w = 0
|
||||||
|
@Deprecated("Used for debug print") @Transient internal var h = 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return list of unique tiles, in the form of TileNums
|
* @return list of unique tiles, in the form of TileNums
|
||||||
*/
|
*/
|
||||||
@@ -157,8 +175,6 @@ class POILayer(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts `dat` into `blockLayer` so the Layer can be actually utilised.
|
* Converts `dat` into `blockLayer` so the Layer can be actually utilised.
|
||||||
*
|
|
||||||
* `tileSymbolToItemId[255]` and `tileSymbolToItemId[65535]` should return `Block.NULL`
|
|
||||||
*/
|
*/
|
||||||
fun getReadyToBeUsed(tileSymbolToItemId: HashArray<ItemID>, itemIDtoTileNum: Map<ItemID, Int>, width: Int, height: Int, byteLength: Int) {
|
fun getReadyToBeUsed(tileSymbolToItemId: HashArray<ItemID>, itemIDtoTileNum: Map<ItemID, Int>, width: Int, height: Int, byteLength: Int) {
|
||||||
if (::blockLayer.isInitialized) {
|
if (::blockLayer.isInitialized) {
|
||||||
@@ -168,13 +184,17 @@ class POILayer(
|
|||||||
|
|
||||||
dat.forEachIndexed { layerIndex, layer ->
|
dat.forEachIndexed { layerIndex, layer ->
|
||||||
val currentBlockLayer = BlockLayerI16(width, height).also {
|
val currentBlockLayer = BlockLayerI16(width, height).also {
|
||||||
blockLayer[layerIndex] = it
|
blockLayer.add(it)
|
||||||
}
|
}
|
||||||
for (w in 0 until layer.size / byteLength) {
|
for (w in 0 until layer.size / byteLength) {
|
||||||
val word = if (byteLength == 1) layer[w].toUint() else if (byteLength == 2) layer.toULittleShort(2*w) else throw IllegalArgumentException()
|
val word = if (byteLength == 1) layer[w].toUint() else if (byteLength == 2) layer.toULittleShort(2*w) else throw IllegalArgumentException("Illegal byteLength $byteLength")
|
||||||
val x = w % width
|
val x = w % width
|
||||||
val y = w / width
|
val y = w / width
|
||||||
val tile = itemIDtoTileNum[tileSymbolToItemId[word.toLong()]!!]!!
|
val itemID = tileSymbolToItemId[word.toLong()]!!
|
||||||
|
val tile = if (itemID == Block.NULL)
|
||||||
|
-1
|
||||||
|
else
|
||||||
|
itemIDtoTileNum[itemID]!!
|
||||||
currentBlockLayer.unsafeSetTile(x, y, tile)
|
currentBlockLayer.unsafeSetTile(x, y, tile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,7 +207,7 @@ class POILayer(
|
|||||||
blockLayer.forEachIndexed { layerIndex, layer ->
|
blockLayer.forEachIndexed { layerIndex, layer ->
|
||||||
for (x in 0 until layer.width) { for (y in 0 until layer.height) {
|
for (x in 0 until layer.width) { for (y in 0 until layer.height) {
|
||||||
val tile = layer.unsafeGetTile(x, y)
|
val tile = layer.unsafeGetTile(x, y)
|
||||||
if (tile != -1) {
|
if (tile != -1 && tile != 65535) {
|
||||||
val (wx, wy) = world.coerceXY(x + topLeftX, y + topLeftY)
|
val (wx, wy) = world.coerceXY(x + topLeftX, y + topLeftY)
|
||||||
world.setTileOnLayerUnsafe(layerIndex, wx, wy, tile)
|
world.setTileOnLayerUnsafe(layerIndex, wx, wy, tile)
|
||||||
}
|
}
|
||||||
@@ -202,8 +222,24 @@ class POILayer(
|
|||||||
json.writeValue("dat", dat)
|
json.writeValue("dat", dat)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun read(json: Json?, jsonData: JsonValue?) {
|
override fun read(json: Json, jsonData: JsonValue) {
|
||||||
TODO("Not yet implemented")
|
name = jsonData["name"].asString()
|
||||||
|
|
||||||
|
println(name)
|
||||||
|
|
||||||
|
|
||||||
|
dat = jsonData["dat"].mapIndexed { index, value ->
|
||||||
|
val zipdStr = value.asString()
|
||||||
|
val ba = Common.strToBytes(StringReader(zipdStr)).toByteArray()
|
||||||
|
val lname = "L${if (index == TERRAIN) "terr" else if (index == WALL) "wall" else "unk$index"}"
|
||||||
|
if (ba.size != w * h) throw IllegalStateException("Layer size mismatch: expected ${w*h} but got ${ba.size} on POI $id Layer $name $lname")
|
||||||
|
|
||||||
|
print(" $lname: ")
|
||||||
|
print("(${ba.size})")
|
||||||
|
println("[${ba.joinToString()}]")
|
||||||
|
|
||||||
|
ba
|
||||||
|
}.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user