mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
poi wip
This commit is contained in:
@@ -14,12 +14,16 @@ import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||
import net.torvald.terrarum.gameworld.BlockLayerI16
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import net.torvald.terrarum.serialise.PointOfInterest
|
||||
import net.torvald.terrarum.serialise.POILayer
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
import net.torvald.terrarum.ui.UINSMenu
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
@@ -34,7 +38,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
- File
|
||||
- New Flat ter.
|
||||
- New Rand. ter.
|
||||
- Export…
|
||||
- Export… : net.torvald.terrarum.modulebasegame.YamlCommandToolExportTest
|
||||
- Import…
|
||||
- Save World…
|
||||
- Load World…
|
||||
@@ -698,3 +702,13 @@ class YamlCommandToolToggleMarqueeOverlay : YamlInvokable {
|
||||
(args[0] as BuildingMaker).showSelection = !(args[0] as BuildingMaker).showSelection
|
||||
}
|
||||
}
|
||||
|
||||
class YamlCommandToolExportTest : YamlInvokable {
|
||||
override fun invoke(args: Array<Any>) {
|
||||
val a = PointOfInterest("test", 10, 10)
|
||||
val dat = BlockLayerI16(10, 10)
|
||||
a.layers.add(POILayer("layerr1").also { it.blockLayer.add(BlockLayerI16(10, 10)) })
|
||||
a.layers.add(POILayer("layerr2").also { it.blockLayer.add(BlockLayerI16(10, 10)) })
|
||||
println(Common.jsoner.toJson(a))
|
||||
}
|
||||
}
|
||||
119
src/net/torvald/terrarum/serialise/PointOfInterest.kt
Normal file
119
src/net/torvald/terrarum/serialise/PointOfInterest.kt
Normal file
@@ -0,0 +1,119 @@
|
||||
package net.torvald.terrarum.serialise
|
||||
|
||||
import com.badlogic.gdx.utils.Json
|
||||
import com.badlogic.gdx.utils.JsonValue
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.BlockLayerI16
|
||||
import net.torvald.terrarum.utils.HashArray
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2023-10-17.
|
||||
*/
|
||||
class PointOfInterest(
|
||||
identifier: String,
|
||||
width: Int,
|
||||
height: Int
|
||||
) : Json.Serializable {
|
||||
|
||||
constructor() : this("undefined", 0,0)
|
||||
|
||||
@Transient val w = width
|
||||
@Transient val h = height
|
||||
@Transient val layers = ArrayList<POILayer>()
|
||||
@Transient val id = identifier
|
||||
|
||||
override fun write(json: Json) {
|
||||
val tileSymbolToItemId = HashArray<ItemID>() // exported
|
||||
val tilenumToItemID = HashMap<Int, ItemID>() // not exported
|
||||
|
||||
// TODO populate above vars. Block.NULL is always integer -1
|
||||
|
||||
val itemIDtoTileSym = tileSymbolToItemId.map { it.value to it.key }.toMap()
|
||||
|
||||
val wordSize = if (tileSymbolToItemId.size >= 255) 16 else 8
|
||||
layers.forEach { it.getReadyForSerialisation(tilenumToItemID, itemIDtoTileSym, wordSize / 8) }
|
||||
|
||||
json.setTypeName(null)
|
||||
json.writeValue("genver", TerrarumAppConfiguration.VERSION_RAW)
|
||||
json.writeValue("id", id)
|
||||
json.writeValue("wlen", wordSize)
|
||||
json.writeValue("w", w)
|
||||
json.writeValue("h", h)
|
||||
json.writeValue("lut", tileSymbolToItemId)
|
||||
json.writeValue("layers", layers)
|
||||
}
|
||||
|
||||
override fun read(json: Json, jsonData: JsonValue) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
class POILayer(
|
||||
name: String
|
||||
) : Json.Serializable {
|
||||
constructor() : this("undefined")
|
||||
|
||||
@Transient val name = name
|
||||
@Transient val blockLayer = ArrayList<BlockLayerI16>()
|
||||
@Transient private lateinit var dat: Array<ByteArray>
|
||||
|
||||
fun getUniqueTiles(): List<Int> {
|
||||
return blockLayer.flatMap { layer ->
|
||||
(0 until layer.height * layer.width).map { layer.unsafeGetTile(it % layer.width, it / layer.width) }
|
||||
}.toSet().toList().sorted()
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts `blockLayer` into `dat` internally, the hidden property used for the serialisation
|
||||
*
|
||||
* Tilenum: tile number in the block layer, identical to the any other block layers
|
||||
* TileSymbol: condensed version of the Tilenum, of which the higheset number is equal to the number of unique tiles used in the layer
|
||||
*/
|
||||
fun getReadyForSerialisation(tilenumToItemID: Map<Int, ItemID>, itemIDtoTileSym: Map<ItemID, Long>, byteLength: Int) {
|
||||
dat = blockLayer.map { layer ->
|
||||
ByteArray(layer.width * layer.height * byteLength) { i ->
|
||||
if (byteLength == 1) {
|
||||
itemIDtoTileSym[tilenumToItemID[layer.unsafeGetTile(i % layer.width, i / layer.width)]!!]!!.toByte()
|
||||
}
|
||||
else if (byteLength == 2) {
|
||||
val tileSym = itemIDtoTileSym[tilenumToItemID[layer.unsafeGetTile((i/2) % layer.width, (i/2) / layer.width)]!!]!!
|
||||
if (i % 2 == 0) tileSym.and(255).toByte() else tileSym.ushr(8).and(255).toByte()
|
||||
}
|
||||
else throw IllegalArgumentException()
|
||||
}
|
||||
}.toTypedArray()
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts `dat` into `blockLayer` so the Layer can be actually utilised.
|
||||
*/
|
||||
fun getReadyToBeUsed(tileSymbolToItemId: HashArray<ItemID>, itemIDtoTileNum: Map<ItemID, Int>, width: Int, height: Int, byteLength: Int) {
|
||||
blockLayer.forEach { it.dispose() }
|
||||
blockLayer.clear()
|
||||
|
||||
dat.forEachIndexed { layerIndex, layer ->
|
||||
val currentBlockLayer = BlockLayerI16(width, height).also {
|
||||
blockLayer[layerIndex] = it
|
||||
}
|
||||
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 x = w % width
|
||||
val y = w / width
|
||||
val tile = itemIDtoTileNum[tileSymbolToItemId[word.toLong()]!!]!!
|
||||
currentBlockLayer.unsafeSetTile(x, y, tile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun write(json: Json) {
|
||||
json.setTypeName(null)
|
||||
json.writeValue("name", name)
|
||||
json.writeValue("dat", dat)
|
||||
}
|
||||
|
||||
override fun read(json: Json?, jsonData: JsonValue?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
||||
35
work_files/DataFormats/poi.md
Normal file
35
work_files/DataFormats/poi.md
Normal file
@@ -0,0 +1,35 @@
|
||||
POI (Point of Interest) is a placement of blocks that can be used by the world generator.
|
||||
|
||||
POIs are serialised as following:
|
||||
|
||||
```json
|
||||
{
|
||||
"genver": 1234567890, /* game version in Int64 */
|
||||
"id": "test_struct_with_enumerable_variations",
|
||||
"wlen": 8, /* word length of the tile number. Can be 8 or 16 */
|
||||
"lut": {"0": "basegame:0", "1": "basegame:48"},
|
||||
"w": 7, "h": 4,
|
||||
"layers": [ /* order matters! */
|
||||
{"name": "base", "dat": [
|
||||
"...layer_0.gz.b85", /* each byte matches what's on the LUT, except 0xFF (0xFFFF if wlen=16) always refers to the null tile. Endianness: little */
|
||||
"...layer_1.gz.b85"
|
||||
]},
|
||||
{"name": "varianceA", "dat": [
|
||||
"...layer_0.gz.b85",
|
||||
"...layer_1.gz.b85"
|
||||
]},
|
||||
{"name": "varianceB", "dat": [
|
||||
"...layer_0.gz.b85",
|
||||
"...layer_1.gz.b85"
|
||||
]},
|
||||
{"name": "varianceC", "dat": [
|
||||
"...layer_0.gz.b85",
|
||||
"...layer_1.gz.b85"
|
||||
]},
|
||||
{"name": "overlay", "dat": [
|
||||
"...layer_0.gz.b85",
|
||||
"...layer_1.gz.b85"
|
||||
]}
|
||||
]
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user