the-flattening wip

This commit is contained in:
minjaesong
2021-02-10 17:48:01 +09:00
parent 73acaea025
commit 8fdc11288c
21 changed files with 513 additions and 503 deletions

View File

@@ -21,4 +21,29 @@ Actors range in-depth
|0x6000_0000..0x6FFF_FFFF|Rendered front (e.g. fake tile)| |0x6000_0000..0x6FFF_FFFF|Rendered front (e.g. fake tile)|
|0x7000_0000..0x7FFF_FFFF|Rendered as screen overlay, not affected by light nor environment overlays| |0x7000_0000..0x7FFF_FFFF|Rendered as screen overlay, not affected by light nor environment overlays|
Actor IDs are assigned in 256 groups, single actor can have 256 sub-actors Actor IDs are assigned in 256 groups, single actor can have 256 sub-actors
## Prefix-ID Referencing
Every blocks and items have Prefix-ID Referencing scheme, which is defined as follows:
```<prefix>@<modname>:<integer-id>```
where prefix is predefined (see below), integer-id is arbitrarily chosen.
### Prefixes
|Name|Description|
|----|-----------|
|wall|Wall|
|wire|Wire|
|item|Item (Static)|
Note: BlockCodex and ItemCodex will not store prefix part of the ID, as blocks and walls are identical in properties
### Predefined Modname
|Name|Description|
|----|-----------|
|dyn|Dynamic Item|
|actor|Actor As an Item|
|virt|Virtual Tile Number|

View File

@@ -1,7 +1,7 @@
"id";"classname" "id";"classname"
"135168";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeCopper" "0";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeCopper"
"135169";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeIron" "1";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeIron"
"135170";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeSteel" "2";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeSteel"
"135171";"net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire" "3";"net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire"
"135172";"net.torvald.terrarum.modulebasegame.gameitems.TikiTorchTester" "4";"net.torvald.terrarum.modulebasegame.gameitems.TikiTorchTester"
"135173";"net.torvald.terrarum.modulebasegame.gameitems.ItemCraftingTable" "5";"net.torvald.terrarum.modulebasegame.gameitems.ItemCraftingTable"
1 id classname
2 135168 0 net.torvald.terrarum.modulebasegame.gameitems.PickaxeCopper
3 135169 1 net.torvald.terrarum.modulebasegame.gameitems.PickaxeIron
4 135170 2 net.torvald.terrarum.modulebasegame.gameitems.PickaxeSteel
5 135171 3 net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire
6 135172 4 net.torvald.terrarum.modulebasegame.gameitems.TikiTorchTester
7 135173 5 net.torvald.terrarum.modulebasegame.gameitems.ItemCraftingTable

View File

@@ -111,7 +111,7 @@ object DefaultConfig {
// settings regarding debugger // settings regarding debugger
val buildingMakerFavs = JsonArray() val buildingMakerFavs = JsonArray()
intArrayOf( arrayOf(
Block.GLASS_CRUDE, Block.GLASS_CRUDE,
Block.PLANK_NORMAL, Block.PLANK_NORMAL,
Block.PLANK_BIRCH, Block.PLANK_BIRCH,
@@ -120,9 +120,10 @@ object DefaultConfig {
Block.STONE_TILE_WHITE, Block.STONE_TILE_WHITE,
Block.TORCH, Block.TORCH,
Block.PLANK_NORMAL + BlockCodex.MAX_TERRAIN_TILES, "wall@" + Block.PLANK_NORMAL,
Block.PLANK_BIRCH + BlockCodex.MAX_TERRAIN_TILES, "wall@" + Block.PLANK_BIRCH,
Block.GLASS_CRUDE + BlockCodex.MAX_TERRAIN_TILES).forEach { "wall@" + Block.GLASS_CRUDE
).forEach {
buildingMakerFavs.add(it) buildingMakerFavs.add(it)
} }
jsonObject.add("buildingmakerfavs", buildingMakerFavs) jsonObject.add("buildingmakerfavs", buildingMakerFavs)

View File

@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.utils.Queue import com.badlogic.gdx.utils.Queue
import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.realestate.LandUtil
@@ -141,7 +142,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
* *
* Queueing schema is used to make sure things are synchronised. * Queueing schema is used to make sure things are synchronised.
*/ */
open fun queueTerrainChangedEvent(old: Int, new: Int, position: Long) { open fun queueTerrainChangedEvent(old: ItemID, new: ItemID, position: Long) {
val (x, y) = LandUtil.resolveBlockAddr(world, position) val (x, y) = LandUtil.resolveBlockAddr(world, position)
terrainChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y)) terrainChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
} }
@@ -149,7 +150,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
/** /**
* Wall version of terrainChanged() event * Wall version of terrainChanged() event
*/ */
open fun queueWallChangedEvent(old: Int, new: Int, position: Long) { open fun queueWallChangedEvent(old: ItemID, new: ItemID, position: Long) {
val (x, y) = LandUtil.resolveBlockAddr(world, position) val (x, y) = LandUtil.resolveBlockAddr(world, position)
wallChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y)) wallChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
} }
@@ -160,7 +161,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
* @param old previous settings of conduits in bit set format. * @param old previous settings of conduits in bit set format.
* @param new current settings of conduits in bit set format. * @param new current settings of conduits in bit set format.
*/ */
open fun queueWireChangedEvent(old: Int, new: Int, position: Long) { open fun queueWireChangedEvent(old: ItemID, new: ItemID, position: Long) {
val (x, y) = LandUtil.resolveBlockAddr(world, position) val (x, y) = LandUtil.resolveBlockAddr(world, position)
wireChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y)) wireChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
} }
@@ -252,7 +253,7 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
data class BlockChangeQueueItem(val old: Int, val new: Int, val posX: Int, val posY: Int) data class BlockChangeQueueItem(val old: ItemID, val new: ItemID, val posX: Int, val posY: Int)
open fun sendNotification(messages: Array<String>) {} open fun sendNotification(messages: Array<String>) {}
open fun sendNotification(messages: List<String>) {} open fun sendNotification(messages: List<String>) {}

View File

@@ -178,16 +178,19 @@ object ModMgr {
} }
/** Get a common file (literal file or directory) from all the installed mods. Files are guaranteed to exist. If a mod does not /** Get a common file (literal file or directory) from all the installed mods. Files are guaranteed to exist. If a mod does not
* contain the file, the mod will be skipped. */ * contain the file, the mod will be skipped.
fun getFilesFromEveryMod(path: String): List<File> { *
* @return List of pairs<modname, file>
*/
fun getFilesFromEveryMod(path: String): List<Pair<String, File>> {
val path = path.sanitisePath() val path = path.sanitisePath()
val moduleNames = moduleInfo.keys.toList() val moduleNames = moduleInfo.keys.toList()
val filesList = ArrayList<File>() val filesList = ArrayList<Pair<String, File>>()
moduleNames.forEach { moduleNames.forEach {
val file = File(getPath(it, path)) val file = File(getPath(it, path))
if (file.exists()) filesList.add(file) if (file.exists()) filesList.add(it to file)
} }
return filesList.toList() return filesList.toList()
@@ -196,16 +199,18 @@ object ModMgr {
/** Get a common file (literal file or directory) from all the installed mods. Files are guaranteed to exist. If a mod does not /** Get a common file (literal file or directory) from all the installed mods. Files are guaranteed to exist. If a mod does not
* contain the file, the mod will be skipped. * contain the file, the mod will be skipped.
* *
* Returning files are read-only. */ * Returning files are read-only.
fun getGdxFilesFromEveryMod(path: String): List<FileHandle> { * @return List of pairs<modname, filehandle>
*/
fun getGdxFilesFromEveryMod(path: String): List<Pair<String, FileHandle>> {
val path = path.sanitisePath() val path = path.sanitisePath()
val moduleNames = moduleInfo.keys.toList() val moduleNames = moduleInfo.keys.toList()
val filesList = ArrayList<FileHandle>() val filesList = ArrayList<Pair<String, FileHandle>>()
moduleNames.forEach { moduleNames.forEach {
val file = Gdx.files.internal(getPath(it, path)) val file = Gdx.files.internal(getPath(it, path))
if (file.exists()) filesList.add(file) if (file.exists()) filesList.add(it to file)
} }
return filesList.toList() return filesList.toList()
@@ -231,15 +236,16 @@ object ModMgr {
val csv = CSVFetcher.readFromModule(module, itemPath + "itemid.csv") val csv = CSVFetcher.readFromModule(module, itemPath + "itemid.csv")
csv.forEach { csv.forEach {
val className = it["classname"].toString() val className = it["classname"].toString()
val itemID = it["id"].toInt() val internalID = it["id"].toInt()
val itemName = "item@$module:$internalID"
printdbg(this, "Reading item #$itemID with className $className") printdbg(this, "Reading item #$internalID with className $className")
val loadedClass = Class.forName(className) val loadedClass = Class.forName(className)
val loadedClassConstructor = loadedClass.getConstructor(ItemID::class.java) val loadedClassConstructor = loadedClass.getConstructor(ItemID::class.java)
val loadedClassInstance = loadedClassConstructor.newInstance(itemID) val loadedClassInstance = loadedClassConstructor.newInstance(internalID)
ItemCodex[itemID] = loadedClassInstance as GameItem ItemCodex[itemName] = loadedClassInstance as GameItem
} }
} }
} }

View File

@@ -22,4 +22,6 @@ object ReferencingRanges {
val VIRTUAL_TILES = -2 downTo -1048576 // index of -1 breaks things for some reason :( val VIRTUAL_TILES = -2 downTo -1048576 // index of -1 breaks things for some reason :(
val PREFIX_DYNAMICITEM = "dyn:"
val PREFIX_ACTORITEM = "actor:"
} }

View File

@@ -5,128 +5,128 @@ package net.torvald.terrarum.blockproperties
*/ */
object Block { object Block {
const val AIR = 0 // hard coded; this is the standard const val AIR = "basegame:0" // hard coded; this is the standard
const val STONE = 16 const val STONE = "basegame:16"
const val STONE_QUARRIED = 17 const val STONE_QUARRIED = "basegame:17"
const val STONE_TILE_WHITE = 18 const val STONE_TILE_WHITE = "basegame:18"
const val STONE_BRICKS = 19 const val STONE_BRICKS = "basegame:19"
const val DIRT = 32 const val DIRT = "basegame:32"
const val GRASS = 33 const val GRASS = "basegame:33"
const val GRASSWALL = 34 const val GRASSWALL = "basegame:34"
const val PLANK_NORMAL = 48 const val PLANK_NORMAL = "basegame:48"
const val PLANK_EBONY = 49 const val PLANK_EBONY = "basegame:49"
const val PLANK_BIRCH = 50 const val PLANK_BIRCH = "basegame:50"
const val PLANK_BLOODROSE = 51 const val PLANK_BLOODROSE = "basegame:51"
const val TRUNK_NORMAL = 64 const val TRUNK_NORMAL = "basegame:64"
const val TRUNK_EBONY = 65 const val TRUNK_EBONY = "basegame:65"
const val TRUNK_BIRCH = 66 const val TRUNK_BIRCH = "basegame:66"
const val TRUNK_BLOODROSE = 67 const val TRUNK_BLOODROSE = "basegame:67"
const val SAND = 80 const val SAND = "basegame:80"
const val SAND_WHITE = 81 const val SAND_WHITE = "basegame:81"
const val SAND_RED = 82 const val SAND_RED = "basegame:82"
const val SAND_DESERT = 83 const val SAND_DESERT = "basegame:83"
const val SAND_BLACK = 84 const val SAND_BLACK = "basegame:84"
const val SAND_GREEN = 85 const val SAND_GREEN = "basegame:85"
const val GRAVEL = 96 const val GRAVEL = "basegame:96"
const val GRAVEL_GREY = 97 const val GRAVEL_GREY = "basegame:97"
const val ORE_COPPER = 112 const val ORE_COPPER = "basegame:112"
const val ORE_IRON = 113 const val ORE_IRON = "basegame:113"
const val ORE_GOLD = 114 const val ORE_GOLD = "basegame:114"
const val ORE_SILVER = 115 const val ORE_SILVER = "basegame:115"
const val ORE_ILMENITE = 116 const val ORE_ILMENITE = "basegame:116"
const val ORE_AURICHALCUM = 117 const val ORE_AURICHALCUM = "basegame:117"
const val RAW_RUBY = 128 const val RAW_RUBY = "basegame:128"
const val RAW_EMERALD = 129 const val RAW_EMERALD = "basegame:129"
const val RAW_SAPPHIRE = 130 const val RAW_SAPPHIRE = "basegame:130"
const val RAW_TOPAZ = 131 const val RAW_TOPAZ = "basegame:131"
const val RAW_DIAMOND = 132 const val RAW_DIAMOND = "basegame:132"
const val RAW_AMETHYST = 133 const val RAW_AMETHYST = "basegame:133"
const val SNOW = 144 const val SNOW = "basegame:144"
const val ICE_FRAGILE = 145 const val ICE_FRAGILE = "basegame:145"
const val ICE_NATURAL = 146 const val ICE_NATURAL = "basegame:146"
const val ICE_MAGICAL = 147 const val ICE_MAGICAL = "basegame:147"
const val GLASS_CRUDE = 148 const val GLASS_CRUDE = "basegame:148"
const val GLASS_CLEAN = 149 const val GLASS_CLEAN = "basegame:149"
const val PLATFORM_STONE = 160 const val PLATFORM_STONE = "basegame:160"
const val PLATFORM_WOODEN = 161 const val PLATFORM_WOODEN = "basegame:161"
const val PLATFORM_EBONY = 162 const val PLATFORM_EBONY = "basegame:162"
const val PLATFORM_BIRCH = 163 const val PLATFORM_BIRCH = "basegame:163"
const val PLATFORM_BLOODROSE = 164 const val PLATFORM_BLOODROSE = "basegame:164"
const val TORCH = 176 const val TORCH = "basegame:176"
const val TORCH_FROST = 177 const val TORCH_FROST = "basegame:177"
const val TORCH_OFF = 192 const val TORCH_OFF = "basegame:192"
const val TORCH_FROST_OFF = 193 const val TORCH_FROST_OFF = "basegame:193"
const val ILLUMINATOR_WHITE = 208 const val ILLUMINATOR_WHITE = "basegame:208"
const val ILLUMINATOR_YELLOW = 209 const val ILLUMINATOR_YELLOW = "basegame:209"
const val ILLUMINATOR_ORANGE = 210 const val ILLUMINATOR_ORANGE = "basegame:210"
const val ILLUMINATOR_RED = 211 const val ILLUMINATOR_RED = "basegame:211"
const val ILLUMINATOR_FUCHSIA = 212 const val ILLUMINATOR_FUCHSIA = "basegame:212"
const val ILLUMINATOR_PURPLE = 213 const val ILLUMINATOR_PURPLE = "basegame:213"
const val ILLUMINATOR_BLUE = 214 const val ILLUMINATOR_BLUE = "basegame:214"
const val ILLUMINATOR_CYAN = 215 const val ILLUMINATOR_CYAN = "basegame:215"
const val ILLUMINATOR_GREEN = 216 const val ILLUMINATOR_GREEN = "basegame:216"
const val ILLUMINATOR_GREEN_DARK = 217 const val ILLUMINATOR_GREEN_DARK = "basegame:217"
const val ILLUMINATOR_BROWN = 218 const val ILLUMINATOR_BROWN = "basegame:218"
const val ILLUMINATOR_TAN = 219 const val ILLUMINATOR_TAN = "basegame:219"
const val ILLUMINATOR_GREY_LIGHT = 220 const val ILLUMINATOR_GREY_LIGHT = "basegame:220"
const val ILLUMINATOR_GREY_MED = 221 const val ILLUMINATOR_GREY_MED = "basegame:221"
const val ILLUMINATOR_GREY_DARK = 222 const val ILLUMINATOR_GREY_DARK = "basegame:222"
const val ILLUMINATOR_BLACK = 223 const val ILLUMINATOR_BLACK = "basegame:223"
const val ILLUMINATOR_WHITE_OFF = 224 const val ILLUMINATOR_WHITE_OFF = "basegame:224"
const val ILLUMINATOR_YELLOW_OFF = 225 const val ILLUMINATOR_YELLOW_OFF = "basegame:225"
const val ILLUMINATOR_ORANGE_OFF = 226 const val ILLUMINATOR_ORANGE_OFF = "basegame:226"
const val ILLUMINATOR_RED_OFF = 227 const val ILLUMINATOR_RED_OFF = "basegame:227"
const val ILLUMINATOR_FUCHSIA_OFF = 228 const val ILLUMINATOR_FUCHSIA_OFF = "basegame:228"
const val ILLUMINATOR_PURPLE_OFF = 229 const val ILLUMINATOR_PURPLE_OFF = "basegame:229"
const val ILLUMINATOR_BLUE_OFF = 230 const val ILLUMINATOR_BLUE_OFF = "basegame:230"
const val ILLUMINATOR_CYAN_OFF = 231 const val ILLUMINATOR_CYAN_OFF = "basegame:231"
const val ILLUMINATOR_GREEN_OFF = 232 const val ILLUMINATOR_GREEN_OFF = "basegame:232"
const val ILLUMINATOR_GREEN_DARK_OFF = 233 const val ILLUMINATOR_GREEN_DARK_OFF = "basegame:233"
const val ILLUMINATOR_BROWN_OFF = 234 const val ILLUMINATOR_BROWN_OFF = "basegame:234"
const val ILLUMINATOR_TAN_OFF = 235 const val ILLUMINATOR_TAN_OFF = "basegame:235"
const val ILLUMINATOR_GREY_LIGHT_OFF = 236 const val ILLUMINATOR_GREY_LIGHT_OFF = "basegame:236"
const val ILLUMINATOR_GREY_MED_OFF = 237 const val ILLUMINATOR_GREY_MED_OFF = "basegame:237"
const val ILLUMINATOR_GREY_DARK_OFF = 238 const val ILLUMINATOR_GREY_DARK_OFF = "basegame:238"
const val ILLUMINATOR_BLACK_OFF = 239 const val ILLUMINATOR_BLACK_OFF = "basegame:239"
const val SANDSTONE = 240 const val SANDSTONE = "basegame:240"
const val SANDSTONE_WHITE = 241 const val SANDSTONE_WHITE = "basegame:241"
const val SANDSTONE_RED = 242 const val SANDSTONE_RED = "basegame:242"
const val SANDSTONE_DESERT = 243 const val SANDSTONE_DESERT = "basegame:243"
const val SANDSTONE_BLACK = 244 const val SANDSTONE_BLACK = "basegame:244"
const val SANDSTONE_GREEN = 245 const val SANDSTONE_GREEN = "basegame:245"
const val LANTERN = 256 const val LANTERN = "basegame:256"
const val SUNSTONE = 257 const val SUNSTONE = "basegame:257"
const val DAYLIGHT_CAPACITOR = 258 const val DAYLIGHT_CAPACITOR = "basegame:258"
const val ACTORBLOCK_NO_COLLISION = 4091 const val ACTORBLOCK_NO_COLLISION = "basegame:4091"
const val ACTORBLOCK_FULL_COLLISION = 4092 const val ACTORBLOCK_FULL_COLLISION = "basegame:4092"
const val ACTORBLOCK_ALLOW_MOVE_DOWN = 4093 const val ACTORBLOCK_ALLOW_MOVE_DOWN = "basegame:4093"
const val ACTORBLOCK_NO_PASS_RIGHT = 4094 const val ACTORBLOCK_NO_PASS_RIGHT = "basegame:4094"
const val ACTORBLOCK_NO_PASS_LEFT = 4095 const val ACTORBLOCK_NO_PASS_LEFT = "basegame:4095"
const val LAVA = 4094 const val LAVA = "basegame:4094"
const val WATER = 4095 const val WATER = "basegame:4095"
const val NULL = -1 const val NULL = "basegame:-1"
val actorblocks = listOf( val actorblocks = listOf(
ACTORBLOCK_NO_COLLISION, ACTORBLOCK_NO_COLLISION,

View File

@@ -5,6 +5,7 @@ import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.AppLoader.printmsg import net.torvald.terrarum.AppLoader.printmsg
import net.torvald.terrarum.ReferencingRanges import net.torvald.terrarum.ReferencingRanges
import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.gameworld.FluidType import net.torvald.terrarum.gameworld.FluidType
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.utils.CSVFetcher import net.torvald.terrarum.utils.CSVFetcher
@@ -18,12 +19,12 @@ import java.io.IOException
*/ */
object BlockCodex { object BlockCodex {
private var blockProps = HashMap<Int, BlockProp>() private var blockProps = HashMap<ItemID, BlockProp>()
val dynamicLights = SortedArrayList<Int>() // does not include virtual ones val dynamicLights = SortedArrayList<ItemID>() // does not include virtual ones
/** 65536 */ /** 65536 */
val MAX_TERRAIN_TILES = GameWorld.TILES_SUPPORTED //val MAX_TERRAIN_TILES = GameWorld.TILES_SUPPORTED
private val nullProp = BlockProp() private val nullProp = BlockProp()
@@ -32,12 +33,9 @@ object BlockCodex {
// fake props for "randomised" dynamic lights // fake props for "randomised" dynamic lights
const val DYNAMIC_RANDOM_CASES = 64 const val DYNAMIC_RANDOM_CASES = 64
var virtualPropsCount = 0 private var virtualTileCursor = 0
private set val tileToVirtual = HashMap<ItemID, List<ItemID>>()
/** always points to the HIGHEST prop ID. <Original ID, Virtual ID> */ val virtualToTile = HashMap<ItemID, ItemID>()
val dynamicToVirtualPropMapping = ArrayList<Pair<Int, Int>>()
/** for random access dont iterate over this */
val dynamicToVirtualMap = hashMapOf<Int, Int>()
/** /**
* Later entry (possible from other modules) will replace older ones * Later entry (possible from other modules) will replace older ones
@@ -56,27 +54,29 @@ object BlockCodex {
setProp(blockProps[intVal(it, "id")], it) setProp(blockProps[intVal(it, "id")], it)
}*/ }*/
val id = intVal(it, "id") val numericID = intVal(it, "id")
setProp(id, it) setProp(module, numericID, it)
val tileId = "tile@$module:$numericID"
// register tiles with dynamic light // register tiles with dynamic light
if ((blockProps[id]?.dynamicLuminosityFunction ?: 0) != 0) { if ((blockProps[tileId]?.dynamicLuminosityFunction ?: 0) != 0) {
dynamicLights.add(id) dynamicLights.add(tileId)
// add virtual props for dynamic lights // add virtual props for dynamic lights
val virtualIDMax = ReferencingRanges.VIRTUAL_TILES.first - virtualPropsCount val virtualChunk = ArrayList<ItemID>()
dynamicToVirtualPropMapping.add(id to virtualIDMax) repeat(DYNAMIC_RANDOM_CASES) { _ ->
dynamicToVirtualMap[id] = virtualIDMax val virtualID = "virt:$virtualTileCursor"
repeat(DYNAMIC_RANDOM_CASES) { i ->
setProp(virtualIDMax - i, it)
printdbg(this, "Block ID $id -> Virtual ID ${virtualIDMax - i}, baseLum: ${blockProps[virtualIDMax - i]?.baseLumCol}")
virtualPropsCount += 1 virtualToTile[virtualID] = tileId
virtualChunk.add(virtualID)
setProp("virt", virtualTileCursor, it)
printdbg(this, "Block ID $tileId -> Virtual ID $virtualID, baseLum: ${blockProps[virtualID]?.baseLumCol}")
virtualTileCursor += 1
} }
tileToVirtual[tileId] = virtualChunk.sorted().toList()
} }
if (id > highestNumber)
highestNumber = id
} }
} }
catch (e: IOException) { catch (e: IOException) {
@@ -84,6 +84,8 @@ object BlockCodex {
} }
} }
fun getAll() = blockProps.values
/*fun get(index: Int): BlockProp { /*fun get(index: Int): BlockProp {
try { try {
return blockProps[index] return blockProps[index]
@@ -97,7 +99,7 @@ object BlockCodex {
} }
}*/ }*/
operator fun get(rawIndex: Int?): BlockProp { /*operator fun get(rawIndex: Int?): BlockProp {
if (rawIndex == null || rawIndex == Block.NULL) { if (rawIndex == null || rawIndex == Block.NULL) {
return nullProp return nullProp
} }
@@ -108,31 +110,45 @@ object BlockCodex {
catch (e: NullPointerException) { catch (e: NullPointerException) {
throw NullPointerException("Blockprop with raw id $rawIndex does not exist.") throw NullPointerException("Blockprop with raw id $rawIndex does not exist.")
} }
} }*/
operator fun get(blockID: ItemID?): BlockProp {
operator fun get(fluidType: FluidType?): BlockProp { if (blockID == null || blockID == "basegame:"+Block.NULL) {
if (fluidType == null || fluidType.value == 0) { return nullProp
return blockProps[Block.AIR]!!
} }
try { try {
return blockProps[fluidType.abs() + GameWorld.TILES_SUPPORTED - 1]!! return blockProps[blockID]!!
} }
catch (e: NullPointerException) { catch (e: NullPointerException) {
throw NullPointerException("Blockprop with raw id $fluidType does not exist.") throw NullPointerException("Blockprop with id $blockID does not exist.")
} }
} }
fun getOrNull(rawIndex: Int?): BlockProp? {//<O> operator fun get(fluidType: FluidType?): BlockProp {
return blockProps[rawIndex] // TODO fluid from other mods
if (fluidType == null || fluidType.value == 0) {
return blockProps["basegame:"+Block.AIR]!!
}
try {
return blockProps["basegame:${fluidType.abs() + GameWorld.TILES_SUPPORTED - 1}"]!!
}
catch (e: NullPointerException) {
throw NullPointerException("Blockprop with id $fluidType does not exist.")
}
} }
private fun setProp(key: Int, record: CSVRecord) { fun getOrNull(blockID: ItemID?): BlockProp? {//<O>
return blockProps[blockID]
}
private fun setProp(modname: String, key: Int, record: CSVRecord) {
val prop = BlockProp() val prop = BlockProp()
prop.nameKey = record.get("name") prop.nameKey = record.get("name")
prop.id = if (key == -1) 0 else intVal(record, "id") prop.id = "$modname:${(if (key == -1) 0 else intVal(record, "id"))}"
prop.drop = intVal(record, "drop") prop.drop = "$modname:${intVal(record, "drop")}"
prop.shadeColR = floatVal(record, "shdr") prop.shadeColR = floatVal(record, "shdr")
prop.shadeColG = floatVal(record, "shdg") prop.shadeColG = floatVal(record, "shdg")
@@ -163,9 +179,9 @@ object BlockCodex {
prop.dynamicLuminosityFunction = intVal(record, "dlfn") prop.dynamicLuminosityFunction = intVal(record, "dlfn")
blockProps[key] = prop blockProps["$modname:$key"] = prop
printmsg(this, "${intVal(record, "id")}\t" + prop.nameKey) printmsg(this, "$modname:${intVal(record, "id")}\t" + prop.nameKey)
} }
} }

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.blockproperties
import net.torvald.gdx.graphics.Cvec import net.torvald.gdx.graphics.Cvec
import net.torvald.random.XXHash32 import net.torvald.random.XXHash32
import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.gameworld.fmod import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.serialise.toLittle import net.torvald.terrarum.serialise.toLittle
@@ -10,7 +11,7 @@ import net.torvald.terrarum.serialise.toLittle
*/ */
class BlockProp { class BlockProp {
var id: Int = 0 var id: ItemID = ""
var nameKey: String = "" var nameKey: String = ""
@@ -62,14 +63,14 @@ class BlockProp {
baseLumCol baseLumCol
} else { } else {
val offset = XXHash32.hash(((x and 0xFFFF).shl(16) or (y and 0xFFFF)).toLittle(), 10000).fmod(BlockCodex.DYNAMIC_RANDOM_CASES) val offset = XXHash32.hash(((x and 0xFFFF).shl(16) or (y and 0xFFFF)).toLittle(), 10000).fmod(BlockCodex.DYNAMIC_RANDOM_CASES)
BlockCodex[BlockCodex.dynamicToVirtualMap[id]!! - offset]._lumCol BlockCodex[BlockCodex.tileToVirtual[id]!![offset]]._lumCol
} }
fun getLumCol(x: Int, y: Int, channel: Int): Float = if (dynamicLuminosityFunction == 0) { fun getLumCol(x: Int, y: Int, channel: Int): Float = if (dynamicLuminosityFunction == 0) {
baseLumCol.getElem(channel) baseLumCol.getElem(channel)
} else { } else {
val offset = XXHash32.hash(((x and 0xFFFF).shl(16) or (y and 0xFFFF)).toLittle(), 10000).fmod(BlockCodex.DYNAMIC_RANDOM_CASES) val offset = XXHash32.hash(((x and 0xFFFF).shl(16) or (y and 0xFFFF)).toLittle(), 10000).fmod(BlockCodex.DYNAMIC_RANDOM_CASES)
BlockCodex[BlockCodex.dynamicToVirtualMap[id]!! - offset]._lumCol.getElem(channel) BlockCodex[BlockCodex.tileToVirtual[id]!![offset]]._lumCol.getElem(channel)
} }
/** /**
@@ -80,7 +81,7 @@ class BlockProp {
//fun getLum(channel: Int) = lumCol.getElem(channel) //fun getLum(channel: Int) = lumCol.getElem(channel)
var drop: Int = 0 var drop: ItemID = ""
var maxSupport: Int = -1 // couldn't use NULL at all... var maxSupport: Int = -1 // couldn't use NULL at all...

View File

@@ -4,14 +4,14 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.TextureRegion import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.ItemValue import net.torvald.terrarum.ItemValue
import net.torvald.terrarum.ReferencingRanges.PREFIX_DYNAMICITEM
import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_DYNAMIC
import net.torvald.terrarum.itemproperties.Material import net.torvald.terrarum.itemproperties.Material
import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
typealias ItemID = Int typealias ItemID = String
/** /**
* Instances of the GameItem (e.g. net.torvald.terrarum.modulebasegame.gameitems.PickaxeCopper) are preferably referenced * Instances of the GameItem (e.g. net.torvald.terrarum.modulebasegame.gameitems.PickaxeCopper) are preferably referenced
@@ -40,7 +40,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
abstract val originalName: String abstract val originalName: String
var newName: String = "I AM VITTUN PLACEHOLDER" var newName: String = "I AM VITUN PLACEHOLDER"
private set private set
var name: String var name: String
@@ -208,7 +208,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
} }
override fun hashCode(): Int { override fun hashCode(): Int {
return dynamicID return dynamicID.hashCode()
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@@ -222,7 +222,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
nameColour = Color.WHITE nameColour = Color.WHITE
} }
override fun compareTo(other: GameItem): Int = (this.dynamicID - other.dynamicID).sign() override fun compareTo(other: GameItem): Int = (this.dynamicID.substring(4).toInt() - other.dynamicID.substring(4).toInt()).sign()
fun Int.sign(): Int = if (this > 0) 1 else if (this < 0) -1 else 0 fun Int.sign(): Int = if (this > 0) 1 else if (this < 0) -1 else 0
@@ -295,7 +295,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
fun generateUniqueDynamicID(inventory: ActorInventory): GameItem { fun generateUniqueDynamicID(inventory: ActorInventory): GameItem {
dynamicID = Companion.generateUniqueDynamicID(inventory) dynamicID = "$PREFIX_DYNAMICITEM${Companion.generateUniqueDynamicID(inventory)}"
ItemCodex.registerNewDynamicItem(dynamicID, this) ItemCodex.registerNewDynamicItem(dynamicID, this)
return this return this
} }
@@ -307,8 +307,8 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
fun generateUniqueDynamicID(inventory: ActorInventory): Int { fun generateUniqueDynamicID(inventory: ActorInventory): Int {
var ret: Int var ret: Int
do { do {
ret = ITEM_DYNAMIC.pickRandom() ret = (1..2147483647).pickRandom()
} while (inventory.contains(ret)) } while (inventory.contains("$PREFIX_DYNAMICITEM$ret"))
return ret return ret
} }

View File

@@ -9,10 +9,12 @@ import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.Fluid import net.torvald.terrarum.blockproperties.Fluid
import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator
import net.torvald.terrarum.printStackTrace import net.torvald.terrarum.printStackTrace
import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.serialise.ReadLayerDataZip import net.torvald.terrarum.serialise.ReadLayerDataZip
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
import net.torvald.util.SortedArrayList import net.torvald.util.SortedArrayList
import org.dyn4j.geometry.Vector2 import org.dyn4j.geometry.Vector2
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
@@ -79,7 +81,7 @@ open class GameWorld : Disposable {
/** /**
* Used by the renderer. When wirings are updated, `wirings` and this properties must be synchronised. * Used by the renderer. When wirings are updated, `wirings` and this properties must be synchronised.
*/ */
private val wiringBlocks: HashMap<BlockAddress, Int> private val wiringBlocks: HashMap<BlockAddress, ItemID>
//public World physWorld = new World( new Vec2(0, -Terrarum.game.gravitationalAccel) ); //public World physWorld = new World( new Vec2(0, -Terrarum.game.gravitationalAccel) );
//physics //physics
@@ -100,6 +102,11 @@ open class GameWorld : Disposable {
open var TIME_T: Long = 0L open var TIME_T: Long = 0L
open var dayLength: Int = 86400 open var dayLength: Int = 86400
@TEMzPayload("TMaP", TEMzPayload.EXTERNAL_JSON)
val tileNumberToNameMap: HashMap<Int, ItemID>
// does not go to the savefile
val tileNameToNumberMap: HashMap<ItemID, Int>
constructor(worldIndex: Int, width: Int, height: Int, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) { constructor(worldIndex: Int, width: Int, height: Int, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) {
if (width <= 0 || height <= 0) throw IllegalArgumentException("Non-positive width/height: ($width, $height)") if (width <= 0 || height <= 0) throw IllegalArgumentException("Non-positive width/height: ($width, $height)")
@@ -133,6 +140,14 @@ open class GameWorld : Disposable {
creationTime = creationTIME_T creationTime = creationTIME_T
lastPlayTime = lastPlayTIME_T lastPlayTime = lastPlayTIME_T
this.totalPlayTime = totalPlayTime this.totalPlayTime = totalPlayTime
tileNumberToNameMap = HashMap<Int, ItemID>()
tileNameToNumberMap = HashMap<ItemID, Int>()
CreateTileAtlas.tags.forEach {
tileNumberToNameMap[it.value.tileNumber] = it.key
tileNameToNumberMap[it.key] = it.value.tileNumber
}
} }
internal constructor(worldIndex: Int, layerData: ReadLayerDataZip.LayerData, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) { internal constructor(worldIndex: Int, layerData: ReadLayerDataZip.LayerData, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) {
@@ -160,6 +175,17 @@ open class GameWorld : Disposable {
creationTime = creationTIME_T creationTime = creationTIME_T
lastPlayTime = lastPlayTIME_T lastPlayTime = lastPlayTIME_T
this.totalPlayTime = totalPlayTime this.totalPlayTime = totalPlayTime
tileNumberToNameMap = layerData.tileNumberToNameMap
// TODO perform renaming of tile layers
// after the renaming, update the name maps
tileNameToNumberMap = HashMap<ItemID, Int>()
CreateTileAtlas.tags.forEach {
tileNumberToNameMap[it.value.tileNumber] = it.key
tileNameToNumberMap[it.key] = it.value.tileNumber
}
} }
/** /**
@@ -172,12 +198,34 @@ open class GameWorld : Disposable {
fun coerceXY(x: Int, y: Int) = (x fmod width) to (y.coerceIn(0, height - 1)) fun coerceXY(x: Int, y: Int) = (x fmod width) to (y.coerceIn(0, height - 1))
fun getTileFromWall(rawX: Int, rawY: Int): Int { /**
* @return ItemID
*/
fun getTileFromWall(rawX: Int, rawY: Int): ItemID {
val (x, y) = coerceXY(rawX, rawY)
return tileNumberToNameMap[layerWall.unsafeGetTile(x, y)]!!
}
/**
* @return ItemID
*/
fun getTileFromTerrain(rawX: Int, rawY: Int): ItemID {
val (x, y) = coerceXY(rawX, rawY)
return tileNumberToNameMap[layerTerrain.unsafeGetTile(x, y)]!!
}
/**
* @return Int
*/
fun getTileNumFromWall(rawX: Int, rawY: Int): Int {
val (x, y) = coerceXY(rawX, rawY) val (x, y) = coerceXY(rawX, rawY)
return layerWall.unsafeGetTile(x, y) return layerWall.unsafeGetTile(x, y)
} }
fun getTileFromTerrain(rawX: Int, rawY: Int): Int { /**
* @return Int
*/
fun getTileNumFromTerrain(rawX: Int, rawY: Int): Int {
val (x, y) = coerceXY(rawX, rawY) val (x, y) = coerceXY(rawX, rawY)
return layerTerrain.unsafeGetTile(x, y) return layerTerrain.unsafeGetTile(x, y)
} }
@@ -191,17 +239,17 @@ open class GameWorld : Disposable {
* * * *
* @param y * @param y
* * * *
* @param tilenum Item id of the wall block. Less-than-4096-value is permitted. * @param itemID Tile as in ItemID
*/ */
fun setTileWall(x: Int, y: Int, tilenum: Int) { fun setTileWall(x: Int, y: Int, itemID: ItemID) {
val (x, y) = coerceXY(x, y) val (x, y) = coerceXY(x, y)
val tilenum = tilenum % TILES_SUPPORTED // does work without this, but to be safe... val tilenum = tileNameToNumberMap[itemID]!!
val oldWall = getTileFromWall(x, y) val oldWall = getTileFromWall(x, y)
layerWall.unsafeSetTile(x, y, tilenum) layerWall.unsafeSetTile(x, y, tilenum)
wallDamages.remove(LandUtil.getBlockAddr(this, x, y)) wallDamages.remove(LandUtil.getBlockAddr(this, x, y))
Terrarum.ingame?.queueWallChangedEvent(oldWall, tilenum, LandUtil.getBlockAddr(this, x, y)) Terrarum.ingame?.queueWallChangedEvent(oldWall, itemID, LandUtil.getBlockAddr(this, x, y))
} }
/** /**
@@ -213,23 +261,24 @@ open class GameWorld : Disposable {
* * * *
* @param y * @param y
* * * *
* @param tilenum Item id of the terrain block, <4096 * @param itemID Tile as in ItemID
*/ */
fun setTileTerrain(x: Int, y: Int, tilenum: Int) { fun setTileTerrain(x: Int, y: Int, itemID: ItemID) {
val (x, y) = coerceXY(x, y) val (x, y) = coerceXY(x, y)
val tilenum = tileNameToNumberMap[itemID]!!
val oldTerrain = getTileFromTerrain(x, y) val oldTerrain = getTileFromTerrain(x, y)
layerTerrain.unsafeSetTile(x, y, tilenum) layerTerrain.unsafeSetTile(x, y, tilenum)
val blockAddr = LandUtil.getBlockAddr(this, x, y) val blockAddr = LandUtil.getBlockAddr(this, x, y)
terrainDamages.remove(blockAddr) terrainDamages.remove(blockAddr)
if (BlockCodex[tilenum].isSolid) { if (BlockCodex[itemID].isSolid) {
fluidFills.remove(blockAddr) fluidFills.remove(blockAddr)
fluidTypes.remove(blockAddr) fluidTypes.remove(blockAddr)
} }
// fluid tiles-item should be modified so that they will also place fluid onto their respective map // fluid tiles-item should be modified so that they will also place fluid onto their respective map
Terrarum.ingame?.queueTerrainChangedEvent(oldTerrain, tilenum, LandUtil.getBlockAddr(this, x, y)) Terrarum.ingame?.queueTerrainChangedEvent(oldTerrain, itemID, LandUtil.getBlockAddr(this, x, y))
} }
/*fun setTileWire(x: Int, y: Int, tile: Byte) { /*fun setTileWire(x: Int, y: Int, tile: Byte) {
@@ -241,8 +290,9 @@ open class GameWorld : Disposable {
Terrarum.ingame?.queueWireChangedEvent(oldWire, tile.toUint(), LandUtil.getBlockAddr(this, x, y)) Terrarum.ingame?.queueWireChangedEvent(oldWire, tile.toUint(), LandUtil.getBlockAddr(this, x, y))
}*/ }*/
fun getWiringBlocks(x: Int, y: Int): Int { fun getWiringBlocks(x: Int, y: Int): ItemID {
return wiringBlocks.getOrDefault(LandUtil.getBlockAddr(this, x, y), 0) return Block.AIR // TODO
//return wiringBlocks.getOrDefault(LandUtil.getBlockAddr(this, x, y), Block.AIR)
} }
fun getAllConduitsFrom(x: Int, y: Int): SortedArrayList<WiringNode>? { fun getAllConduitsFrom(x: Int, y: Int): SortedArrayList<WiringNode>? {
@@ -258,7 +308,9 @@ open class GameWorld : Disposable {
} }
fun addNewConduitTo(x: Int, y: Int, node: WiringNode) { fun addNewConduitTo(x: Int, y: Int, node: WiringNode) {
val blockAddr = LandUtil.getBlockAddr(this, x, y) // TODO needs new conduit storage scheme
/*val blockAddr = LandUtil.getBlockAddr(this, x, y)
// check for existing type of conduit // check for existing type of conduit
// if there's no duplicate... // if there's no duplicate...
@@ -270,10 +322,10 @@ open class GameWorld : Disposable {
} }
else { else {
TODO("need overwriting policy for existing conduit node") TODO("need overwriting policy for existing conduit node")
} }*/
} }
fun getTileFrom(mode: Int, x: Int, y: Int): Int? { fun getTileFrom(mode: Int, x: Int, y: Int): ItemID {
if (mode == TERRAIN) { if (mode == TERRAIN) {
return getTileFromTerrain(x, y) return getTileFromTerrain(x, y)
} }
@@ -287,8 +339,8 @@ open class GameWorld : Disposable {
throw IllegalArgumentException("illegal mode input: " + mode.toString()) throw IllegalArgumentException("illegal mode input: " + mode.toString())
} }
fun terrainIterator(): Iterator<Int> { fun terrainIterator(): Iterator<ItemID> {
return object : Iterator<Int> { return object : Iterator<ItemID> {
private var iteratorCount = 0 private var iteratorCount = 0
@@ -296,7 +348,7 @@ open class GameWorld : Disposable {
return iteratorCount < width * height return iteratorCount < width * height
} }
override fun next(): Int { override fun next(): ItemID {
val y = iteratorCount / width val y = iteratorCount / width
val x = iteratorCount % width val x = iteratorCount % width
// advance counter // advance counter
@@ -308,15 +360,15 @@ open class GameWorld : Disposable {
} }
} }
fun wallIterator(): Iterator<Int> { fun wallIterator(): Iterator<ItemID> {
return object : Iterator<Int> { return object : Iterator<ItemID> {
private var iteratorCount = 0 private var iteratorCount = 0
override fun hasNext(): Boolean = override fun hasNext(): Boolean =
iteratorCount < width * height iteratorCount < width * height
override fun next(): Int { override fun next(): ItemID {
val y = iteratorCount / width val y = iteratorCount / width
val x = iteratorCount % width val x = iteratorCount % width
// advance counter // advance counter
@@ -351,7 +403,7 @@ open class GameWorld : Disposable {
// remove tile from the world // remove tile from the world
if (terrainDamages[addr] ?: 0f >= BlockCodex[getTileFromTerrain(x, y)].strength) { if (terrainDamages[addr] ?: 0f >= BlockCodex[getTileFromTerrain(x, y)].strength) {
setTileTerrain(x, y, 0) setTileTerrain(x, y, Block.AIR)
terrainDamages.remove(addr) terrainDamages.remove(addr)
return true return true
} }
@@ -380,7 +432,7 @@ open class GameWorld : Disposable {
// remove tile from the world // remove tile from the world
if (wallDamages[addr]!! >= BlockCodex[getTileFromWall(x, y)].strength) { if (wallDamages[addr]!! >= BlockCodex[getTileFromWall(x, y)].strength) {
setTileWall(x, y, 0) setTileWall(x, y, Block.AIR)
wallDamages.remove(addr) wallDamages.remove(addr)
return true return true
} }

View File

@@ -5,7 +5,11 @@ import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.CommonResourcePool import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.ReferencingRanges import net.torvald.terrarum.ReferencingRanges
import net.torvald.terrarum.ReferencingRanges.PREFIX_ACTORITEM
import net.torvald.terrarum.ReferencingRanges.PREFIX_DYNAMICITEM
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.BlockProp
import net.torvald.terrarum.blockproperties.Fluid import net.torvald.terrarum.blockproperties.Fluid
import net.torvald.terrarum.gameitem.GameItem import net.torvald.terrarum.gameitem.GameItem
import net.torvald.terrarum.gameitem.ItemID import net.torvald.terrarum.gameitem.ItemID
@@ -13,6 +17,8 @@ import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.CanBeAnItem import net.torvald.terrarum.modulebasegame.gameactors.CanBeAnItem
import net.torvald.terrarum.worlddrawer.BlocksDrawer import net.torvald.terrarum.worlddrawer.BlocksDrawer
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.ITEM_ATLAS_TILES_X
import java.util.* import java.util.*
/** /**
@@ -24,96 +30,20 @@ object ItemCodex {
* <ItemID or RefID for Actor, TheItem> * <ItemID or RefID for Actor, TheItem>
* Will return corresponding Actor if ID >= ACTORID_MIN * Will return corresponding Actor if ID >= ACTORID_MIN
*/ */
val itemCodex = HashMap<ItemID, GameItem>() private val itemCodex = HashMap<ItemID, GameItem>()
val dynamicItemDescription = HashMap<ItemID, GameItem>() val dynamicItemDescription = HashMap<ItemID, GameItem>()
val dynamicToStaticTable = HashMap<ItemID, ItemID>() val dynamicToStaticTable = HashMap<ItemID, ItemID>()
val ITEM_TILES = ReferencingRanges.TILES
val ITEM_WALLS = ReferencingRanges.WALLS
val ITEM_WIRES = ReferencingRanges.WIRES
val ITEM_STATIC = ReferencingRanges.ITEMS_STATIC
val ITEM_DYNAMIC = ReferencingRanges.ITEMS_DYNAMIC
val ACTORID_MIN = ReferencingRanges.ACTORS.first val ACTORID_MIN = ReferencingRanges.ACTORS.first
private val itemImagePlaceholder: TextureRegion private val itemImagePlaceholder: TextureRegion
get() = CommonResourcePool.getAsTextureRegion("itemplaceholder_24") // copper pickaxe get() = CommonResourcePool.getAsTextureRegion("itemplaceholder_24") // copper pickaxe
// TODO: when generalised, there's no guarantee that blocks will be used as an item. Write customised item prop loader and init it on the Ingame
init { init {
//val ingame = Terrarum.ingame!! as Ingame // WARNING you can't put this here, ExceptionInInitializerError //val ingame = Terrarum.ingame!! as Ingame // WARNING you can't put this here, ExceptionInInitializerError
/*println("[ItemCodex] recording item ID ") println("[ItemCodex] recording item ID ")
// blocks.csvs are loaded by ModMgr beforehand
// block items (blocks and walls are the same thing basically)
for (i in ITEM_TILES + ITEM_WALLS) {
itemCodex[i] = object : GameItem() {
override val originalID = i
override var dynamicID = i
override val isUnique: Boolean = false
override var baseMass: Double = BlockCodex[i].density / 1000.0
override var baseToolSize: Double? = null
override var equipPosition = EquipPosition.HAND_GRIP
override val originalName = BlockCodex[i % ITEM_WALLS.first].nameKey
override var stackable = true
override var inventoryCategory = if (i in ITEM_TILES) Category.BLOCK else Category.WALL
override var isDynamic = false
override val material = Material(0,0,0,0,0,0,0,0,0,0.0)
init {
print("$originalID ")
}
override fun startPrimaryUse(delta: Float): Boolean {
return false
// TODO base punch attack
}
override fun startSecondaryUse(delta: Float): Boolean {
val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
// check for collision with actors (BLOCK only)
if (this.inventoryCategory == Category.BLOCK) {
ingame.actorContainerActive.forEach {
if (it is ActorWBMovable && it.hIntTilewiseHitbox.intersects(mousePoint))
return false
}
}
// return false if the tile is already there
if (this.inventoryCategory == Category.BLOCK &&
this.dynamicID == ingame.world.getTileFromTerrain(Terrarum.mouseTileX, Terrarum.mouseTileY) ||
this.inventoryCategory == Category.WALL &&
this.dynamicID - ITEM_WALLS.start == ingame.world.getTileFromWall(Terrarum.mouseTileX, Terrarum.mouseTileY) ||
this.inventoryCategory == Category.WIRE &&
this.dynamicID - ITEM_WIRES.start == ingame.world.getTileFromWire(Terrarum.mouseTileX, Terrarum.mouseTileY)
)
return false
// filter passed, do the job
// FIXME this is only useful for Player
if (i in ITEM_TILES) {
ingame.world.setTileTerrain(
Terrarum.mouseTileX,
Terrarum.mouseTileY,
i
)
}
else {
ingame.world.setTileWall(
Terrarum.mouseTileX,
Terrarum.mouseTileY,
i
)
}
return true
}
}
}*/
// test copper pickaxe // test copper pickaxe
/*itemCodex[ITEM_STATIC.first] = object : GameItem() { /*itemCodex[ITEM_STATIC.first] = object : GameItem() {
@@ -176,7 +106,7 @@ object ItemCodex {
// test water bucket // test water bucket
itemCodex[9000] = object : GameItem(9000) { /*itemCodex[9000] = object : GameItem(9000) {
override val isUnique: Boolean = true override val isUnique: Boolean = true
override val originalName: String = "Infinite Water Bucket" override val originalName: String = "Infinite Water Bucket"
@@ -226,7 +156,7 @@ object ItemCodex {
ingame.world.setFluid(Terrarum.mouseTileX, Terrarum.mouseTileY, Fluid.LAVA, 4f) ingame.world.setFluid(Terrarum.mouseTileX, Terrarum.mouseTileY, Fluid.LAVA, 4f)
return true return true
} }
} }*/
// read from save (if applicable) and fill dynamicItemDescription // read from save (if applicable) and fill dynamicItemDescription
@@ -236,7 +166,10 @@ object ItemCodex {
println() println()
} }
fun registerNewDynamicItem(dynamicID: Int, item: GameItem) { /**
* @param: dynamicID string of "dyn:<random id>"
*/
fun registerNewDynamicItem(dynamicID: ItemID, item: GameItem) {
if (AppLoader.IS_DEVELOPMENT_BUILD) { if (AppLoader.IS_DEVELOPMENT_BUILD) {
printdbg(this, "Registering new dynamic item $dynamicID (from ${item.originalID})") printdbg(this, "Registering new dynamic item $dynamicID (from ${item.originalID})")
} }
@@ -251,18 +184,17 @@ object ItemCodex {
operator fun get(code: ItemID?): GameItem? { operator fun get(code: ItemID?): GameItem? {
if (code == null) return null if (code == null) return null
if (code <= ITEM_STATIC.endInclusive) // generic item if (code.startsWith(PREFIX_DYNAMICITEM))
return itemCodex[code]!!.clone() // from CSV
else if (code <= ITEM_DYNAMIC.endInclusive) {
return dynamicItemDescription[code]!! return dynamicItemDescription[code]!!
} else if (code.startsWith(PREFIX_ACTORITEM)) {
else { val a = (Terrarum.ingame!! as TerrarumIngame).getActorByID(code.substring(6).toInt()) // actor item
val a = (Terrarum.ingame!! as TerrarumIngame).getActorByID(code) // actor item
if (a is CanBeAnItem) return a.itemData if (a is CanBeAnItem) return a.itemData
return null return null
//throw IllegalArgumentException("Attempted to get item data of actor that cannot be an item. ($a)") //throw IllegalArgumentException("Attempted to get item data of actor that cannot be an item. ($a)")
} }
else // generic item
return itemCodex[code]!!.clone() // from CSV
} }
fun dynamicToStaticID(dynamicID: ItemID) = dynamicToStaticTable[dynamicID]!! fun dynamicToStaticID(dynamicID: ItemID) = dynamicToStaticTable[dynamicID]!!
@@ -270,6 +202,10 @@ object ItemCodex {
/** /**
* Mainly used by GameItemLoader * Mainly used by GameItemLoader
*/ */
fun set(modname: String, code: Int, item: GameItem) {
itemCodex["$modname:$code"] = item
}
operator fun set(code: ItemID, item: GameItem) { operator fun set(code: ItemID, item: GameItem) {
itemCodex[code] = item itemCodex[code] = item
} }
@@ -280,31 +216,35 @@ object ItemCodex {
return getItemImage(item.originalID) return getItemImage(item.originalID)
} }
fun getItemImage(itemOriginalID: Int): TextureRegion { fun getItemImage(itemID: ItemID?): TextureRegion? {
if (itemID == null) return null
// dynamic item // dynamic item
if (itemOriginalID in ITEM_DYNAMIC) { if (itemID.startsWith(PREFIX_DYNAMICITEM)) {
return getItemImage(dynamicToStaticID(itemOriginalID)) return getItemImage(dynamicToStaticID(itemID))
}
// item
else if (itemID.startsWith("item@")) {
return getItemImage(itemID)
}
// TODO: wires
// wall
else if (itemID.startsWith("wall@")) {
val itemSheetNumber = CreateTileAtlas.tileIDtoItemSheetNumber(itemID.substring(5))
return BlocksDrawer.tileItemWall.get(
itemSheetNumber % ITEM_ATLAS_TILES_X,
itemSheetNumber / ITEM_ATLAS_TILES_X
)
} }
// terrain // terrain
else if (itemOriginalID in ITEM_TILES) { else {
val itemSheetNumber = CreateTileAtlas.tileIDtoItemSheetNumber(itemID)
return BlocksDrawer.tileItemTerrain.get( return BlocksDrawer.tileItemTerrain.get(
itemOriginalID % 16, itemSheetNumber % ITEM_ATLAS_TILES_X,
itemOriginalID / 16 itemSheetNumber / ITEM_ATLAS_TILES_X
) )
} }
// wall
else if (itemOriginalID in ITEM_WALLS) {
return BlocksDrawer.tileItemWall.get(
(itemOriginalID.minus(ITEM_WALLS.first) % 16),
(itemOriginalID.minus(ITEM_WALLS.first) / 16)
)
}
// wire
/*else if (itemOriginalID in ITEM_WIRES) {
return BlocksDrawer.tilesWire.get((itemOriginalID % 16) * 16, itemOriginalID / 16)
}*/
else
return itemCodex[itemOriginalID]?.itemImage ?: itemImagePlaceholder
} }
fun hasItem(itemID: Int): Boolean = dynamicItemDescription.containsKey(itemID) fun hasItem(itemID: Int): Boolean = dynamicItemDescription.containsKey(itemID)

View File

@@ -6,6 +6,7 @@ import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.ModMgr import net.torvald.terrarum.ModMgr
import net.torvald.terrarum.ModuleEntryPoint import net.torvald.terrarum.ModuleEntryPoint
import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.BlockProp
import net.torvald.terrarum.gameitem.GameItem import net.torvald.terrarum.gameitem.GameItem
import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.itemproperties.MaterialCodex import net.torvald.terrarum.itemproperties.MaterialCodex
@@ -52,36 +53,9 @@ class EntryPoint : ModuleEntryPoint() {
// blocks.csvs are loaded by ModMgr beforehand // blocks.csvs are loaded by ModMgr beforehand
// block items (blocks and walls are the same thing basically) // block items (blocks and walls are the same thing basically)
for (i in ItemCodex.ITEM_TILES + ItemCodex.ITEM_WALLS) { for (tile in BlockCodex.getAll()) {
val blockProp = BlockCodex.getOrNull(i % ItemCodex.ITEM_WALLS.first) ItemCodex[tile.id] = makeNewItemObj(tile, false)
ItemCodex["wall@"+tile.id] = makeNewItemObj(tile, true)
if (blockProp != null) {
ItemCodex.itemCodex[i] = object : GameItem(i) {
override val isUnique: Boolean = false
override var baseMass: Double = blockProp.density / 1000.0
override var baseToolSize: Double? = null
override val originalName = blockProp.nameKey
override var stackable = true
override var inventoryCategory = if (i in ItemCodex.ITEM_TILES) Category.BLOCK else Category.WALL
override var isDynamic = false
override val material = MaterialCodex.getOrDefault(blockProp.material)
init {
equipPosition = EquipPosition.HAND_GRIP
if (IS_DEVELOPMENT_BUILD)
print("$originalID ")
}
override fun startPrimaryUse(delta: Float): Boolean {
return BlockBase.blockStartPrimaryUse(this, i, delta)
}
override fun effectWhenEquipped(delta: Float) {
BlockBase.blockEffectWhenEquipped(delta)
}
}
}
} }
@@ -89,6 +63,33 @@ class EntryPoint : ModuleEntryPoint() {
println("[Basegame.EntryPoint] Welcome back!") println("[Basegame.EntryPoint] Welcome back!")
} }
private fun makeNewItemObj(tile: BlockProp, isWall: Boolean) = object : GameItem(tile.id) {
override val isUnique: Boolean = false
override var baseMass: Double = tile.density / 1000.0
override var baseToolSize: Double? = null
override val originalName = tile.nameKey
override var stackable = true
override var inventoryCategory = if (isWall) Category.WALL else Category.BLOCK
override var isDynamic = false
override val material = MaterialCodex.getOrDefault(tile.material)
init {
equipPosition = EquipPosition.HAND_GRIP
if (IS_DEVELOPMENT_BUILD)
print("$originalID ")
}
override fun startPrimaryUse(delta: Float): Boolean {
return BlockBase.blockStartPrimaryUse(this, tile.id, delta)
}
override fun effectWhenEquipped(delta: Float) {
BlockBase.blockEffectWhenEquipped(delta)
}
}
override fun dispose() { override fun dispose() {
WatchFont.dispose() WatchFont.dispose()
} }

View File

@@ -7,8 +7,6 @@ import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameitem.GameItem import net.torvald.terrarum.gameitem.GameItem
import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_DYNAMIC
import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_WALLS
import net.torvald.terrarum.gameitem.ItemID import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.lock import net.torvald.terrarum.lock
import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.TerrarumIngame
@@ -54,8 +52,8 @@ class ActorInventory(@Transient val actor: Pocketed, var maxCapacity: Int, var c
// not wall-able walls // not wall-able walls
if (item.inventoryCategory == GameItem.Category.WALL && if (item.inventoryCategory == GameItem.Category.WALL &&
!BlockCodex[item.dynamicID - ITEM_WALLS.start].isWallable) { (!item.dynamicID.startsWith("wall@") || !BlockCodex[item.dynamicID.substring(5)].isWallable)) {
throw IllegalArgumentException("Wall ID ${item.dynamicID - ITEM_WALLS.start} is not wall-able.") throw IllegalArgumentException("Wall ID ${item.dynamicID} is not wall-able.")
} }
@@ -65,12 +63,12 @@ class ActorInventory(@Transient val actor: Pocketed, var maxCapacity: Int, var c
if (count < 0) if (count < 0)
throw IllegalArgumentException("Item count is negative number. If you intended removing items, use remove()\n" + throw IllegalArgumentException("Item count is negative number. If you intended removing items, use remove()\n" +
"These commands are NOT INTERCHANGEABLE; they handle things differently according to the context.") "These commands are NOT INTERCHANGEABLE; they handle things differently according to the context.")
if (item.originalID == Terrarum.PLAYER_REF_ID || item.originalID == 0x51621D) // do not delete this magic if (item.originalID == "actor:${Terrarum.PLAYER_REF_ID}" || item.originalID == ("actor:${0x51621D}")) // do not delete this magic
throw IllegalArgumentException("Attempted to put human player into the inventory.") throw IllegalArgumentException("Attempted to put human player into the inventory.")
if (((Terrarum.ingame as? TerrarumIngame)?.gameFullyLoaded ?: false) && if (((Terrarum.ingame as? TerrarumIngame)?.gameFullyLoaded ?: false) &&
(item.originalID == (Terrarum.ingame as? TerrarumIngame)?.actorNowPlaying?.referenceID)) (item.originalID == "actor:${(Terrarum.ingame as? TerrarumIngame)?.actorNowPlaying?.referenceID}"))
throw IllegalArgumentException("Attempted to put active player into the inventory.") throw IllegalArgumentException("Attempted to put active player into the inventory.")
if ((!item.stackable || item.dynamicID in ITEM_DYNAMIC) && count > 1) if ((!item.stackable || item.dynamicID.startsWith("dyn:")) && count > 1)
throw IllegalArgumentException("Attempting to adding stack of item but the item is not stackable; item: $item, count: $count") throw IllegalArgumentException("Attempting to adding stack of item but the item is not stackable; item: $item, count: $count")

View File

@@ -2,7 +2,6 @@ package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.terrarum.ModMgr import net.torvald.terrarum.ModMgr
import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.BlockCodex.MAX_TERRAIN_TILES
import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.faction.FactionFactory import net.torvald.terrarum.gameactors.faction.FactionFactory
import net.torvald.terrarum.worlddrawer.CreateTileAtlas import net.torvald.terrarum.worlddrawer.CreateTileAtlas
@@ -79,18 +78,18 @@ object PlayerBuilderSigrid {
CreateTileAtlas.tags.forEach { t, _ -> CreateTileAtlas.tags.forEach { t, _ ->
inventory.add(t, 9995) inventory.add(t, 9995)
if (BlockCodex[t].isWallable) { if (BlockCodex[t].isWallable) {
inventory.add(t + MAX_TERRAIN_TILES, 9995) inventory.add("wall@"+t, 9995)
} }
} }
// item ids are defined in <module>/items/itemid.csv // item ids are defined in <module>/items/itemid.csv
inventory.add(135168, 16) // copper pick inventory.add("item@basegame:0", 16) // copper pick
inventory.add(135169) // iron pick inventory.add("item@basegame:1") // iron pick
inventory.add(135170) // steel pick inventory.add("item@basegame:2") // steel pick
inventory.add(135171, 9995) // wire piece inventory.add("item@basegame:3", 9995) // wire piece
inventory.add(135172, 385930603) // test tiki torch inventory.add("item@basegame:4", 385930603) // test tiki torch
inventory.add(135173, 95) // crafting table inventory.add("item@basegame:5", 95) // crafting table
//inventory.add(9000) // TEST water bucket //inventory.add(9000) // TEST water bucket
//inventory.add(9001) // TEST lava bucket //inventory.add(9001) // TEST lava bucket
} }

View File

@@ -5,6 +5,7 @@ import net.torvald.terrarum.Point2i
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitem.GameItem import net.torvald.terrarum.gameitem.GameItem
import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.TerrarumIngame
@@ -20,7 +21,7 @@ object BlockBase {
* @param dontEncaseActors when set to true, blocks won't be placed where Actors are. You will want to set it false * @param dontEncaseActors when set to true, blocks won't be placed where Actors are. You will want to set it false
* for wire items, otherwise you want it to be true. * for wire items, otherwise you want it to be true.
*/ */
fun blockStartPrimaryUse(gameItem: GameItem, itemID: Int, delta: Float): Boolean { fun blockStartPrimaryUse(gameItem: GameItem, itemID: ItemID, delta: Float): Boolean {
val ingame = Terrarum.ingame!! as TerrarumIngame val ingame = Terrarum.ingame!! as TerrarumIngame
val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble()) val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
val mouseTile = Point2i(Terrarum.mouseTileX, Terrarum.mouseTileY) val mouseTile = Point2i(Terrarum.mouseTileX, Terrarum.mouseTileY)
@@ -45,21 +46,21 @@ object BlockBase {
if (gameItem.inventoryCategory == GameItem.Category.BLOCK && if (gameItem.inventoryCategory == GameItem.Category.BLOCK &&
gameItem.dynamicID == ingame.world.getTileFromTerrain(mouseTile.x, mouseTile.y) || gameItem.dynamicID == ingame.world.getTileFromTerrain(mouseTile.x, mouseTile.y) ||
gameItem.inventoryCategory == GameItem.Category.WALL && gameItem.inventoryCategory == GameItem.Category.WALL &&
gameItem.dynamicID - ItemCodex.ITEM_WALLS.start == ingame.world.getTileFromWall(mouseTile.x, mouseTile.y) gameItem.dynamicID == ingame.world.getTileFromWall(mouseTile.x, mouseTile.y)
) )
return false return false
// filter passed, do the job // filter passed, do the job
// FIXME this is only useful for Player // FIXME this is only useful for Player
if (itemID in ItemCodex.ITEM_TILES) { if (itemID.startsWith("wall@")) {
ingame.world.setTileTerrain( ingame.world.setTileWall(
mouseTile.x, mouseTile.x,
mouseTile.y, mouseTile.y,
itemID itemID.substring(5)
) )
} }
else { else {
ingame.world.setTileWall( ingame.world.setTileTerrain(
mouseTile.x, mouseTile.x,
mouseTile.y, mouseTile.y,
itemID itemID
@@ -74,7 +75,8 @@ object BlockBase {
} }
fun wireStartPrimaryUse(gameItem: GameItem, wireTypeBit: Int, delta: Float): Boolean { fun wireStartPrimaryUse(gameItem: GameItem, wireTypeBit: Int, delta: Float): Boolean {
val ingame = Terrarum.ingame!! as TerrarumIngame return false // TODO need new wire storing format
/*val ingame = Terrarum.ingame!! as TerrarumIngame
val mouseTile = Point2i(Terrarum.mouseTileX, Terrarum.mouseTileY) val mouseTile = Point2i(Terrarum.mouseTileX, Terrarum.mouseTileY)
// return false if the tile is already there // return false if the tile is already there
@@ -93,7 +95,7 @@ object BlockBase {
) )
) )
return true return true*/
} }
fun wireEffectWhenEquipped(typebit: Int, delta: Float) { fun wireEffectWhenEquipped(typebit: Int, delta: Float) {

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.serialise package net.torvald.terrarum.serialise
import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.gameworld.BlockAddress import net.torvald.terrarum.gameworld.BlockAddress
import net.torvald.terrarum.gameworld.BlockLayer import net.torvald.terrarum.gameworld.BlockLayer
import net.torvald.terrarum.gameworld.FluidType import net.torvald.terrarum.gameworld.FluidType
@@ -152,6 +153,7 @@ internal object ReadLayerDataZip {
val wallDamages = HashMap<BlockAddress, Float>() val wallDamages = HashMap<BlockAddress, Float>()
val fluidTypes = HashMap<BlockAddress, FluidType>() val fluidTypes = HashMap<BlockAddress, FluidType>()
val fluidFills = HashMap<BlockAddress, Float>() val fluidFills = HashMap<BlockAddress, Float>()
val tileNumberToNameMap = HashMap<Int, ItemID>()
// parse terrain damages // parse terrain damages
for (c in payloadBytes["TdMG"]!!.indices step 10) { for (c in payloadBytes["TdMG"]!!.indices step 10) {
@@ -184,7 +186,7 @@ internal object ReadLayerDataZip {
spawnPoint.first, spawnPoint.second, spawnPoint.first, spawnPoint.second,
wallDamages, terrainDamages, fluidTypes, fluidFills wallDamages, terrainDamages, fluidTypes, fluidFills, tileNumberToNameMap
) )
} }
@@ -204,7 +206,8 @@ internal object ReadLayerDataZip {
val wallDamages: HashMap<BlockAddress, Float>, val wallDamages: HashMap<BlockAddress, Float>,
val terrainDamages: HashMap<BlockAddress, Float>, val terrainDamages: HashMap<BlockAddress, Float>,
val fluidTypes: HashMap<BlockAddress, FluidType>, val fluidTypes: HashMap<BlockAddress, FluidType>,
val fluidFills: HashMap<BlockAddress, Float> val fluidFills: HashMap<BlockAddress, Float>,
val tileNumberToNameMap: HashMap<Int, ItemID>
) )
internal fun InputStream.readRelative(b: ByteArray, off: Int, len: Int): Int { internal fun InputStream.readRelative(b: ByteArray, off: Int, len: Int): Int {

View File

@@ -8,6 +8,7 @@ import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.fmod import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
@@ -179,7 +180,7 @@ internal object BlocksDrawer {
/** /**
* To interact with external modules * To interact with external modules
*/ */
@JvmStatic fun addBlendMul(blockID: Int): Boolean { @JvmStatic fun addBlendMul(blockID: ItemID): Boolean {
return TILES_BLEND_MUL.add(blockID) return TILES_BLEND_MUL.add(blockID)
} }
@@ -307,11 +308,11 @@ internal object BlocksDrawer {
val bufferX = x - for_x_start val bufferX = x - for_x_start
val bufferY = y - for_y_start val bufferY = y - for_y_start
val thisTile = when (mode) { val thisTile: ItemID = when (mode) {
WALL -> world.getTileFromWall(x, y) WALL -> world.getTileFromWall(x, y)
TERRAIN -> world.getTileFromTerrain(x, y) TERRAIN -> world.getTileFromTerrain(x, y)
WIRE -> world.getWiringBlocks(x, y).and(drawWires).toBitOrd() * 16 WIRE -> "basegame:-1" // TODO need new wire storing format //world.getWiringBlocks(x, y).and(drawWires).toBitOrd() * 16
FLUID -> world.getFluid(x, y).type.abs() FLUID -> "basegame:-1" // TODO need new wire storing format //world.getFluid(x, y).type.abs()
else -> throw IllegalArgumentException() else -> throw IllegalArgumentException()
} }
@@ -344,10 +345,10 @@ internal object BlocksDrawer {
if (mode == FLUID) if (mode == FLUID)
CreateTileAtlas.fluidToTileNumber(world.getFluid(x, y)) CreateTileAtlas.fluidToTileNumber(world.getFluid(x, y))
else if (mode == WIRE) else if (mode == WIRE)
thisTile 0 // TODO need new wire storing format
else else
renderTag.tileNumber renderTag.tileNumber
val tileNumber = if (mode != WIRE && thisTile == 0) 0 val tileNumber = if (mode != WIRE && thisTile == Block.AIR) 0
// special case: fluids // special case: fluids
else if (mode == FLUID) tileNumberBase + connectLut47[nearbyTilesInfo] else if (mode == FLUID) tileNumberBase + connectLut47[nearbyTilesInfo]
// special case: wires // special case: wires
@@ -376,11 +377,11 @@ internal object BlocksDrawer {
// draw a tile // draw a tile
if (mode == WIRE && thisTile < 0) { if (mode == WIRE) {
// no wire here, draw block id 255 (bottom right) // no wire here, draw block id 255 (bottom right)
writeToBuffer(mode, bufferX, bufferY, 15, 15, 0) writeToBuffer(mode, bufferX, bufferY, 15, 15, 0)
} }
else if (mode == FLUID || mode == WIRE) { else if (mode == FLUID) {
writeToBuffer(mode, bufferX, bufferY, thisTileX, thisTileY, 0) writeToBuffer(mode, bufferX, bufferY, thisTileX, thisTileY, 0)
} }
else { else {
@@ -404,7 +405,7 @@ internal object BlocksDrawer {
) )
} }
private fun getNearbyTilesInfoConSelf(x: Int, y: Int, mode: Int, mark: Int?): Int { private fun getNearbyTilesInfoConSelf(x: Int, y: Int, mode: Int, mark: ItemID?): Int {
val nearbyTiles = getNearbyTilesPos(x, y).map { world.getTileFrom(mode, it.x, it.y) ?: Block.NULL } val nearbyTiles = getNearbyTilesPos(x, y).map { world.getTileFrom(mode, it.x, it.y) ?: Block.NULL }
var ret = 0 var ret = 0
@@ -423,8 +424,9 @@ internal object BlocksDrawer {
* *
* @return offset from the spritesheet's "base" tile number, 0..15. * @return offset from the spritesheet's "base" tile number, 0..15.
*/ */
private fun getNearbyWiringInfo(x: Int, y: Int, wire: Int): Int { private fun getNearbyWiringInfo(x: Int, y: Int, wire: ItemID): Int {
val nearbyTiles = getNearbyTilesPos(x, y).map { world.getWiringBlocks(it.x, it.y).and(drawWires).toBitOrd() * 16 } return 0 // TODO need new wire storing format
/*val nearbyTiles = getNearbyTilesPos(x, y).map { world.getWiringBlocks(it.x, it.y).and(drawWires).toBitOrd() * 16 }
var ret = 0 var ret = 0
for (i in nearbyTiles.indices) { for (i in nearbyTiles.indices) {
@@ -433,11 +435,11 @@ internal object BlocksDrawer {
} }
} }
return ret return ret*/
} }
private fun getNearbyTilesInfoConMutual(x: Int, y: Int, mode: Int): Int { private fun getNearbyTilesInfoConMutual(x: Int, y: Int, mode: Int): Int {
val nearbyTiles = getNearbyTilesPos(x, y).map { world.getTileFrom(mode, it.x, it.y) ?: Block.NULL } val nearbyTiles: List<ItemID> = getNearbyTilesPos(x, y).map { world.getTileFrom(mode, it.x, it.y)!! }
var ret = 0 var ret = 0
for (i in nearbyTiles.indices) { for (i in nearbyTiles.indices) {
@@ -454,7 +456,7 @@ internal object BlocksDrawer {
*/ */
private fun getNearbyTilesInfoFluids(x: Int, y: Int): Int { private fun getNearbyTilesInfoFluids(x: Int, y: Int): Int {
val nearbyPos = getNearbyTilesPos(x, y) val nearbyPos = getNearbyTilesPos(x, y)
val nearbyTiles = nearbyPos.map { world.getTileFromTerrain(it.x, it.y) ?: Block.NULL } val nearbyTiles: List<ItemID> = nearbyPos.map { world.getTileFromTerrain(it.x, it.y) }
var ret = 0 var ret = 0
for (i in nearbyTiles.indices) { for (i in nearbyTiles.indices) {
@@ -468,12 +470,12 @@ internal object BlocksDrawer {
} }
private fun getNearbyTilesInfoWallSticker(x: Int, y: Int): Int { private fun getNearbyTilesInfoWallSticker(x: Int, y: Int): Int {
val nearbyTiles = IntArray(4) val nearbyTiles = arrayOf(Block.NULL, Block.NULL, Block.NULL, Block.NULL)
val NEARBY_TILE_KEY_BACK = NEARBY_TILE_KEY_UP val NEARBY_TILE_KEY_BACK = NEARBY_TILE_KEY_UP
nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: Block.NULL nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y)
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y) ?: Block.NULL nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y)
nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(TERRAIN, x , y + 1) ?: Block.NULL nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(TERRAIN, x , y + 1)
nearbyTiles[NEARBY_TILE_KEY_BACK] = world.getTileFrom(WALL, x , y) ?: Block.NULL nearbyTiles[NEARBY_TILE_KEY_BACK] = world.getTileFrom(WALL, x , y)
try { try {
if (BlockCodex[nearbyTiles[NEARBY_TILE_KEY_DOWN]].isSolid) if (BlockCodex[nearbyTiles[NEARBY_TILE_KEY_DOWN]].isSolid)
@@ -502,9 +504,11 @@ internal object BlocksDrawer {
} }
private fun getNearbyTilesInfoPlatform(x: Int, y: Int): Int { private fun getNearbyTilesInfoPlatform(x: Int, y: Int): Int {
val nearbyTiles = IntArray(4) val nearbyTiles = arrayOf(Block.NULL, Block.NULL, Block.NULL, Block.NULL)
nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: Block.NULL val NEARBY_TILE_KEY_BACK = NEARBY_TILE_KEY_UP
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y) ?: Block.NULL nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y)
nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y)
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y)
if ((BlockCodex[nearbyTiles[NEARBY_TILE_KEY_LEFT]].isSolid && if ((BlockCodex[nearbyTiles[NEARBY_TILE_KEY_LEFT]].isSolid &&
BlockCodex[nearbyTiles[NEARBY_TILE_KEY_RIGHT]].isSolid) || BlockCodex[nearbyTiles[NEARBY_TILE_KEY_RIGHT]].isSolid) ||
@@ -753,10 +757,10 @@ internal object BlocksDrawer {
fun getRenderEndX(): Int = clampWTile(getRenderStartX() + (WorldCamera.width / TILE_SIZE) + 2) fun getRenderEndX(): Int = clampWTile(getRenderStartX() + (WorldCamera.width / TILE_SIZE) + 2)
fun getRenderEndY(): Int = clampHTile(getRenderStartY() + (WorldCamera.height / TILE_SIZE) + 2) fun getRenderEndY(): Int = clampHTile(getRenderStartY() + (WorldCamera.height / TILE_SIZE) + 2)
fun isConnectSelf(b: Int): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_SELF fun isConnectSelf(b: ItemID): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_SELF
fun isConnectMutual(b: Int): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_MUTUAL fun isConnectMutual(b: ItemID): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_MUTUAL
fun isWallSticker(b: Int): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_WALL_STICKER fun isWallSticker(b: ItemID): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_WALL_STICKER
fun isPlatform(b: Int): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_WALL_STICKER_CONNECT_SELF fun isPlatform(b: ItemID): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_WALL_STICKER_CONNECT_SELF
//fun isBlendMul(b: Int): Boolean = TILES_BLEND_MUL.contains(b) //fun isBlendMul(b: Int): Boolean = TILES_BLEND_MUL.contains(b)
fun tileInCamera(x: Int, y: Int) = fun tileInCamera(x: Int, y: Int) =

View File

@@ -6,9 +6,12 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.utils.GdxRuntimeException import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.gdx.graphics.Cvec
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.Fluid import net.torvald.terrarum.blockproperties.Fluid
import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import kotlin.math.roundToInt import kotlin.math.roundToInt
@@ -28,6 +31,8 @@ object CreateTileAtlas {
const val TILE_SIZE = TerrarumAppConfiguration.TILE_SIZE const val TILE_SIZE = TerrarumAppConfiguration.TILE_SIZE
const val TILES_IN_X = MAX_TEX_SIZE / TILE_SIZE const val TILES_IN_X = MAX_TEX_SIZE / TILE_SIZE
const val ITEM_ATLAS_TILES_X = 16
private val TOTAL_TILES = TILES_IN_X * TILES_IN_X private val TOTAL_TILES = TILES_IN_X * TILES_IN_X
lateinit var atlas: Pixmap lateinit var atlas: Pixmap
@@ -38,8 +43,10 @@ object CreateTileAtlas {
lateinit var atlasGlow: Pixmap // glowing won't be affected by the season... for now lateinit var atlasGlow: Pixmap // glowing won't be affected by the season... for now
lateinit var itemTerrainTexture: Texture lateinit var itemTerrainTexture: Texture
lateinit var itemWallTexture: Texture lateinit var itemWallTexture: Texture
lateinit var terrainTileColourMap: GdxColorMap lateinit var terrainTileColourMap: HashMap<ItemID, Cvec>
internal lateinit var tags: HashMap<Int, RenderTag> lateinit var tags: HashMap<ItemID, RenderTag> // TileID, RenderTag
private set
lateinit var itemSheetNumbers: HashMap<ItemID, Int> // TileID, Int
private set private set
private val defaultRenderTag = RenderTag(3, RenderTag.CONNECT_SELF, RenderTag.MASK_NA) // 'update' block private val defaultRenderTag = RenderTag(3, RenderTag.CONNECT_SELF, RenderTag.MASK_NA) // 'update' block
var initialised = false var initialised = false
@@ -56,14 +63,16 @@ object CreateTileAtlas {
private var atlasCursor = 0 private var atlasCursor = 0
private var atlasCursorGlow = 0 private var atlasCursorGlow = 0
private val atlasInit = "./assets/graphics/blocks/init.tga" private val atlasInit = "./assets/graphics/blocks/init.tga"
private var itemSheetCursor = 16
/** /**
* Must be called AFTER mods' loading so that all the block props are loaded * Must be called AFTER mods' loading so that all the block props are loaded
*/ */
operator fun invoke(updateExisting: Boolean = false) { if (updateExisting || !initialised) { operator fun invoke(updateExisting: Boolean = false) { if (updateExisting || !initialised) {
tags = HashMap<Int, RenderTag>() tags = HashMap<ItemID, RenderTag>()
tags[0] = RenderTag(0, RenderTag.CONNECT_SELF, RenderTag.MASK_NA) itemSheetNumbers = HashMap<ItemID, Int>()
tags[Block.AIR] = RenderTag(0, RenderTag.CONNECT_SELF, RenderTag.MASK_NA)
atlas = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888) atlas = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
atlasAutumn = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888) atlasAutumn = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
@@ -86,27 +95,27 @@ object CreateTileAtlas {
// get all the files applicable // get all the files applicable
// first, get all the '/blocks' directory, and add all the files, regardless of their extension, to the list // first, get all the '/blocks' directory, and add all the files, regardless of their extension, to the list
val tgaList = ArrayList<FileHandle>() val tgaList = ArrayList<Pair<String, FileHandle>>() //Pair of <modname, filehandle>
ModMgr.getGdxFilesFromEveryMod("blocks").forEach { ModMgr.getGdxFilesFromEveryMod("blocks").forEach { (modname, filehandle) ->
if (!it.isDirectory) { if (!filehandle.isDirectory) {
throw Error("Path '${it.path()}' is not a directory") throw Error("Path '${filehandle.path()}' is not a directory")
} }
it.list().forEach { tgaFile -> filehandle.list().forEach { tgaFile ->
if (!tgaFile.isDirectory && (tgaFile.name().matches(tileNameRegex))) { if (!tgaFile.isDirectory && (tgaFile.name().matches(tileNameRegex))) {
tgaList.add(tgaFile) tgaList.add(modname to tgaFile)
} }
} }
} }
// Sift through the file list for blocks, but TGA format first // Sift through the file list for blocks, but TGA format first
tgaList.forEach { tgaList.forEach { (modname, filehandle) ->
try { try {
val glowFile = Gdx.files.internal(it.path().dropLast(4) + "_glow.tga") // assuming strict ".tga" file val glowFile = Gdx.files.internal(filehandle.path().dropLast(4) + "_glow.tga") // assuming strict ".tga" file
fileToAtlantes(it, if (glowFile.exists()) glowFile else null) fileToAtlantes(modname, filehandle, if (glowFile.exists()) glowFile else null)
} }
catch (e: GdxRuntimeException) { catch (e: GdxRuntimeException) {
System.err.println("Couldn't load file $it, skipping...") System.err.println("Couldn't load file $filehandle from $modname, skipping...")
} }
} }
@@ -127,73 +136,6 @@ object CreateTileAtlas {
} }
}*/ }*/
// Sift through the file list for fluids, but TGA format first
val fluidMasterPixmap = Pixmap(TILE_SIZE * 47, TILE_SIZE * 8, Pixmap.Format.RGBA8888)
tgaList.filter { it.name().matches(validFluidTilesFilename) && it.extension().toUpperCase() == "TGA" }.forEachIndexed { fluidLevel, it ->
val pixmap = Pixmap(it)
// dirty manual copy
repeat(5) {
fluidMasterPixmap.drawPixmap(pixmap,
it * TILE_SIZE * 7, fluidLevel * TILE_SIZE,
0, TILE_SIZE * it,
TILE_SIZE * 7, TILE_SIZE
)
}
repeat(2) {
fluidMasterPixmap.drawPixmap(pixmap,
(35 + it * 6) * TILE_SIZE, fluidLevel * TILE_SIZE,
0, TILE_SIZE * (5 + it),
TILE_SIZE * 6, TILE_SIZE
)
}
pixmap.dispose()
}
// test print
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/fluidpixmapmaster.tga"), fluidMasterPixmap, false)
// occupy the fluid pixmap with software rendering
for (i in BlockCodex.MAX_TERRAIN_TILES..BlockCodex.highestNumber) {
val fluid = Color(BlockCodex[i].colour)
// pixmap <- (color SCREEN fluidMasterPixmap)
// then occupy the atlasFluid
val pixmap = Pixmap(fluidMasterPixmap.width, fluidMasterPixmap.height, Pixmap.Format.RGBA8888)
pixmap.blending = Pixmap.Blending.None
for (y in 0 until pixmap.height) {
for (x in 0 until pixmap.width) {
val inColour = Color(fluidMasterPixmap.getPixel(x, y))
// SCREEN for RGB, MUL for A.
inColour.r = 1f - (1f - fluid.r) * (1f - inColour.r)
inColour.g = 1f - (1f - fluid.g) * (1f - inColour.g)
inColour.b = 1f - (1f - fluid.b) * (1f - inColour.b)
inColour.a = fluid.a * inColour.a
pixmap.drawPixel(x, y, inColour.toRGBA())
}
}
// test print
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/$i.tga"), pixmap, false)
// to the atlas
val atlasTargetPos = 16 + 47 * 8 * (i - BlockCodex.MAX_TERRAIN_TILES)
for (k in 0 until 47 * 8) {
val srcX = (k % 47) * TILE_SIZE
val srcY = (k / 47) * TILE_SIZE
val destX = ((atlasTargetPos + k) % TILES_IN_X) * TILE_SIZE
val destY = ((atlasTargetPos + k) / TILES_IN_X) * TILE_SIZE
atlasFluid.drawPixmap(pixmap, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
}
pixmap.dispose()
}
fluidMasterPixmap.dispose()
// create item_wall images // create item_wall images
fun maskTypetoTileIDForItemImage(maskType: Int) = when(maskType) { fun maskTypetoTileIDForItemImage(maskType: Int) = when(maskType) {
@@ -204,14 +146,14 @@ object CreateTileAtlas {
val itemTerrainPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888) val itemTerrainPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
val itemWallPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888) val itemWallPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
val terrainColormapPixmap = Pixmap(16, TILES_IN_X, Pixmap.Format.RGBA8888)
CreateTileAtlas.tags.toMap().forEach { t, u -> CreateTileAtlas.tags.toMap().forEach { id, tag ->
val tilePosFromAtlas = u.tileNumber + maskTypetoTileIDForItemImage(u.maskType) val tilePosFromAtlas = tag.tileNumber + maskTypetoTileIDForItemImage(tag.maskType)
val srcX = (tilePosFromAtlas % TILES_IN_X) * TILE_SIZE val srcX = (tilePosFromAtlas % TILES_IN_X) * TILE_SIZE
val srcY = (tilePosFromAtlas / TILES_IN_X) * TILE_SIZE val srcY = (tilePosFromAtlas / TILES_IN_X) * TILE_SIZE
val destX = (t % 16) * TILE_SIZE val t = tileIDtoItemSheetNumber(id)
val destY = (t / 16) * TILE_SIZE val destX = (t % ITEM_ATLAS_TILES_X) * TILE_SIZE
val destY = (t / ITEM_ATLAS_TILES_X) * TILE_SIZE
itemTerrainPixmap.drawPixmap(CreateTileAtlas.atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE) itemTerrainPixmap.drawPixmap(CreateTileAtlas.atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
itemWallPixmap.drawPixmap(CreateTileAtlas.atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE) itemWallPixmap.drawPixmap(CreateTileAtlas.atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
} }
@@ -222,35 +164,35 @@ object CreateTileAtlas {
itemWallPixmap.drawPixel(x, y, c) itemWallPixmap.drawPixel(x, y, c)
} }
} }
// create terrain colourmap // create terrain colourmap
terrainTileColourMap = HashMap<ItemID, Cvec>()
val pxCount = TILE_SIZE * TILE_SIZE val pxCount = TILE_SIZE * TILE_SIZE
for (id in 0 until BlockCodex.MAX_TERRAIN_TILES) { for (id in itemSheetNumbers) {
val tx = (id % 16) * TILE_SIZE val tilenum = id.value
val ty = (id / 16) * TILE_SIZE val tx = (tilenum % ITEM_ATLAS_TILES_X) * TILE_SIZE
var r = 0; var g = 0; var b = 0; var a = 0 val ty = (tilenum / ITEM_ATLAS_TILES_X) * TILE_SIZE
var r = 0f; var g = 0f; var b = 0f; var a = 0f
// average out the whole block // average out the whole block
for (y in ty until ty + TILE_SIZE) { for (y in ty until ty + TILE_SIZE) {
for (x in tx until tx + TILE_SIZE) { for (x in tx until tx + TILE_SIZE) {
val data = itemTerrainPixmap.getPixel(x, y) val data = itemTerrainPixmap.getPixel(x, y)
r += (data ushr 24) and 255 r += ((data ushr 24) and 255).div(255f)
g += (data ushr 16) and 255 g += ((data ushr 16) and 255).div(255f)
b += (data ushr 8) and 255 b += ((data ushr 8) and 255).div(255f)
a += data and 255 a += (data and 255).div(255f)
} }
} }
terrainColormapPixmap.drawPixel(tx / TILE_SIZE, ty / TILE_SIZE, terrainTileColourMap[id.key] = Cvec(
(r / pxCount).shl(24) or (r / pxCount),
(g / pxCount).shl(16) or (g / pxCount),
(b / pxCount).shl(8) or (b / pxCount),
(a / pxCount) (a / pxCount)
) )
} }
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/terrain_colormap.tga"), terrainColormapPixmap, false)
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/terrainitem.tga"), itemTerrainPixmap, false)
terrainTileColourMap = GdxColorMap(terrainColormapPixmap)
itemTerrainTexture = Texture(itemTerrainPixmap) itemTerrainTexture = Texture(itemTerrainPixmap)
itemWallTexture = Texture(itemWallPixmap) itemWallTexture = Texture(itemWallPixmap)
itemTerrainPixmap.dispose() itemTerrainPixmap.dispose()
@@ -259,7 +201,7 @@ object CreateTileAtlas {
initialised = true initialised = true
} } } }
fun getRenderTag(blockID: Int): RenderTag { fun getRenderTag(blockID: ItemID): RenderTag {
return tags.getOrDefault(blockID, defaultRenderTag) return tags.getOrDefault(blockID, defaultRenderTag)
} }
@@ -273,10 +215,11 @@ object CreateTileAtlas {
private val nullTile = Pixmap(TILE_SIZE * 16, TILE_SIZE * 16, Pixmap.Format.RGBA8888) private val nullTile = Pixmap(TILE_SIZE * 16, TILE_SIZE * 16, Pixmap.Format.RGBA8888)
private fun fileToAtlantes(matte: FileHandle, glow: FileHandle?) { private fun fileToAtlantes(modname: String, matte: FileHandle, glow: FileHandle?) {
val tilesPixmap = Pixmap(matte) val tilesPixmap = Pixmap(matte)
val tilesGlowPixmap = if (glow != null) Pixmap(glow) else nullTile val tilesGlowPixmap = if (glow != null) Pixmap(glow) else nullTile
val blockID = matte.nameWithoutExtension().toInt() val blockName = matte.nameWithoutExtension().toInt() // basically a filename
val blockID = "$modname:$blockName"
// determine the type of the block (populate tags list) // determine the type of the block (populate tags list)
// predefined by the image dimension: 16x16 for (1,0) // predefined by the image dimension: 16x16 for (1,0)
@@ -317,14 +260,20 @@ object CreateTileAtlas {
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tileCount) drawToAtlantes(tilesPixmap, tilesGlowPixmap, tileCount)
} }
itemSheetNumbers[blockID] = itemSheetCursor
itemSheetCursor += 1
tilesPixmap.dispose() tilesPixmap.dispose()
} }
fun tileIDtoAtlasNumber(tileID: ItemID) = tags[tileID]!!.tileNumber
fun tileIDtoItemSheetNumber(tileID: ItemID) = itemSheetNumbers[tileID]!!
/** /**
* This function must precede the drawToAtlantes() function, as the marking requires the variable * This function must precede the drawToAtlantes() function, as the marking requires the variable
* 'atlasCursor' and the draw function modifies it! * 'atlasCursor' and the draw function modifies it!
*/ */
private fun addTag(id: Int, connectionType: Int, maskType: Int) { private fun addTag(id: ItemID, connectionType: Int, maskType: Int) {
if (tags.containsKey(id)) { if (tags.containsKey(id)) {
throw Error("Block $id already exists") throw Error("Block $id already exists")
} }
@@ -391,6 +340,9 @@ object CreateTileAtlas {
} }
} }
/**
* @param tileNumber ordinal number of a tile in the texture atlas
*/
data class RenderTag(val tileNumber: Int, val connectionType: Int, val maskType: Int) { data class RenderTag(val tileNumber: Int, val connectionType: Int, val maskType: Int) {
companion object { companion object {
const val CONNECT_MUTUAL = 0 const val CONNECT_MUTUAL = 0

View File

@@ -487,14 +487,14 @@ object LightmapRenderer {
if (_thisFluid.type != Fluid.NULL) { if (_thisFluid.type != Fluid.NULL) {
_fluidAmountToCol.set(_thisFluid.amount, _thisFluid.amount, _thisFluid.amount, _thisFluid.amount) _fluidAmountToCol.set(_thisFluid.amount, _thisFluid.amount, _thisFluid.amount, _thisFluid.amount)
_thisTileLuminosity.set(BlockCodex[_thisTerrain].getLumCol(worldX, worldY)) _thisTileLuminosity.set(BlockCodex[world.tileNumberToNameMap[_thisTerrain]].getLumCol(worldX, worldY))
_thisTileLuminosity.maxAndAssign(BlockCodex[_thisFluid.type].getLumCol(worldX, worldY).mul(_fluidAmountToCol)) // already been div by four _thisTileLuminosity.maxAndAssign(BlockCodex[_thisFluid.type].getLumCol(worldX, worldY).mul(_fluidAmountToCol)) // already been div by four
_mapThisTileOpacity.setVec(lx, ly, BlockCodex[_thisTerrain].opacity) _mapThisTileOpacity.setVec(lx, ly, BlockCodex[world.tileNumberToNameMap[_thisTerrain]].opacity)
_mapThisTileOpacity.max(lx, ly, BlockCodex[_thisFluid.type].opacity.mul(_fluidAmountToCol))// already been div by four _mapThisTileOpacity.max(lx, ly, BlockCodex[_thisFluid.type].opacity.mul(_fluidAmountToCol))// already been div by four
} }
else { else {
_thisTileLuminosity.set(BlockCodex[_thisTerrain].getLumCol(worldX, worldY)) _thisTileLuminosity.set(BlockCodex[world.tileNumberToNameMap[_thisTerrain]].getLumCol(worldX, worldY))
_mapThisTileOpacity.setVec(lx, ly, BlockCodex[_thisTerrain].opacity) _mapThisTileOpacity.setVec(lx, ly, BlockCodex[world.tileNumberToNameMap[_thisTerrain]].opacity)
} }
_mapThisTileOpacity2.setR(lx, ly, _mapThisTileOpacity.getR(lx, ly) * 1.41421356f) _mapThisTileOpacity2.setR(lx, ly, _mapThisTileOpacity.getR(lx, ly) * 1.41421356f)
@@ -504,7 +504,8 @@ object LightmapRenderer {
// open air || luminous tile backed by sunlight // open air || luminous tile backed by sunlight
if ((_thisTerrain == AIR && _thisWall == AIR) || (_thisTileLuminosity.nonZero() && _thisWall == AIR)) { if ((world.tileNumberToNameMap[_thisTerrain] == AIR && world.tileNumberToNameMap[_thisWall] == AIR) ||
(_thisTileLuminosity.nonZero() && world.tileNumberToNameMap[_thisWall] == AIR)) {
_mapLightLevelThis.setVec(lx, ly, sunLight) _mapLightLevelThis.setVec(lx, ly, sunLight)
} }

View File

@@ -71,11 +71,17 @@ Payload "FlFL" -- world fluid fills, array of: (Int48 tileAddress, Float32 amoun
Payload "WiNt" -- wiring nodes, in JSON format Payload "WiNt" -- wiring nodes, in JSON format
Payload "CtYP" -- conduit types, array of: (Int48 tileAddress, Uint32 bitarray) Payload "TMaP" -- tile number to name map, array of: (Int32, tileNumber, String itemID)
String is null-terminated byte array
TODO need a format that can store arbitrary number of conduits, not just limited to 32
/*Payload "CtYP" -- conduit types, array of: (Int48 tileAddress, Uint32 bitarray)
can hold 32 different wires simultaneously can hold 32 different wires simultaneously
Payload "CfL0" -- conduit fills, aka size of liquid/gas packet, array of: (Int48 tileAddress, Float32 fill) Payload "CfL0" -- conduit fills, aka size of liquid/gas packet, array of: (Int48 tileAddress, Float32 fill)
CfL0..CfL9, CfLa..CfLf are available to store values for 16 different things. CfL0..CfL9, CfLa..CfLf are available to store values for 16 different things.*/
EOF 45 E EOF 45 E
EOF 6E n EOF 6E n