mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
merging branch the-flattening into master
This commit is contained in:
@@ -1,17 +1,42 @@
|
||||
## 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 within a domain.
|
||||
|
||||
### Prefixes
|
||||
|Name|Description|
|
||||
|----|-----------|
|
||||
|wall|Wall, only used by the Inventory to differentiate walls from blocks (therefore wall shares same "ID Space" with blocks/fluids/wires)|
|
||||
|item|Item (Static), uses different "ID Space" with blocks/walls/fluids/wires|
|
||||
|
||||
Notes:
|
||||
- BlockCodex and ItemCodex will not store prefix part of the ID, as blocks and walls are identical in properties
|
||||
- Wires and Fluids use the same "ID Space" as the tiles; they just happened to exclusive to their own layers.
|
||||
This simplifies many things e.g. only one TileID-to-AtlasTileNumber map is needed and the renderer will
|
||||
greatly benefit from it.
|
||||
|
||||
### Predefined Modnames
|
||||
|
||||
|Name|Description|
|
||||
|----|-----------|
|
||||
|dyn|Dynamic Item|
|
||||
|actor|Actor As an Item. Integer ID is identical to the actor's Reference ID|
|
||||
|virt|Virtual Tile Number|
|
||||
|
||||
### Integer ID Domains
|
||||
|
||||
|Range|Description|
|
||||
|-----|-----------|
|
||||
|0..65535|Tiles (65536 possible)|
|
||||
|65536..131071|Walls (65536 possible)|
|
||||
|131072..135167|Wires (4096 possible)|
|
||||
|135168..0x0F_FFFF|Items (static) (1M possible)|
|
||||
|0x10_0000..0x0FFF_FFFF|Items (dynamic\*) (267M possible)|
|
||||
|0x1000_0000..0x7FFF_FFFF|Actors (1879M possible)|
|
||||
|-2..-1048576|Virtual Tiles|
|
||||
|-2147483648..-1048577 (all negative numbers)|Faction (2147M possible)|
|
||||
|1..2147483647|Integer ID for dynamic items|
|
||||
|0x1000_0000..0x7FFF_FFFF|Reference ID for Actors (1879M possible)|
|
||||
|1..2147483647|Integer ID for virtual tiles|
|
||||
|
||||
* dynamic items have own properties that will persist through savegame.
|
||||
|
||||
Actors range in-depth
|
||||
Actor range in-depth
|
||||
|
||||
|Range|Description|
|
||||
|-----|-----------|
|
||||
|
||||
BIN
assets/graphics/blocks/init.tga
LFS
BIN
assets/graphics/blocks/init.tga
LFS
Binary file not shown.
BIN
assets/mods/basegame/blocks/0.tga
LFS
Normal file
BIN
assets/mods/basegame/blocks/0.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/blocks/_8192.tga
LFS
Normal file
BIN
assets/mods/basegame/blocks/_8192.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/blocks/_8193.tga
LFS
Normal file
BIN
assets/mods/basegame/blocks/_8193.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/blocks/_8194.tga
LFS
Normal file
BIN
assets/mods/basegame/blocks/_8194.tga
LFS
Normal file
Binary file not shown.
BIN
assets/mods/basegame/blocks/_8195.tga
LFS
Normal file
BIN
assets/mods/basegame/blocks/_8195.tga
LFS
Normal file
Binary file not shown.
@@ -1,6 +1,5 @@
|
||||
"id";"drop";"name";"shdr";"shdg";"shdb";"shduv";"str";"dsty";"mate";"solid";"plat";"wall";"grav";"dlfn";"fv";"fr";"lumr";"lumg";"lumb";"lumuv";"colour";"vscs"
|
||||
"0";"0";"BLOCK_AIR";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A"
|
||||
"1";"1";"BLOCK_MIASMA";"0.0312";"0.0312";"0.0312";"0.0312";"1";"1";"NULL";"0";"0";"1";"N/A";"0";"0";"4";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A"
|
||||
"16";"17";"BLOCK_STONE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"0";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A"
|
||||
"17";"17";"BLOCK_STONE_QUARRIED";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"0";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A"
|
||||
"18";"18";"BLOCK_STONE_TILE_WHITE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"0";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A"
|
||||
|
||||
|
12
assets/mods/basegame/blocks/wires.csv
Normal file
12
assets/mods/basegame/blocks/wires.csv
Normal file
@@ -0,0 +1,12 @@
|
||||
"id";"drop";"name";"accept";"inputcount";"inputtype";"outputtype"
|
||||
"8192";"8192";"WIRE_RED";"digital_bit";"N/A";"N/A";"N/A"
|
||||
"8193";"8193";"WIRE_GREEN";"digital_bit";"N/A";"N/A";"N/A"
|
||||
"8194";"8194";"WIRE_BLUE";"digital_bit";"N/A";"N/A";"N/A"
|
||||
"8195";"8195";"WIRE_BUNDLE";"digital_3bits";"N/A";"N/A";"N/A"
|
||||
"bundlemaker";"bundlemaker";"WIRE_BUNDLEMAKER";"N/A";3;"digital_bit";"digital_3bits"
|
||||
|
||||
|
||||
# accept: which wiretype (defined elsewhere) the wires acceps. Use comma to separate multiple. N/A for electronic components (aka "not wires")
|
||||
# inputcount: how many sides are input (outputcount is deduced from the inputcount). N/A for wires
|
||||
# inputtype: which wiretype it accepts. N/A for wires
|
||||
# outputtype: which wiretype it emits. N/A for wires
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 131.
|
@@ -1,7 +1,7 @@
|
||||
"id";"classname"
|
||||
"135168";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeCopper"
|
||||
"135169";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeIron"
|
||||
"135170";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeSteel"
|
||||
"135171";"net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire"
|
||||
"135172";"net.torvald.terrarum.modulebasegame.gameitems.TikiTorchTester"
|
||||
"135173";"net.torvald.terrarum.modulebasegame.gameitems.ItemCraftingTable"
|
||||
"1";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeCopper"
|
||||
"2";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeIron"
|
||||
"3";"net.torvald.terrarum.modulebasegame.gameitems.PickaxeSteel"
|
||||
"4";"net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire"
|
||||
"5";"net.torvald.terrarum.modulebasegame.gameitems.TikiTorchTester"
|
||||
"6";"net.torvald.terrarum.modulebasegame.gameitems.ItemCraftingTable"
|
||||
|
||||
|
@@ -76,7 +76,7 @@ void main() {
|
||||
int tile = getTileFromColor(tileFromMap);
|
||||
int breakage = getBreakageFromColor(tileFromMap);
|
||||
ivec2 tileXY = getTileXY(tile);
|
||||
ivec2 breakageXY = getTileXY(breakage + 5); // +5 is hard-coded constant that depends on the atlas
|
||||
ivec2 breakageXY = getTileXY(breakage + 5); // +5 is hard-coded constant that depends on the contents of the atlas
|
||||
|
||||
// calculate the UV coord value for texture sampling //
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import net.torvald.terrarum.modulebasegame.TerrarumIngame;
|
||||
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory;
|
||||
import net.torvald.terrarum.utils.JsonFetcher;
|
||||
import net.torvald.terrarum.utils.JsonWriter;
|
||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas;
|
||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase;
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack;
|
||||
import net.torvald.util.ArrayListMap;
|
||||
@@ -494,6 +495,10 @@ public class AppLoader implements ApplicationListener {
|
||||
|
||||
// make loading list
|
||||
CommonResourcePool.INSTANCE.loadAll();
|
||||
|
||||
// create tile atlas
|
||||
printdbg(this, "Making terrain textures...");
|
||||
CreateTileAtlas.INSTANCE.invoke(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1123,6 +1128,21 @@ public class AppLoader implements ApplicationListener {
|
||||
return ((float[]) cfg);
|
||||
}
|
||||
|
||||
public static String[] getConfigStringArray(String key) {
|
||||
Object cfg = getConfigMaster(key);
|
||||
if (cfg instanceof JsonArray) {
|
||||
JsonArray jsonArray = ((JsonArray) cfg).getAsJsonArray();
|
||||
//return IntArray(jsonArray.size(), { i -> jsonArray[i].asInt })
|
||||
String[] intArray = new String[jsonArray.size()];
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
intArray[i] = jsonArray.get(i).getAsString();
|
||||
}
|
||||
return intArray;
|
||||
}
|
||||
else
|
||||
return ((String[]) cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config from config file. If the entry does not exist, get from defaults; if the entry is not in the default, NullPointerException will be thrown
|
||||
*/
|
||||
|
||||
@@ -111,7 +111,7 @@ object DefaultConfig {
|
||||
|
||||
// settings regarding debugger
|
||||
val buildingMakerFavs = JsonArray()
|
||||
intArrayOf(
|
||||
arrayOf(
|
||||
Block.GLASS_CRUDE,
|
||||
Block.PLANK_NORMAL,
|
||||
Block.PLANK_BIRCH,
|
||||
@@ -120,9 +120,10 @@ object DefaultConfig {
|
||||
|
||||
Block.STONE_TILE_WHITE,
|
||||
Block.TORCH,
|
||||
Block.PLANK_NORMAL + BlockCodex.MAX_TERRAIN_TILES,
|
||||
Block.PLANK_BIRCH + BlockCodex.MAX_TERRAIN_TILES,
|
||||
Block.GLASS_CRUDE + BlockCodex.MAX_TERRAIN_TILES).forEach {
|
||||
"wall@" + Block.PLANK_NORMAL,
|
||||
"wall@" + Block.PLANK_BIRCH,
|
||||
"wall@" + Block.GLASS_CRUDE
|
||||
).forEach {
|
||||
buildingMakerFavs.add(it)
|
||||
}
|
||||
jsonObject.add("buildingmakerfavs", buildingMakerFavs)
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.utils.Queue
|
||||
import net.torvald.terrarum.AppLoader.printdbg
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
@@ -141,17 +142,17 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
||||
*
|
||||
* 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)
|
||||
terrainChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
|
||||
terrainChangeQueue.addLast(BlockChangeQueueItem(old, new, x, y))
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
wallChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
|
||||
wallChangeQueue.addLast(BlockChangeQueueItem(old, new, x, y))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,9 +161,9 @@ open class IngameInstance(val batch: SpriteBatch) : Screen {
|
||||
* @param old previous 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)
|
||||
wireChangeQueue.addFirst(BlockChangeQueueItem(old, new, x, y))
|
||||
wireChangeQueue.addLast(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: List<String>) {}
|
||||
|
||||
@@ -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
|
||||
* contain the file, the mod will be skipped. */
|
||||
fun getFilesFromEveryMod(path: String): List<File> {
|
||||
* contain the file, the mod will be skipped.
|
||||
*
|
||||
* @return List of pairs<modname, file>
|
||||
*/
|
||||
fun getFilesFromEveryMod(path: String): List<Pair<String, File>> {
|
||||
val path = path.sanitisePath()
|
||||
val moduleNames = moduleInfo.keys.toList()
|
||||
|
||||
val filesList = ArrayList<File>()
|
||||
val filesList = ArrayList<Pair<String, File>>()
|
||||
moduleNames.forEach {
|
||||
val file = File(getPath(it, path))
|
||||
|
||||
if (file.exists()) filesList.add(file)
|
||||
if (file.exists()) filesList.add(it to file)
|
||||
}
|
||||
|
||||
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
|
||||
* contain the file, the mod will be skipped.
|
||||
*
|
||||
* Returning files are read-only. */
|
||||
fun getGdxFilesFromEveryMod(path: String): List<FileHandle> {
|
||||
* Returning files are read-only.
|
||||
* @return List of pairs<modname, filehandle>
|
||||
*/
|
||||
fun getGdxFilesFromEveryMod(path: String): List<Pair<String, FileHandle>> {
|
||||
val path = path.sanitisePath()
|
||||
val moduleNames = moduleInfo.keys.toList()
|
||||
|
||||
val filesList = ArrayList<FileHandle>()
|
||||
val filesList = ArrayList<Pair<String, FileHandle>>()
|
||||
moduleNames.forEach {
|
||||
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()
|
||||
@@ -230,16 +235,17 @@ object ModMgr {
|
||||
@JvmStatic operator fun invoke(module: String) {
|
||||
val csv = CSVFetcher.readFromModule(module, itemPath + "itemid.csv")
|
||||
csv.forEach {
|
||||
val className = it["classname"].toString()
|
||||
val itemID = it["id"].toInt()
|
||||
val className: String = it["classname"].toString()
|
||||
val internalID: Int = it["id"].toInt()
|
||||
val itemName: String = "item@$module:$internalID"
|
||||
|
||||
printdbg(this, "Reading item #$itemID with className $className")
|
||||
printdbg(this, "Reading item ${itemName} <<- internal #$internalID with className $className")
|
||||
|
||||
val loadedClass = Class.forName(className)
|
||||
val loadedClassConstructor = loadedClass.getConstructor(ItemID::class.java)
|
||||
val loadedClassInstance = loadedClassConstructor.newInstance(itemID)
|
||||
val loadedClassInstance = loadedClassConstructor.newInstance(itemName)
|
||||
|
||||
ItemCodex[itemID] = loadedClassInstance as GameItem
|
||||
ItemCodex[itemName] = loadedClassInstance as GameItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,4 +22,6 @@ object ReferencingRanges {
|
||||
|
||||
val VIRTUAL_TILES = -2 downTo -1048576 // index of -1 breaks things for some reason :(
|
||||
|
||||
val PREFIX_DYNAMICITEM = "dyn:"
|
||||
val PREFIX_ACTORITEM = "actor:"
|
||||
}
|
||||
@@ -5,128 +5,128 @@ package net.torvald.terrarum.blockproperties
|
||||
*/
|
||||
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_QUARRIED = 17
|
||||
const val STONE_TILE_WHITE = 18
|
||||
const val STONE_BRICKS = 19
|
||||
const val STONE = "basegame:16"
|
||||
const val STONE_QUARRIED = "basegame:17"
|
||||
const val STONE_TILE_WHITE = "basegame:18"
|
||||
const val STONE_BRICKS = "basegame:19"
|
||||
|
||||
const val DIRT = 32
|
||||
const val GRASS = 33
|
||||
const val GRASSWALL = 34
|
||||
const val DIRT = "basegame:32"
|
||||
const val GRASS = "basegame:33"
|
||||
const val GRASSWALL = "basegame:34"
|
||||
|
||||
const val PLANK_NORMAL = 48
|
||||
const val PLANK_EBONY = 49
|
||||
const val PLANK_BIRCH = 50
|
||||
const val PLANK_BLOODROSE = 51
|
||||
const val PLANK_NORMAL = "basegame:48"
|
||||
const val PLANK_EBONY = "basegame:49"
|
||||
const val PLANK_BIRCH = "basegame:50"
|
||||
const val PLANK_BLOODROSE = "basegame:51"
|
||||
|
||||
const val TRUNK_NORMAL = 64
|
||||
const val TRUNK_EBONY = 65
|
||||
const val TRUNK_BIRCH = 66
|
||||
const val TRUNK_BLOODROSE = 67
|
||||
const val TRUNK_NORMAL = "basegame:64"
|
||||
const val TRUNK_EBONY = "basegame:65"
|
||||
const val TRUNK_BIRCH = "basegame:66"
|
||||
const val TRUNK_BLOODROSE = "basegame:67"
|
||||
|
||||
const val SAND = 80
|
||||
const val SAND_WHITE = 81
|
||||
const val SAND_RED = 82
|
||||
const val SAND_DESERT = 83
|
||||
const val SAND_BLACK = 84
|
||||
const val SAND_GREEN = 85
|
||||
const val SAND = "basegame:80"
|
||||
const val SAND_WHITE = "basegame:81"
|
||||
const val SAND_RED = "basegame:82"
|
||||
const val SAND_DESERT = "basegame:83"
|
||||
const val SAND_BLACK = "basegame:84"
|
||||
const val SAND_GREEN = "basegame:85"
|
||||
|
||||
const val GRAVEL = 96
|
||||
const val GRAVEL_GREY = 97
|
||||
const val GRAVEL = "basegame:96"
|
||||
const val GRAVEL_GREY = "basegame:97"
|
||||
|
||||
const val ORE_COPPER = 112
|
||||
const val ORE_IRON = 113
|
||||
const val ORE_GOLD = 114
|
||||
const val ORE_SILVER = 115
|
||||
const val ORE_ILMENITE = 116
|
||||
const val ORE_AURICHALCUM = 117
|
||||
const val ORE_COPPER = "basegame:112"
|
||||
const val ORE_IRON = "basegame:113"
|
||||
const val ORE_GOLD = "basegame:114"
|
||||
const val ORE_SILVER = "basegame:115"
|
||||
const val ORE_ILMENITE = "basegame:116"
|
||||
const val ORE_AURICHALCUM = "basegame:117"
|
||||
|
||||
const val RAW_RUBY = 128
|
||||
const val RAW_EMERALD = 129
|
||||
const val RAW_SAPPHIRE = 130
|
||||
const val RAW_TOPAZ = 131
|
||||
const val RAW_DIAMOND = 132
|
||||
const val RAW_AMETHYST = 133
|
||||
const val RAW_RUBY = "basegame:128"
|
||||
const val RAW_EMERALD = "basegame:129"
|
||||
const val RAW_SAPPHIRE = "basegame:130"
|
||||
const val RAW_TOPAZ = "basegame:131"
|
||||
const val RAW_DIAMOND = "basegame:132"
|
||||
const val RAW_AMETHYST = "basegame:133"
|
||||
|
||||
const val SNOW = 144
|
||||
const val ICE_FRAGILE = 145
|
||||
const val ICE_NATURAL = 146
|
||||
const val ICE_MAGICAL = 147
|
||||
const val SNOW = "basegame:144"
|
||||
const val ICE_FRAGILE = "basegame:145"
|
||||
const val ICE_NATURAL = "basegame:146"
|
||||
const val ICE_MAGICAL = "basegame:147"
|
||||
|
||||
const val GLASS_CRUDE = 148
|
||||
const val GLASS_CLEAN = 149
|
||||
const val GLASS_CRUDE = "basegame:148"
|
||||
const val GLASS_CLEAN = "basegame:149"
|
||||
|
||||
const val PLATFORM_STONE = 160
|
||||
const val PLATFORM_WOODEN = 161
|
||||
const val PLATFORM_EBONY = 162
|
||||
const val PLATFORM_BIRCH = 163
|
||||
const val PLATFORM_BLOODROSE = 164
|
||||
const val PLATFORM_STONE = "basegame:160"
|
||||
const val PLATFORM_WOODEN = "basegame:161"
|
||||
const val PLATFORM_EBONY = "basegame:162"
|
||||
const val PLATFORM_BIRCH = "basegame:163"
|
||||
const val PLATFORM_BLOODROSE = "basegame:164"
|
||||
|
||||
const val TORCH = 176
|
||||
const val TORCH_FROST = 177
|
||||
const val TORCH = "basegame:176"
|
||||
const val TORCH_FROST = "basegame:177"
|
||||
|
||||
const val TORCH_OFF = 192
|
||||
const val TORCH_FROST_OFF = 193
|
||||
const val TORCH_OFF = "basegame:192"
|
||||
const val TORCH_FROST_OFF = "basegame:193"
|
||||
|
||||
const val ILLUMINATOR_WHITE = 208
|
||||
const val ILLUMINATOR_YELLOW = 209
|
||||
const val ILLUMINATOR_ORANGE = 210
|
||||
const val ILLUMINATOR_RED = 211
|
||||
const val ILLUMINATOR_FUCHSIA = 212
|
||||
const val ILLUMINATOR_PURPLE = 213
|
||||
const val ILLUMINATOR_BLUE = 214
|
||||
const val ILLUMINATOR_CYAN = 215
|
||||
const val ILLUMINATOR_GREEN = 216
|
||||
const val ILLUMINATOR_GREEN_DARK = 217
|
||||
const val ILLUMINATOR_BROWN = 218
|
||||
const val ILLUMINATOR_TAN = 219
|
||||
const val ILLUMINATOR_GREY_LIGHT = 220
|
||||
const val ILLUMINATOR_GREY_MED = 221
|
||||
const val ILLUMINATOR_GREY_DARK = 222
|
||||
const val ILLUMINATOR_BLACK = 223
|
||||
const val ILLUMINATOR_WHITE = "basegame:208"
|
||||
const val ILLUMINATOR_YELLOW = "basegame:209"
|
||||
const val ILLUMINATOR_ORANGE = "basegame:210"
|
||||
const val ILLUMINATOR_RED = "basegame:211"
|
||||
const val ILLUMINATOR_FUCHSIA = "basegame:212"
|
||||
const val ILLUMINATOR_PURPLE = "basegame:213"
|
||||
const val ILLUMINATOR_BLUE = "basegame:214"
|
||||
const val ILLUMINATOR_CYAN = "basegame:215"
|
||||
const val ILLUMINATOR_GREEN = "basegame:216"
|
||||
const val ILLUMINATOR_GREEN_DARK = "basegame:217"
|
||||
const val ILLUMINATOR_BROWN = "basegame:218"
|
||||
const val ILLUMINATOR_TAN = "basegame:219"
|
||||
const val ILLUMINATOR_GREY_LIGHT = "basegame:220"
|
||||
const val ILLUMINATOR_GREY_MED = "basegame:221"
|
||||
const val ILLUMINATOR_GREY_DARK = "basegame:222"
|
||||
const val ILLUMINATOR_BLACK = "basegame:223"
|
||||
|
||||
const val ILLUMINATOR_WHITE_OFF = 224
|
||||
const val ILLUMINATOR_YELLOW_OFF = 225
|
||||
const val ILLUMINATOR_ORANGE_OFF = 226
|
||||
const val ILLUMINATOR_RED_OFF = 227
|
||||
const val ILLUMINATOR_FUCHSIA_OFF = 228
|
||||
const val ILLUMINATOR_PURPLE_OFF = 229
|
||||
const val ILLUMINATOR_BLUE_OFF = 230
|
||||
const val ILLUMINATOR_CYAN_OFF = 231
|
||||
const val ILLUMINATOR_GREEN_OFF = 232
|
||||
const val ILLUMINATOR_GREEN_DARK_OFF = 233
|
||||
const val ILLUMINATOR_BROWN_OFF = 234
|
||||
const val ILLUMINATOR_TAN_OFF = 235
|
||||
const val ILLUMINATOR_GREY_LIGHT_OFF = 236
|
||||
const val ILLUMINATOR_GREY_MED_OFF = 237
|
||||
const val ILLUMINATOR_GREY_DARK_OFF = 238
|
||||
const val ILLUMINATOR_BLACK_OFF = 239
|
||||
const val ILLUMINATOR_WHITE_OFF = "basegame:224"
|
||||
const val ILLUMINATOR_YELLOW_OFF = "basegame:225"
|
||||
const val ILLUMINATOR_ORANGE_OFF = "basegame:226"
|
||||
const val ILLUMINATOR_RED_OFF = "basegame:227"
|
||||
const val ILLUMINATOR_FUCHSIA_OFF = "basegame:228"
|
||||
const val ILLUMINATOR_PURPLE_OFF = "basegame:229"
|
||||
const val ILLUMINATOR_BLUE_OFF = "basegame:230"
|
||||
const val ILLUMINATOR_CYAN_OFF = "basegame:231"
|
||||
const val ILLUMINATOR_GREEN_OFF = "basegame:232"
|
||||
const val ILLUMINATOR_GREEN_DARK_OFF = "basegame:233"
|
||||
const val ILLUMINATOR_BROWN_OFF = "basegame:234"
|
||||
const val ILLUMINATOR_TAN_OFF = "basegame:235"
|
||||
const val ILLUMINATOR_GREY_LIGHT_OFF = "basegame:236"
|
||||
const val ILLUMINATOR_GREY_MED_OFF = "basegame:237"
|
||||
const val ILLUMINATOR_GREY_DARK_OFF = "basegame:238"
|
||||
const val ILLUMINATOR_BLACK_OFF = "basegame:239"
|
||||
|
||||
const val SANDSTONE = 240
|
||||
const val SANDSTONE_WHITE = 241
|
||||
const val SANDSTONE_RED = 242
|
||||
const val SANDSTONE_DESERT = 243
|
||||
const val SANDSTONE_BLACK = 244
|
||||
const val SANDSTONE_GREEN = 245
|
||||
const val SANDSTONE = "basegame:240"
|
||||
const val SANDSTONE_WHITE = "basegame:241"
|
||||
const val SANDSTONE_RED = "basegame:242"
|
||||
const val SANDSTONE_DESERT = "basegame:243"
|
||||
const val SANDSTONE_BLACK = "basegame:244"
|
||||
const val SANDSTONE_GREEN = "basegame:245"
|
||||
|
||||
const val LANTERN = 256
|
||||
const val SUNSTONE = 257
|
||||
const val DAYLIGHT_CAPACITOR = 258
|
||||
const val LANTERN = "basegame:256"
|
||||
const val SUNSTONE = "basegame:257"
|
||||
const val DAYLIGHT_CAPACITOR = "basegame:258"
|
||||
|
||||
|
||||
const val ACTORBLOCK_NO_COLLISION = 4091
|
||||
const val ACTORBLOCK_FULL_COLLISION = 4092
|
||||
const val ACTORBLOCK_ALLOW_MOVE_DOWN = 4093
|
||||
const val ACTORBLOCK_NO_PASS_RIGHT = 4094
|
||||
const val ACTORBLOCK_NO_PASS_LEFT = 4095
|
||||
const val ACTORBLOCK_NO_COLLISION = "basegame:4091"
|
||||
const val ACTORBLOCK_FULL_COLLISION = "basegame:4092"
|
||||
const val ACTORBLOCK_ALLOW_MOVE_DOWN = "basegame:4093"
|
||||
const val ACTORBLOCK_NO_PASS_RIGHT = "basegame:4094"
|
||||
const val ACTORBLOCK_NO_PASS_LEFT = "basegame:4095"
|
||||
|
||||
|
||||
const val LAVA = 4094
|
||||
const val WATER = 4095
|
||||
const val LAVA = "basegame:4094"
|
||||
const val WATER = "basegame:4095"
|
||||
|
||||
const val NULL = -1
|
||||
const val NULL = "basegame:-1"
|
||||
|
||||
val actorblocks = listOf(
|
||||
ACTORBLOCK_NO_COLLISION,
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.AppLoader.printdbg
|
||||
import net.torvald.terrarum.AppLoader.printmsg
|
||||
import net.torvald.terrarum.ReferencingRanges
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.FluidType
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.utils.CSVFetcher
|
||||
@@ -18,12 +19,12 @@ import java.io.IOException
|
||||
*/
|
||||
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 */
|
||||
val MAX_TERRAIN_TILES = GameWorld.TILES_SUPPORTED
|
||||
//val MAX_TERRAIN_TILES = GameWorld.TILES_SUPPORTED
|
||||
|
||||
private val nullProp = BlockProp()
|
||||
|
||||
@@ -32,12 +33,17 @@ object BlockCodex {
|
||||
|
||||
// fake props for "randomised" dynamic lights
|
||||
const val DYNAMIC_RANDOM_CASES = 64
|
||||
var virtualPropsCount = 0
|
||||
private set
|
||||
/** always points to the HIGHEST prop ID. <Original ID, Virtual ID> */
|
||||
val dynamicToVirtualPropMapping = ArrayList<Pair<Int, Int>>()
|
||||
/** for random access dont iterate over this */
|
||||
val dynamicToVirtualMap = hashMapOf<Int, Int>()
|
||||
private var virtualTileCursor = 1
|
||||
|
||||
/**
|
||||
* One-to-Many
|
||||
*/
|
||||
val tileToVirtual = HashMap<ItemID, List<ItemID>>()
|
||||
|
||||
/**
|
||||
* Many-to-One
|
||||
*/
|
||||
val virtualToTile = HashMap<ItemID, ItemID>()
|
||||
|
||||
/**
|
||||
* Later entry (possible from other modules) will replace older ones
|
||||
@@ -56,27 +62,28 @@ object BlockCodex {
|
||||
setProp(blockProps[intVal(it, "id")], it)
|
||||
}*/
|
||||
|
||||
val id = intVal(it, "id")
|
||||
setProp(id, it)
|
||||
setProp(module, intVal(it, "id"), it)
|
||||
val tileId = "$module:${intVal(it, "id")}"
|
||||
|
||||
// register tiles with dynamic light
|
||||
if ((blockProps[id]?.dynamicLuminosityFunction ?: 0) != 0) {
|
||||
dynamicLights.add(id)
|
||||
if ((blockProps[tileId]?.dynamicLuminosityFunction ?: 0) != 0) {
|
||||
dynamicLights.add(tileId)
|
||||
|
||||
// add virtual props for dynamic lights
|
||||
val virtualIDMax = ReferencingRanges.VIRTUAL_TILES.first - virtualPropsCount
|
||||
dynamicToVirtualPropMapping.add(id to virtualIDMax)
|
||||
dynamicToVirtualMap[id] = virtualIDMax
|
||||
repeat(DYNAMIC_RANDOM_CASES) { i ->
|
||||
setProp(virtualIDMax - i, it)
|
||||
printdbg(this, "Block ID $id -> Virtual ID ${virtualIDMax - i}, baseLum: ${blockProps[virtualIDMax - i]?.baseLumCol}")
|
||||
val virtualChunk = ArrayList<ItemID>()
|
||||
repeat(DYNAMIC_RANDOM_CASES) { _ ->
|
||||
val virtualID = "virt:$virtualTileCursor"
|
||||
|
||||
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) {
|
||||
@@ -84,6 +91,8 @@ object BlockCodex {
|
||||
}
|
||||
}
|
||||
|
||||
fun getAll() = blockProps.values
|
||||
|
||||
/*fun get(index: Int): BlockProp {
|
||||
try {
|
||||
return blockProps[index]
|
||||
@@ -97,7 +106,7 @@ object BlockCodex {
|
||||
}
|
||||
}*/
|
||||
|
||||
operator fun get(rawIndex: Int?): BlockProp {
|
||||
/*operator fun get(rawIndex: Int?): BlockProp {
|
||||
if (rawIndex == null || rawIndex == Block.NULL) {
|
||||
return nullProp
|
||||
}
|
||||
@@ -108,31 +117,45 @@ object BlockCodex {
|
||||
catch (e: NullPointerException) {
|
||||
throw NullPointerException("Blockprop with raw id $rawIndex does not exist.")
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(fluidType: FluidType?): BlockProp {
|
||||
if (fluidType == null || fluidType.value == 0) {
|
||||
return blockProps[Block.AIR]!!
|
||||
}*/
|
||||
operator fun get(blockID: ItemID?): BlockProp {
|
||||
if (blockID == null || blockID == "basegame:"+Block.NULL) {
|
||||
return nullProp
|
||||
}
|
||||
|
||||
try {
|
||||
return blockProps[fluidType.abs() + GameWorld.TILES_SUPPORTED - 1]!!
|
||||
return blockProps[blockID]!!
|
||||
}
|
||||
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>
|
||||
return blockProps[rawIndex]
|
||||
operator fun get(fluidType: FluidType?): BlockProp {
|
||||
// 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()
|
||||
prop.nameKey = record.get("name")
|
||||
|
||||
prop.id = if (key == -1) 0 else intVal(record, "id")
|
||||
prop.drop = intVal(record, "drop")
|
||||
prop.id = "$modname:$key"
|
||||
prop.drop = "$modname:${intVal(record, "drop")}"
|
||||
|
||||
prop.shadeColR = floatVal(record, "shdr")
|
||||
prop.shadeColG = floatVal(record, "shdg")
|
||||
@@ -163,9 +186,9 @@ object BlockCodex {
|
||||
|
||||
prop.dynamicLuminosityFunction = intVal(record, "dlfn")
|
||||
|
||||
blockProps[key] = prop
|
||||
blockProps[prop.id] = prop
|
||||
|
||||
printmsg(this, "${intVal(record, "id")}\t" + prop.nameKey)
|
||||
printmsg(this, "Setting prop ${prop.id} ->>\t${prop.nameKey}\tsolid:${prop.isSolid}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.torvald.terrarum.blockproperties
|
||||
|
||||
import net.torvald.gdx.graphics.Cvec
|
||||
import net.torvald.random.XXHash32
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.serialise.toLittle
|
||||
|
||||
@@ -10,7 +11,7 @@ import net.torvald.terrarum.serialise.toLittle
|
||||
*/
|
||||
class BlockProp {
|
||||
|
||||
var id: Int = 0
|
||||
var id: ItemID = ""
|
||||
|
||||
var nameKey: String = ""
|
||||
|
||||
@@ -62,14 +63,14 @@ class BlockProp {
|
||||
baseLumCol
|
||||
} else {
|
||||
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) {
|
||||
baseLumCol.getElem(channel)
|
||||
} else {
|
||||
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)
|
||||
|
||||
var drop: Int = 0
|
||||
var drop: ItemID = ""
|
||||
|
||||
var maxSupport: Int = -1 // couldn't use NULL at all...
|
||||
|
||||
|
||||
@@ -71,36 +71,34 @@ object BlockPropUtil {
|
||||
catch (skip: NullPointerException) {}
|
||||
}*/
|
||||
// update randomised virtual props instead
|
||||
for (keyMax in BlockCodex.dynamicToVirtualPropMapping) {
|
||||
repeat(BlockCodex.DYNAMIC_RANDOM_CASES) {
|
||||
val prop = BlockCodex[keyMax.second - it]
|
||||
val domain = when (prop.dynamicLuminosityFunction) {
|
||||
1 -> flickerFuncDomain
|
||||
4 -> breathCycleDuration
|
||||
5 -> pulsateCycleDuration
|
||||
else -> 0f
|
||||
}
|
||||
|
||||
// FPS-time compensation
|
||||
if (Gdx.graphics.framesPerSecond > 0) {
|
||||
prop.rngBase0 += Gdx.graphics.rawDeltaTime
|
||||
}
|
||||
|
||||
// reset timer
|
||||
if (prop.rngBase0 > domain) {
|
||||
prop.rngBase0 -= domain
|
||||
|
||||
// flicker related
|
||||
prop.rngBase1 = prop.rngBase2
|
||||
prop.rngBase2 = getNewRandom()
|
||||
}
|
||||
|
||||
prop._lumCol.set(getDynamicLumFunc(prop))
|
||||
//prop.lumColR = prop.lumCol.r
|
||||
//prop.lumColG = prop.lumCol.g
|
||||
//prop.lumColB = prop.lumCol.b
|
||||
//prop.lumColA = prop.lumCol.a
|
||||
for (key in BlockCodex.tileToVirtual.values.flatten()) {
|
||||
val prop = BlockCodex[key]
|
||||
val domain = when (prop.dynamicLuminosityFunction) {
|
||||
1 -> flickerFuncDomain
|
||||
4 -> breathCycleDuration
|
||||
5 -> pulsateCycleDuration
|
||||
else -> 0f
|
||||
}
|
||||
|
||||
// FPS-time compensation
|
||||
if (Gdx.graphics.framesPerSecond > 0) {
|
||||
prop.rngBase0 += Gdx.graphics.rawDeltaTime
|
||||
}
|
||||
|
||||
// reset timer
|
||||
if (prop.rngBase0 > domain) {
|
||||
prop.rngBase0 -= domain
|
||||
|
||||
// flicker related
|
||||
prop.rngBase1 = prop.rngBase2
|
||||
prop.rngBase2 = getNewRandom()
|
||||
}
|
||||
|
||||
prop._lumCol.set(getDynamicLumFunc(prop))
|
||||
//prop.lumColR = prop.lumCol.r
|
||||
//prop.lumColG = prop.lumCol.g
|
||||
//prop.lumColB = prop.lumCol.b
|
||||
//prop.lumColA = prop.lumCol.a
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.torvald.terrarum.blockstats
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||
@@ -14,7 +15,7 @@ import java.util.*
|
||||
*/
|
||||
object BlockStats {
|
||||
|
||||
private val tilestat = ShortArray(GameWorld.TILES_SUPPORTED)
|
||||
private val tilestat = HashMap<ItemID, Int>()
|
||||
|
||||
private val TSIZE = CreateTileAtlas.TILE_SIZE
|
||||
|
||||
@@ -22,7 +23,7 @@ object BlockStats {
|
||||
* Update tile stats from tiles on screen
|
||||
*/
|
||||
fun update() {
|
||||
Arrays.fill(tilestat, 0.toShort())
|
||||
tilestat.clear()
|
||||
|
||||
// Get stats on no-zoomed screen area. In other words, will behave as if screen zoom were 1.0
|
||||
// no matter how the screen is zoomed.
|
||||
@@ -47,29 +48,14 @@ object BlockStats {
|
||||
for (x in for_x_start..for_x_end - 1) {
|
||||
val tileWall = map.getTileFromWall(x, y)
|
||||
val tileTerrain = map.getTileFromTerrain(x, y)
|
||||
++tilestat[tileWall ?: 0]
|
||||
++tilestat[tileTerrain ?: 0]
|
||||
tilestat[tileWall] = 1 + (tilestat[tileWall] ?: 0)
|
||||
tilestat[tileTerrain] = 1 + (tilestat[tileTerrain] ?: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getCount(vararg tile: Byte): Int {
|
||||
var sum = 0
|
||||
for (i in tile.indices) {
|
||||
val newArgs = java.lang.Byte.toUnsignedInt(tile[i])
|
||||
sum += java.lang.Short.toUnsignedInt(tilestat[newArgs])
|
||||
}
|
||||
|
||||
return sum
|
||||
fun getCount(vararg tiles: ItemID): Int {
|
||||
return tiles.fold(0) { acc, key -> acc + (tilestat[key] ?: 0) }
|
||||
}
|
||||
|
||||
fun getCount(vararg tile: Int): Int {
|
||||
var sum = 0
|
||||
for (i in tile.indices) {
|
||||
sum += java.lang.Short.toUnsignedInt(tilestat[tile[i]])
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -134,10 +134,10 @@ object MinimapComposer : Disposable {
|
||||
|
||||
for (y in topLeftY until topLeftY + LIVETILE_SIZE) {
|
||||
for (x in if (tileSlotIndexY >= TILES_IN_X / 2) (topLeftX + LIVETILE_SIZE - 1) downTo topLeftX else topLeftX until topLeftX + LIVETILE_SIZE) {
|
||||
val tileTerr = world.getTileFromTerrain(x, y) ?: throw Error("OoB: $x, $y")
|
||||
val wallTerr = world.getTileFromWall(x, y) ?: Block.AIR
|
||||
val colTerr = CreateTileAtlas.terrainTileColourMap.get(tileTerr % 16, tileTerr / 16)
|
||||
val colWall = CreateTileAtlas.terrainTileColourMap.get(wallTerr % 16, wallTerr / 16).mul(BlocksDrawer.wallOverlayColour)
|
||||
val tileTerr = world.getTileFromTerrain(x, y)
|
||||
val wallTerr = world.getTileFromWall(x, y)
|
||||
val colTerr = CreateTileAtlas.terrainTileColourMap.get(tileTerr)!!.toGdxColor()
|
||||
val colWall = CreateTileAtlas.terrainTileColourMap.get(wallTerr)!!.toGdxColor().mul(CreateTileAtlas.wallOverlayColour)
|
||||
|
||||
val outCol = if (colTerr.a > 0.1f) colTerr else colWall
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.BlockProp
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.BlockAddress
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
@@ -1231,7 +1232,7 @@ open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties)
|
||||
*
|
||||
* Very straightforward for the actual solid tiles, not so much for the platforms
|
||||
*/
|
||||
private fun shouldICollideWithThis(tile: Int) =
|
||||
private fun shouldICollideWithThis(tile: ItemID) =
|
||||
// regular solid block
|
||||
(BlockCodex[tile].isSolid)
|
||||
|
||||
@@ -1240,7 +1241,7 @@ open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties)
|
||||
*
|
||||
* Just like "shouldICollideWithThis" but it's intended to work with feet tiles
|
||||
*/
|
||||
private fun shouldICollideWithThisFeet(tile: Int) =
|
||||
private fun shouldICollideWithThisFeet(tile: ItemID) =
|
||||
// regular solid block
|
||||
(BlockCodex[tile].isSolid) ||
|
||||
// platforms, moving downward AND not "going down"
|
||||
@@ -1295,7 +1296,7 @@ open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties)
|
||||
return contactAreaCounter
|
||||
}
|
||||
|
||||
private fun getTileFriction(tile: Int) =
|
||||
private fun getTileFriction(tile: ItemID) =
|
||||
if (physProp.immobileBody && tile == Block.AIR)
|
||||
BlockCodex[Block.AIR].friction.frictionToMult().div(500)
|
||||
.times(if (!grounded) elasticity else 1.0)
|
||||
@@ -1705,11 +1706,11 @@ open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties)
|
||||
}
|
||||
|
||||
|
||||
private fun forEachOccupyingTileNum(consumer: (Int?) -> Unit) {
|
||||
private fun forEachOccupyingTileNum(consumer: (ItemID?) -> Unit) {
|
||||
if (world == null) return
|
||||
|
||||
|
||||
val tiles = ArrayList<Int?>()
|
||||
val tiles = ArrayList<ItemID?>()
|
||||
for (y in hIntTilewiseHitbox.startY.toInt()..hIntTilewiseHitbox.endY.toInt()) {
|
||||
for (x in hIntTilewiseHitbox.startX.toInt()..hIntTilewiseHitbox.endX.toInt()) {
|
||||
tiles.add(world!!.getTileFromTerrain(x, y))
|
||||
@@ -1770,11 +1771,11 @@ open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties)
|
||||
return tilePosList.forEach(consumer)
|
||||
}
|
||||
|
||||
private fun forEachFeetTileNum(consumer: (Int?) -> Unit) {
|
||||
private fun forEachFeetTileNum(consumer: (ItemID?) -> Unit) {
|
||||
if (world == null) return
|
||||
|
||||
|
||||
val tiles = ArrayList<Int?>()
|
||||
val tiles = ArrayList<ItemID?>()
|
||||
|
||||
// offset 1 pixel to the down so that friction would work
|
||||
val y = hitbox.endY.plus(1.0).div(TILE_SIZE).floorInt()
|
||||
|
||||
@@ -46,6 +46,8 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
|
||||
}
|
||||
}
|
||||
|
||||
private var worldPrimaryClickLatched = false
|
||||
|
||||
fun update(delta: Float) {
|
||||
|
||||
///////////////////
|
||||
@@ -61,13 +63,18 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
|
||||
// also, some UIs should NOT affect item usage (e.g. quickslot) and ingame's uiOpened property is doing
|
||||
// the very job.
|
||||
|
||||
if (Gdx.input.isButtonPressed(AppLoader.getConfigInt("config_mouseprimary"))) {
|
||||
if (Gdx.input.isButtonPressed(AppLoader.getConfigInt("config_mouseprimary")) && !worldPrimaryClickLatched) {
|
||||
terrarumIngame.worldPrimaryClickStart(AppLoader.UPDATE_RATE)
|
||||
worldPrimaryClickLatched = true
|
||||
}
|
||||
/*if Gdx.input.isButtonPressed(AppLoader.getConfigInt("config_mousesecondary")) {
|
||||
ingame.worldSecondaryClickStart(AppLoader.UPDATE_RATE)
|
||||
}*/
|
||||
|
||||
if (!Gdx.input.isButtonPressed(AppLoader.getConfigInt("config_mouseprimary"))) {
|
||||
worldPrimaryClickLatched = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.ItemValue
|
||||
import net.torvald.terrarum.ReferencingRanges.PREFIX_DYNAMICITEM
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_DYNAMIC
|
||||
import net.torvald.terrarum.itemproperties.Material
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
|
||||
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
|
||||
@@ -40,7 +40,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
||||
abstract val originalName: String
|
||||
|
||||
|
||||
var newName: String = "I AM VITTUN PLACEHOLDER"
|
||||
var newName: String = "I AM VITUN PLACEHOLDER"
|
||||
private set
|
||||
|
||||
var name: String
|
||||
@@ -208,7 +208,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return dynamicID
|
||||
return dynamicID.hashCode()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
@@ -222,7 +222,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
||||
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
|
||||
|
||||
@@ -295,7 +295,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
||||
|
||||
|
||||
fun generateUniqueDynamicID(inventory: ActorInventory): GameItem {
|
||||
dynamicID = Companion.generateUniqueDynamicID(inventory)
|
||||
dynamicID = "$PREFIX_DYNAMICITEM${Companion.generateUniqueDynamicID(inventory)}"
|
||||
ItemCodex.registerNewDynamicItem(dynamicID, this)
|
||||
return this
|
||||
}
|
||||
@@ -307,8 +307,8 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
|
||||
fun generateUniqueDynamicID(inventory: ActorInventory): Int {
|
||||
var ret: Int
|
||||
do {
|
||||
ret = ITEM_DYNAMIC.pickRandom()
|
||||
} while (inventory.contains(ret))
|
||||
ret = (1..2147483647).pickRandom()
|
||||
} while (inventory.contains("$PREFIX_DYNAMICITEM$ret"))
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -9,10 +9,12 @@ import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.WorldSimulator
|
||||
import net.torvald.terrarum.printStackTrace
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.serialise.ReadLayerDataZip
|
||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||
import net.torvald.util.SortedArrayList
|
||||
import org.dyn4j.geometry.Vector2
|
||||
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.
|
||||
*/
|
||||
private val wiringBlocks: HashMap<BlockAddress, Int>
|
||||
private val wiringBlocks: HashMap<BlockAddress, ItemID>
|
||||
|
||||
//public World physWorld = new World( new Vec2(0, -Terrarum.game.gravitationalAccel) );
|
||||
//physics
|
||||
@@ -100,7 +102,14 @@ open class GameWorld : Disposable {
|
||||
open var TIME_T: Long = 0L
|
||||
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>
|
||||
|
||||
/**
|
||||
* Create new world
|
||||
*/
|
||||
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)")
|
||||
|
||||
@@ -133,8 +142,24 @@ open class GameWorld : Disposable {
|
||||
creationTime = creationTIME_T
|
||||
lastPlayTime = lastPlayTIME_T
|
||||
this.totalPlayTime = totalPlayTime
|
||||
|
||||
|
||||
tileNumberToNameMap = HashMap<Int, ItemID>()
|
||||
tileNameToNumberMap = HashMap<ItemID, Int>()
|
||||
CreateTileAtlas.tags.forEach {
|
||||
printdbg(this, "tileNumber ${it.value.tileNumber} <-> tileName ${it.key}")
|
||||
|
||||
tileNumberToNameMap[it.value.tileNumber] = it.key
|
||||
tileNameToNumberMap[it.key] = it.value.tileNumber
|
||||
}
|
||||
|
||||
// AN EXCEPTIONAL TERM: tilenum 0 is always redirected to Air tile, even if the tilenum for actual Air tile is not zero
|
||||
tileNumberToNameMap[0] = Block.AIR
|
||||
}
|
||||
|
||||
/**
|
||||
* Load existing world
|
||||
*/
|
||||
internal constructor(worldIndex: Int, layerData: ReadLayerDataZip.LayerData, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) {
|
||||
this.worldIndex = worldIndex
|
||||
|
||||
@@ -160,6 +185,28 @@ open class GameWorld : Disposable {
|
||||
creationTime = creationTIME_T
|
||||
lastPlayTime = lastPlayTIME_T
|
||||
this.totalPlayTime = totalPlayTime
|
||||
|
||||
// before the renaming, update the name maps
|
||||
tileNumberToNameMap = HashMap<Int, ItemID>()
|
||||
tileNameToNumberMap = HashMap<ItemID, Int>()
|
||||
CreateTileAtlas.tags.forEach {
|
||||
tileNumberToNameMap[it.value.tileNumber] = it.key
|
||||
tileNameToNumberMap[it.key] = it.value.tileNumber
|
||||
}
|
||||
|
||||
// perform renaming of tile layers
|
||||
val oldTileNumberToNameMap = layerData.tileNumberToNameMap
|
||||
for (y in 0 until layerTerrain.height) {
|
||||
for (x in 0 until layerTerrain.width) {
|
||||
layerTerrain.unsafeSetTile(x, y, tileNameToNumberMap[oldTileNumberToNameMap[layerTerrain.unsafeGetTile(x, y)]]!!)
|
||||
layerWall.unsafeSetTile(x, y, tileNameToNumberMap[oldTileNumberToNameMap[layerWall.unsafeGetTile(x, y)]]!!)
|
||||
// TODO rename fluid map
|
||||
// TODO rename wire map
|
||||
}
|
||||
}
|
||||
|
||||
// AN EXCEPTIONAL TERM: tilenum 0 is always redirected to Air tile, even if the tilenum for actual Air tile is not zero
|
||||
tileNumberToNameMap[0] = Block.AIR
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,12 +219,41 @@ open class GameWorld : Disposable {
|
||||
|
||||
fun coerceXY(x: Int, y: Int) = (x fmod width) to (y.coerceIn(0, height - 1))
|
||||
|
||||
fun getTileFromWall(rawX: Int, rawY: Int): Int {
|
||||
/**
|
||||
* @return ItemID, WITHOUT wall tag
|
||||
*/
|
||||
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)
|
||||
|
||||
try {
|
||||
return tileNumberToNameMap[layerTerrain.unsafeGetTile(x, y)]!!
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
System.err.println("NPE for tilenum ${layerTerrain.unsafeGetTile(x, y)}")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Int
|
||||
*/
|
||||
fun getTileNumFromWall(rawX: Int, rawY: Int): Int {
|
||||
val (x, y) = coerceXY(rawX, rawY)
|
||||
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)
|
||||
return layerTerrain.unsafeGetTile(x, y)
|
||||
}
|
||||
@@ -191,17 +267,18 @@ open class GameWorld : Disposable {
|
||||
* *
|
||||
* @param y
|
||||
* *
|
||||
* @param tilenum Item id of the wall block. Less-than-4096-value is permitted.
|
||||
* @param itemID Tile as in ItemID, with tag removed!
|
||||
*/
|
||||
fun setTileWall(x: Int, y: Int, tilenum: Int) {
|
||||
fun setTileWall(x: Int, y: Int, itemID: ItemID, bypassEvent: Boolean) {
|
||||
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)
|
||||
layerWall.unsafeSetTile(x, y, tilenum)
|
||||
wallDamages.remove(LandUtil.getBlockAddr(this, x, y))
|
||||
|
||||
Terrarum.ingame?.queueWallChangedEvent(oldWall, tilenum, LandUtil.getBlockAddr(this, x, y))
|
||||
if (!bypassEvent)
|
||||
Terrarum.ingame?.queueWallChangedEvent(oldWall, itemID, LandUtil.getBlockAddr(this, x, y))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,23 +290,25 @@ open class GameWorld : Disposable {
|
||||
* *
|
||||
* @param y
|
||||
* *
|
||||
* @param tilenum Item id of the terrain block, <4096
|
||||
* @param itemID Tile as in ItemID, with tag removed!
|
||||
*/
|
||||
fun setTileTerrain(x: Int, y: Int, tilenum: Int) {
|
||||
fun setTileTerrain(x: Int, y: Int, itemID: ItemID, bypassEvent: Boolean) {
|
||||
val (x, y) = coerceXY(x, y)
|
||||
val tilenum = tileNameToNumberMap[itemID]!!
|
||||
|
||||
val oldTerrain = getTileFromTerrain(x, y)
|
||||
layerTerrain.unsafeSetTile(x, y, tilenum)
|
||||
val blockAddr = LandUtil.getBlockAddr(this, x, y)
|
||||
terrainDamages.remove(blockAddr)
|
||||
|
||||
if (BlockCodex[tilenum].isSolid) {
|
||||
if (BlockCodex[itemID].isSolid) {
|
||||
fluidFills.remove(blockAddr)
|
||||
fluidTypes.remove(blockAddr)
|
||||
}
|
||||
// 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))
|
||||
if (!bypassEvent)
|
||||
Terrarum.ingame?.queueTerrainChangedEvent(oldTerrain, itemID, LandUtil.getBlockAddr(this, x, y))
|
||||
}
|
||||
|
||||
/*fun setTileWire(x: Int, y: Int, tile: Byte) {
|
||||
@@ -241,8 +320,9 @@ open class GameWorld : Disposable {
|
||||
Terrarum.ingame?.queueWireChangedEvent(oldWire, tile.toUint(), LandUtil.getBlockAddr(this, x, y))
|
||||
}*/
|
||||
|
||||
fun getWiringBlocks(x: Int, y: Int): Int {
|
||||
return wiringBlocks.getOrDefault(LandUtil.getBlockAddr(this, x, y), 0)
|
||||
fun getWiringBlocks(x: Int, y: Int): ItemID {
|
||||
return Block.AIR // TODO
|
||||
//return wiringBlocks.getOrDefault(LandUtil.getBlockAddr(this, x, y), Block.AIR)
|
||||
}
|
||||
|
||||
fun getAllConduitsFrom(x: Int, y: Int): SortedArrayList<WiringNode>? {
|
||||
@@ -258,7 +338,9 @@ open class GameWorld : Disposable {
|
||||
}
|
||||
|
||||
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
|
||||
// if there's no duplicate...
|
||||
@@ -270,10 +352,10 @@ open class GameWorld : Disposable {
|
||||
}
|
||||
else {
|
||||
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) {
|
||||
return getTileFromTerrain(x, y)
|
||||
}
|
||||
@@ -287,8 +369,8 @@ open class GameWorld : Disposable {
|
||||
throw IllegalArgumentException("illegal mode input: " + mode.toString())
|
||||
}
|
||||
|
||||
fun terrainIterator(): Iterator<Int> {
|
||||
return object : Iterator<Int> {
|
||||
fun terrainIterator(): Iterator<ItemID> {
|
||||
return object : Iterator<ItemID> {
|
||||
|
||||
private var iteratorCount = 0
|
||||
|
||||
@@ -296,7 +378,7 @@ open class GameWorld : Disposable {
|
||||
return iteratorCount < width * height
|
||||
}
|
||||
|
||||
override fun next(): Int {
|
||||
override fun next(): ItemID {
|
||||
val y = iteratorCount / width
|
||||
val x = iteratorCount % width
|
||||
// advance counter
|
||||
@@ -308,15 +390,15 @@ open class GameWorld : Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
fun wallIterator(): Iterator<Int> {
|
||||
return object : Iterator<Int> {
|
||||
fun wallIterator(): Iterator<ItemID> {
|
||||
return object : Iterator<ItemID> {
|
||||
|
||||
private var iteratorCount = 0
|
||||
|
||||
override fun hasNext(): Boolean =
|
||||
iteratorCount < width * height
|
||||
|
||||
override fun next(): Int {
|
||||
override fun next(): ItemID {
|
||||
val y = iteratorCount / width
|
||||
val x = iteratorCount % width
|
||||
// advance counter
|
||||
@@ -351,7 +433,7 @@ open class GameWorld : Disposable {
|
||||
|
||||
// remove tile from the world
|
||||
if (terrainDamages[addr] ?: 0f >= BlockCodex[getTileFromTerrain(x, y)].strength) {
|
||||
setTileTerrain(x, y, 0)
|
||||
setTileTerrain(x, y, Block.AIR, false)
|
||||
terrainDamages.remove(addr)
|
||||
return true
|
||||
}
|
||||
@@ -380,7 +462,7 @@ open class GameWorld : Disposable {
|
||||
|
||||
// remove tile from the world
|
||||
if (wallDamages[addr]!! >= BlockCodex[getTileFromWall(x, y)].strength) {
|
||||
setTileWall(x, y, 0)
|
||||
setTileWall(x, y, Block.AIR, false)
|
||||
wallDamages.remove(addr)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@ import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.AppLoader.printdbg
|
||||
import net.torvald.terrarum.CommonResourcePool
|
||||
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.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.BlockProp
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
import net.torvald.terrarum.gameitem.GameItem
|
||||
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.gameactors.CanBeAnItem
|
||||
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.*
|
||||
|
||||
/**
|
||||
@@ -24,219 +30,19 @@ object ItemCodex {
|
||||
* <ItemID or RefID for Actor, TheItem>
|
||||
* 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 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
|
||||
|
||||
private val itemImagePlaceholder: TextureRegion
|
||||
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 {
|
||||
//val ingame = Terrarum.ingame!! as Ingame // WARNING you can't put this here, ExceptionInInitializerError
|
||||
|
||||
|
||||
/*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
|
||||
/*itemCodex[ITEM_STATIC.first] = object : GameItem() {
|
||||
override val originalID = ITEM_STATIC.first
|
||||
override var dynamicID = originalID
|
||||
override val isUnique = false
|
||||
override val originalName = ""
|
||||
override var baseMass = 10.0
|
||||
override var baseToolSize: Double? = 10.0
|
||||
override var stackable = true
|
||||
override var maxDurability = 147//606
|
||||
override var durability = maxDurability.toFloat()
|
||||
override var equipPosition = EquipPosition.HAND_GRIP
|
||||
override var inventoryCategory = Category.TOOL
|
||||
override val isDynamic = true
|
||||
override val material = Material(0,0,0,0,0,0,0,0,1,0.0)
|
||||
|
||||
init {
|
||||
itemProperties[IVKey.ITEMTYPE] = IVKey.ItemType.PICK
|
||||
name = "Stone pickaxe"
|
||||
}
|
||||
|
||||
override fun startPrimaryUse(delta: Float): Boolean {
|
||||
val mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
|
||||
val actorvalue = ingame.actorNowPlaying.actorValue
|
||||
|
||||
|
||||
using = true
|
||||
|
||||
// linear search filter (check for intersection with tilewise mouse point and tilewise hitbox)
|
||||
// return false if hitting actors
|
||||
ingame.actorContainerActive.forEach {
|
||||
if (it is ActorWBMovable && it.hIntTilewiseHitbox.intersects(mousePoint))
|
||||
return false
|
||||
}
|
||||
|
||||
// return false if there's no tile
|
||||
if (Block.AIR == ingame.world.getTileFromTerrain(Terrarum.mouseTileX, Terrarum.mouseTileY))
|
||||
return false
|
||||
|
||||
|
||||
// filter passed, do the job
|
||||
val swingDmgToFrameDmg = delta.toDouble() / actorvalue.getAsDouble(AVKey.ACTION_INTERVAL)!!
|
||||
|
||||
ingame.world.inflictTerrainDamage(
|
||||
Terrarum.mouseTileX,
|
||||
Terrarum.mouseTileY,
|
||||
Calculate.pickaxePower(ingame.actorNowPlaying, material) * swingDmgToFrameDmg
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun endPrimaryUse(delta: Float): Boolean {
|
||||
using = false
|
||||
// reset action timer to zero
|
||||
ingame.actorNowPlaying.actorValue[AVKey.__ACTION_TIMER] = 0.0
|
||||
return true
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
// test water bucket
|
||||
itemCodex[9000] = object : GameItem(9000) {
|
||||
|
||||
override val isUnique: Boolean = true
|
||||
override val originalName: String = "Infinite Water Bucket"
|
||||
|
||||
override var baseMass: Double = 1000.0
|
||||
override var baseToolSize: Double? = null
|
||||
|
||||
override var inventoryCategory: String = "tool"
|
||||
override var stackable: Boolean = false
|
||||
|
||||
override val isDynamic: Boolean = false
|
||||
override val material: Material = Material()
|
||||
|
||||
init {
|
||||
equipPosition = EquipPosition.HAND_GRIP
|
||||
}
|
||||
|
||||
override fun startPrimaryUse(delta: Float): Boolean {
|
||||
val ingame = Terrarum.ingame!! as TerrarumIngame // must be in here
|
||||
ingame.world.setFluid(Terrarum.mouseTileX, Terrarum.mouseTileY, Fluid.WATER, 4f)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// test lava bucket
|
||||
itemCodex[9001] = object : GameItem(9001) {
|
||||
|
||||
override val isUnique: Boolean = true
|
||||
override val originalName: String = "Infinite Lava Bucket"
|
||||
|
||||
override var baseMass: Double = 1000.0
|
||||
override var baseToolSize: Double? = null
|
||||
|
||||
override var inventoryCategory: String = "tool"
|
||||
override var stackable: Boolean = false
|
||||
|
||||
override val isDynamic: Boolean = false
|
||||
override val material: Material = Material()
|
||||
|
||||
init {
|
||||
equipPosition = EquipPosition.HAND_GRIP
|
||||
}
|
||||
|
||||
override fun startPrimaryUse(delta: Float): Boolean {
|
||||
val ingame = Terrarum.ingame!! as TerrarumIngame // must be in here
|
||||
ingame.world.setFluid(Terrarum.mouseTileX, Terrarum.mouseTileY, Fluid.LAVA, 4f)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// read from save (if applicable) and fill dynamicItemDescription
|
||||
|
||||
|
||||
|
||||
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) {
|
||||
printdbg(this, "Registering new dynamic item $dynamicID (from ${item.originalID})")
|
||||
}
|
||||
@@ -251,18 +57,17 @@ object ItemCodex {
|
||||
operator fun get(code: ItemID?): GameItem? {
|
||||
if (code == null) return null
|
||||
|
||||
if (code <= ITEM_STATIC.endInclusive) // generic item
|
||||
return itemCodex[code]!!.clone() // from CSV
|
||||
else if (code <= ITEM_DYNAMIC.endInclusive) {
|
||||
if (code.startsWith(PREFIX_DYNAMICITEM))
|
||||
return dynamicItemDescription[code]!!
|
||||
}
|
||||
else {
|
||||
val a = (Terrarum.ingame!! as TerrarumIngame).getActorByID(code) // actor item
|
||||
else if (code.startsWith(PREFIX_ACTORITEM)) {
|
||||
val a = (Terrarum.ingame!! as TerrarumIngame).getActorByID(code.substring(6).toInt()) // actor item
|
||||
if (a is CanBeAnItem) return a.itemData
|
||||
|
||||
return null
|
||||
//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]!!
|
||||
@@ -270,6 +75,10 @@ object ItemCodex {
|
||||
/**
|
||||
* Mainly used by GameItemLoader
|
||||
*/
|
||||
fun set(modname: String, code: Int, item: GameItem) {
|
||||
itemCodex["$modname:$code"] = item
|
||||
}
|
||||
|
||||
operator fun set(code: ItemID, item: GameItem) {
|
||||
itemCodex[code] = item
|
||||
}
|
||||
@@ -280,31 +89,35 @@ object ItemCodex {
|
||||
return getItemImage(item.originalID)
|
||||
}
|
||||
|
||||
fun getItemImage(itemOriginalID: Int): TextureRegion {
|
||||
fun getItemImage(itemID: ItemID?): TextureRegion? {
|
||||
if (itemID == null) return null
|
||||
|
||||
// dynamic item
|
||||
if (itemOriginalID in ITEM_DYNAMIC) {
|
||||
return getItemImage(dynamicToStaticID(itemOriginalID))
|
||||
if (itemID.startsWith(PREFIX_DYNAMICITEM)) {
|
||||
return getItemImage(dynamicToStaticID(itemID))
|
||||
}
|
||||
// item
|
||||
else if (itemID.startsWith("item@")) {
|
||||
return itemCodex[itemID]?.itemImage
|
||||
}
|
||||
// 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
|
||||
else if (itemOriginalID in ITEM_TILES) {
|
||||
else {
|
||||
val itemSheetNumber = CreateTileAtlas.tileIDtoItemSheetNumber(itemID)
|
||||
return BlocksDrawer.tileItemTerrain.get(
|
||||
itemOriginalID % 16,
|
||||
itemOriginalID / 16
|
||||
itemSheetNumber % ITEM_ATLAS_TILES_X,
|
||||
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)
|
||||
|
||||
@@ -84,19 +84,19 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
println("[BuildingMaker] Generating builder world...")
|
||||
|
||||
for (y in 0 until gameWorld.height) {
|
||||
gameWorld.setTileWall(0, y, Block.ILLUMINATOR_RED)
|
||||
gameWorld.setTileWall(gameWorld.width - 1, y, Block.ILLUMINATOR_RED)
|
||||
gameWorld.setTileTerrain(0, y, Block.ILLUMINATOR_RED_OFF)
|
||||
gameWorld.setTileTerrain(gameWorld.width - 1, y, Block.ILLUMINATOR_RED_OFF)
|
||||
gameWorld.setTileWall(0, y, Block.ILLUMINATOR_RED, true)
|
||||
gameWorld.setTileWall(gameWorld.width - 1, y, Block.ILLUMINATOR_RED, true)
|
||||
gameWorld.setTileTerrain(0, y, Block.ILLUMINATOR_RED_OFF, true)
|
||||
gameWorld.setTileTerrain(gameWorld.width - 1, y, Block.ILLUMINATOR_RED_OFF, true)
|
||||
}
|
||||
|
||||
for (y in 150 until gameWorld.height) {
|
||||
for (x in 1 until gameWorld.width - 1) {
|
||||
// wall layer
|
||||
gameWorld.setTileWall(x, y, Block.DIRT)
|
||||
gameWorld.setTileWall(x, y, Block.DIRT, true)
|
||||
|
||||
// terrain layer
|
||||
gameWorld.setTileTerrain(x, y, if (y == 150) Block.GRASS else Block.DIRT)
|
||||
gameWorld.setTileTerrain(x, y, if (y == 150) Block.GRASS else Block.DIRT, true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,22 +424,22 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
when (currentPenMode) {
|
||||
// test paint terrain layer
|
||||
PENMODE_PENCIL -> {
|
||||
if (palSelection < BlockCodex.MAX_TERRAIN_TILES)
|
||||
world.setTileTerrain(x, y, palSelection)
|
||||
else if (palSelection < 2 * BlockCodex.MAX_TERRAIN_TILES)
|
||||
world.setTileWall(x, y, palSelection - BlockCodex.MAX_TERRAIN_TILES)
|
||||
if (palSelection.startsWith("wall@"))
|
||||
world.setTileWall(x, y, palSelection.substring(5), true)
|
||||
else
|
||||
world.setTileTerrain(x, y, palSelection, true)
|
||||
}
|
||||
PENMODE_PENCIL_ERASE -> {
|
||||
if (currentPenTarget and PENTARGET_WALL != 0)
|
||||
world.setTileWall(x, y, Block.AIR)
|
||||
world.setTileWall(x, y, Block.AIR, true)
|
||||
else
|
||||
world.setTileTerrain(x, y, Block.AIR)
|
||||
world.setTileTerrain(x, y, Block.AIR, true)
|
||||
}
|
||||
PENMODE_EYEDROPPER -> {
|
||||
uiPaletteSelector.fore = if (world.getTileFromTerrain(x, y) == Block.AIR)
|
||||
world.getTileFromWall(x, y)!! + BlockCodex.MAX_TERRAIN_TILES
|
||||
"wall@"+world.getTileFromWall(x, y)
|
||||
else
|
||||
world.getTileFromTerrain(x, y)!!
|
||||
world.getTileFromTerrain(x, y)
|
||||
}
|
||||
PENMODE_MARQUEE -> {
|
||||
addBlockMarker(x, y)
|
||||
@@ -455,7 +455,7 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
return selection.last() - selection.first()
|
||||
}
|
||||
|
||||
private fun serialiseSelection(outfile: File) {
|
||||
/*private fun serialiseSelection(outfile: File) {
|
||||
// save format: sparse list encoded in following binary format:
|
||||
/*
|
||||
Header: TEaT0bLD -- magic: Terrarum Attachment
|
||||
@@ -498,7 +498,7 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
fos.write(FILE_FOOTER)
|
||||
fos.close()
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
class BuildingMakerController(val screen: BuildingMaker) : InputAdapter() {
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.torvald.terrarum.CommonResourcePool
|
||||
import net.torvald.terrarum.ModMgr
|
||||
import net.torvald.terrarum.ModuleEntryPoint
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.BlockProp
|
||||
import net.torvald.terrarum.gameitem.GameItem
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.itemproperties.MaterialCodex
|
||||
@@ -52,35 +53,14 @@ class EntryPoint : ModuleEntryPoint() {
|
||||
|
||||
// blocks.csvs are loaded by ModMgr beforehand
|
||||
// block items (blocks and walls are the same thing basically)
|
||||
for (i in ItemCodex.ITEM_TILES + ItemCodex.ITEM_WALLS) {
|
||||
val blockProp = BlockCodex.getOrNull(i % ItemCodex.ITEM_WALLS.first)
|
||||
for (tile in BlockCodex.getAll()) {
|
||||
ItemCodex[tile.id] = makeNewItemObj(tile, false)
|
||||
|
||||
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)
|
||||
if (IS_DEVELOPMENT_BUILD) print(tile.id+" ")
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
if (BlockCodex[tile.id].isWallable) {
|
||||
ItemCodex["wall@" + tile.id] = makeNewItemObj(tile, true)
|
||||
if (IS_DEVELOPMENT_BUILD) print("wall@" + tile.id + " ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +69,32 @@ class EntryPoint : ModuleEntryPoint() {
|
||||
println("[Basegame.EntryPoint] Welcome back!")
|
||||
}
|
||||
|
||||
private fun makeNewItemObj(tile: BlockProp, isWall: Boolean) = object : GameItem(
|
||||
if (isWall) "wall@"+tile.id else 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
|
||||
}
|
||||
|
||||
override fun startPrimaryUse(delta: Float): Boolean {
|
||||
return BlockBase.blockStartPrimaryUse(this, dynamicID, delta)
|
||||
}
|
||||
|
||||
override fun effectWhenEquipped(delta: Float) {
|
||||
BlockBase.blockEffectWhenEquipped(delta)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun dispose() {
|
||||
WatchFont.dispose()
|
||||
}
|
||||
|
||||
@@ -399,6 +399,8 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
||||
}// END enter
|
||||
|
||||
override fun worldPrimaryClickStart(delta: Float) {
|
||||
//println("[Ingame] worldPrimaryClickStart $delta")
|
||||
|
||||
// bring up the UIs of the fixtures (e.g. crafting menu from a crafting table)
|
||||
var uiOpened = false
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.AppLoader.printdbg
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.BlockProp
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.util.CircularArray
|
||||
import kotlin.math.roundToInt
|
||||
@@ -93,7 +95,9 @@ class WorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidt
|
||||
val wx = (world.width.toFloat() / previewWidth * x).roundToInt()
|
||||
val wy = (world.height.toFloat() / previewHeight * y).roundToInt()
|
||||
|
||||
val outCol = if (world.getTileFromTerrain(wx, wy) > 15) COL_TERR else if (world.getTileFromWall(wx, wy) > 15) COL_WALLED else COL_AIR
|
||||
val outCol = if (BlockCodex[world.getTileFromTerrain(wx, wy)].isSolid) COL_TERR
|
||||
else if (BlockCodex[world.getTileFromWall(wx, wy)].isSolid) COL_WALLED
|
||||
else COL_AIR
|
||||
|
||||
previewPixmap.setColor(outCol)
|
||||
previewPixmap.drawPixel(x, previewHeight - 1 - y) // this flips Y
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum.modulebasegame.console
|
||||
|
||||
import net.torvald.gdx.graphics.Cvec
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
@@ -7,6 +8,7 @@ import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.console.EchoError
|
||||
import net.torvald.terrarum.utils.RasterWriter
|
||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||
import net.torvald.terrarum.worlddrawer.toRGBA
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
@@ -31,7 +33,8 @@ internal object ExportMap : ConsoleCommand {
|
||||
var mapDataPointer = 0
|
||||
|
||||
for (tile in world.terrainIterator()) {
|
||||
val colArray = CreateTileAtlas.terrainTileColourMap.getRaw(tile % 16, tile / 16).toByteArray()
|
||||
val tileNumber = CreateTileAtlas.tileIDtoItemSheetNumber(tile)
|
||||
val colArray = CreateTileAtlas.terrainTileColourMap.get(tileNumber)!!.toByteArray()
|
||||
|
||||
for (i in 0..2) {
|
||||
mapData[mapDataPointer + i] = colArray[i]
|
||||
@@ -71,11 +74,13 @@ internal object ExportMap : ConsoleCommand {
|
||||
/***
|
||||
* R-G-B-A order for RGBA input value
|
||||
*/
|
||||
private fun Cvec.toByteArray() = this.toRGBA().toByteArray()
|
||||
|
||||
private fun Int.toByteArray() = byteArrayOf(
|
||||
this.shr(24).and(0xff).toByte(),
|
||||
this.shr(16).and(0xff).toByte(),
|
||||
this.shr(8).and(0xff).toByte(),
|
||||
this.and(0xff).toByte()
|
||||
this.ushr(24).and(255).toByte(),
|
||||
this.ushr(16).and(255).toByte(),
|
||||
this.ushr(8).and(255).toByte(),
|
||||
this.and(255).toByte()
|
||||
)
|
||||
|
||||
override fun printUsage() {
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.console.EchoError
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
@@ -22,10 +23,10 @@ internal object Inventory : ConsoleCommand {
|
||||
else {
|
||||
when (args[1]) {
|
||||
"list" -> listInventory()
|
||||
"add" -> if (args.size > 3) addItem(args[2].toInt(), args[3].toInt())
|
||||
else addItem(args[2].toInt())
|
||||
"add" -> if (args.size > 3) addItem(args[2], args[3].toInt())
|
||||
else addItem(args[2])
|
||||
"target" -> setTarget(args[2].toInt())
|
||||
"equip" -> equipItem(args[2].toInt())
|
||||
"equip" -> equipItem(args[2])
|
||||
else -> printUsage()
|
||||
}
|
||||
}
|
||||
@@ -57,13 +58,13 @@ internal object Inventory : ConsoleCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private fun addItem(refId: Int, amount: Int = 1) {
|
||||
private fun addItem(refId: ItemID, amount: Int = 1) {
|
||||
if (target != null) {
|
||||
target!!.addItem(ItemCodex[refId]!!, amount)
|
||||
}
|
||||
}
|
||||
|
||||
private fun equipItem(refId: Int) {
|
||||
private fun equipItem(refId: ItemID) {
|
||||
if (target != null) {
|
||||
val item = ItemCodex[refId]!!
|
||||
target!!.equipItem(item)
|
||||
|
||||
@@ -168,7 +168,7 @@ open class ActorHumanoid(
|
||||
|
||||
private var jumpJustPressedLatched = false
|
||||
|
||||
@Transient private val nullItem = object : GameItem(0) {
|
||||
@Transient private val nullItem = object : GameItem("item@basegame:0") {
|
||||
override val isUnique: Boolean = false
|
||||
override var baseMass: Double = 0.0
|
||||
override var baseToolSize: Double? = null
|
||||
|
||||
@@ -7,12 +7,11 @@ import net.torvald.terrarum.gameactors.AVKey
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameitem.GameItem
|
||||
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.lock
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIQuickslotBar
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
@@ -41,23 +40,20 @@ class ActorInventory(@Transient val actor: Pocketed, var maxCapacity: Int, var c
|
||||
val itemList = ArrayList<InventoryPair>()
|
||||
val quickSlot = Array<ItemID?>(UIQuickslotBar.SLOT_COUNT) { null } // 0: Slot 1, 9: Slot 10
|
||||
|
||||
var wallet = 0 // unified currency for whole civs; Dwarf Fortress approach seems too complicated
|
||||
var wallet = BigInteger("0") // unified currency for whole civs; Dwarf Fortress approach seems too complicated
|
||||
|
||||
init {
|
||||
}
|
||||
|
||||
fun add(itemID: ItemID, count: Int = 1) = add(ItemCodex[itemID]!!, count)
|
||||
fun add(itemID: ItemID, count: Int = 1) {
|
||||
if (ItemCodex[itemID] == null)
|
||||
throw NullPointerException("Item not found: $itemID")
|
||||
else
|
||||
add(ItemCodex[itemID]!!, count)
|
||||
}
|
||||
fun add(item: GameItem, count: Int = 1) {
|
||||
|
||||
println("[ActorInventory] add $item, $count")
|
||||
|
||||
|
||||
// not wall-able walls
|
||||
if (item.inventoryCategory == GameItem.Category.WALL &&
|
||||
!BlockCodex[item.dynamicID - ITEM_WALLS.start].isWallable) {
|
||||
throw IllegalArgumentException("Wall ID ${item.dynamicID - ITEM_WALLS.start} is not wall-able.")
|
||||
}
|
||||
|
||||
println("[ActorInventory] add-by-elem $item, $count")
|
||||
|
||||
// other invalid values
|
||||
if (count == 0)
|
||||
@@ -65,12 +61,12 @@ class ActorInventory(@Transient val actor: Pocketed, var maxCapacity: Int, var c
|
||||
if (count < 0)
|
||||
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.")
|
||||
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.")
|
||||
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.")
|
||||
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")
|
||||
|
||||
|
||||
|
||||
@@ -14,15 +14,15 @@ import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
open class DroppedItem(private val item: GameItem) : ActorWithBody(RenderOrder.MIDTOP, PhysProperties.PHYSICS_OBJECT) {
|
||||
|
||||
init {
|
||||
if (item.dynamicID >= ItemCodex.ACTORID_MIN)
|
||||
if (item.dynamicID.startsWith("actor@"))
|
||||
throw RuntimeException("Attempted to create DroppedItem actor of a real actor; the real actor must be dropped instead.")
|
||||
|
||||
isVisible = true
|
||||
|
||||
avBaseMass = if (item.dynamicID < BlockCodex.MAX_TERRAIN_TILES)
|
||||
BlockCodex[item.dynamicID].density / 1000.0
|
||||
else
|
||||
avBaseMass = if (item.dynamicID.startsWith("item@"))
|
||||
ItemCodex[item.dynamicID]!!.mass
|
||||
else
|
||||
BlockCodex[item.dynamicID].density / 1000.0 // block and wall
|
||||
|
||||
actorValue[AVKey.SCALE] = ItemCodex[item.dynamicID]!!.scale
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.gameactors.PhysProperties
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
|
||||
@@ -77,10 +78,10 @@ open class FixtureBase(
|
||||
// if the collision type is allow_move_down, only the top surface tile should be "the platform"
|
||||
// lower part must not have such property (think of the table!)
|
||||
// TODO does this ACTUALLY work ?!
|
||||
world.setTileTerrain(x, y, if (y == posY) BlockBox.ALLOW_MOVE_DOWN else BlockBox.NO_COLLISION)
|
||||
world.setTileTerrain(x, y, if (y == posY) BlockBox.ALLOW_MOVE_DOWN else BlockBox.NO_COLLISION, false)
|
||||
}
|
||||
else
|
||||
world.setTileTerrain(x, y, blockBox.collisionType)
|
||||
world.setTileTerrain(x, y, blockBox.collisionType, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +116,7 @@ open class FixtureBase(
|
||||
// remove filler block
|
||||
for (x in posX until posX + blockBox.width) {
|
||||
for (y in posY until posY + blockBox.height) {
|
||||
world.setTileTerrain(x, y, Block.AIR)
|
||||
world.setTileTerrain(x, y, Block.AIR, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ open class FixtureBase(
|
||||
for (x in posX until posX + blockBox.width) {
|
||||
for (y in posY until posY + blockBox.height) {
|
||||
if (world.getTileFromTerrain(x, y) == blockBox.collisionType) {
|
||||
world.setTileTerrain(x, y, Block.AIR)
|
||||
world.setTileTerrain(x, y, Block.AIR, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,7 +202,7 @@ inline class BlockBoxProps(val flags: Int) {
|
||||
* @param width Width of the block box, tile-wise
|
||||
* @param height Height of the block box, tile-wise
|
||||
*/
|
||||
data class BlockBox(val collisionType: Int, val width: Int, val height: Int) {
|
||||
data class BlockBox(val collisionType: ItemID, val width: Int, val height: Int) {
|
||||
|
||||
/*fun redefine(collisionType: Int, width: Int, height: Int) {
|
||||
redefine(collisionType)
|
||||
|
||||
@@ -27,7 +27,7 @@ open class HumanoidNPC(
|
||||
}
|
||||
|
||||
// we're having GameItem data so that this class could be somewhat universal
|
||||
override var itemData: GameItem = object : GameItem(referenceID) {//GameItem(referenceID ?: forceAssignRefID!!) {
|
||||
override var itemData: GameItem = object : GameItem("actor:"+referenceID) {//GameItem(referenceID ?: forceAssignRefID!!) {
|
||||
override val isUnique = true
|
||||
override var baseMass: Double
|
||||
get() = actorValue.getAsDouble(AVKey.BASEMASS)!!
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.torvald.terrarum.modulebasegame.gameactors
|
||||
|
||||
import net.torvald.terrarum.ModMgr
|
||||
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.faction.FactionFactory
|
||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||
@@ -78,20 +77,22 @@ object PlayerBuilderSigrid {
|
||||
|
||||
CreateTileAtlas.tags.forEach { t, _ ->
|
||||
inventory.add(t, 9995)
|
||||
if (BlockCodex[t].isWallable) {
|
||||
inventory.add(t + MAX_TERRAIN_TILES, 9995)
|
||||
try {
|
||||
inventory.add("wall@"+t, 9995) // this code will try to add nonexisting wall items, do not get surprised with NPEs
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
System.err.println("[PlayerBuilder] $e")
|
||||
}
|
||||
}
|
||||
|
||||
// item ids are defined in <module>/items/itemid.csv
|
||||
|
||||
inventory.add(135168, 16) // copper pick
|
||||
inventory.add(135169) // iron pick
|
||||
inventory.add(135170) // steel pick
|
||||
inventory.add(135171, 9995) // wire piece
|
||||
inventory.add(135172, 385930603) // test tiki torch
|
||||
inventory.add(135173, 95) // crafting table
|
||||
//inventory.add(9000) // TEST water bucket
|
||||
//inventory.add(9001) // TEST lava bucket
|
||||
inventory.add("item@basegame:1", 16) // copper pick
|
||||
inventory.add("item@basegame:2") // iron pick
|
||||
inventory.add("item@basegame:3") // steel pick
|
||||
inventory.add("item@basegame:4", 9995) // wire piece
|
||||
inventory.add("item@basegame:5", 385930603) // test tiki torch
|
||||
inventory.add("item@basegame:6", 95) // crafting table
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,12 +77,12 @@ interface Pocketed {
|
||||
}
|
||||
fun equipped(itemID: ItemID) = equipped(ItemCodex[itemID]!!)
|
||||
|
||||
fun addItem(itemID: Int, count: Int = 1) = inventory.add(ItemCodex[itemID]!!, count)
|
||||
fun addItem(itemID: ItemID, count: Int = 1) = inventory.add(ItemCodex[itemID]!!, count)
|
||||
fun addItem(item: GameItem, count: Int = 1) = inventory.add(item, count)
|
||||
fun removeItem(itemID: Int, count: Int = 1) = inventory.remove(ItemCodex[itemID]!!, count)
|
||||
fun removeItem(itemID: ItemID, count: Int = 1) = inventory.remove(ItemCodex[itemID]!!, count)
|
||||
fun removeItem(item: GameItem, count: Int = 1) = inventory.remove(item, count)
|
||||
|
||||
fun hasItem(item: GameItem) = inventory.contains(item.dynamicID)
|
||||
fun hasItem(id: Int) = inventory.contains(id)
|
||||
fun hasItem(id: ItemID) = inventory.contains(id)
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import net.torvald.terrarum.Point2i
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.gameitem.GameItem
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
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
|
||||
* 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 mousePoint = Point2d(Terrarum.mouseTileX.toDouble(), Terrarum.mouseTileY.toDouble())
|
||||
val mouseTile = Point2i(Terrarum.mouseTileX, Terrarum.mouseTileY)
|
||||
@@ -45,24 +46,26 @@ object BlockBase {
|
||||
if (gameItem.inventoryCategory == GameItem.Category.BLOCK &&
|
||||
gameItem.dynamicID == ingame.world.getTileFromTerrain(mouseTile.x, mouseTile.y) ||
|
||||
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
|
||||
|
||||
// filter passed, do the job
|
||||
// FIXME this is only useful for Player
|
||||
if (itemID in ItemCodex.ITEM_TILES) {
|
||||
ingame.world.setTileTerrain(
|
||||
mouseTile.x,
|
||||
mouseTile.y,
|
||||
itemID
|
||||
)
|
||||
}
|
||||
else {
|
||||
if (itemID.startsWith("wall@")) {
|
||||
ingame.world.setTileWall(
|
||||
mouseTile.x,
|
||||
mouseTile.y,
|
||||
itemID
|
||||
itemID.substring(5),
|
||||
false
|
||||
)
|
||||
}
|
||||
else {
|
||||
ingame.world.setTileTerrain(
|
||||
mouseTile.x,
|
||||
mouseTile.y,
|
||||
itemID,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -74,7 +77,8 @@ object BlockBase {
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
// return false if the tile is already there
|
||||
@@ -93,7 +97,7 @@ object BlockBase {
|
||||
)
|
||||
)
|
||||
|
||||
return true
|
||||
return true*/
|
||||
}
|
||||
|
||||
fun wireEffectWhenEquipped(typebit: Int, delta: Float) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.FluidType
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
@@ -207,8 +208,8 @@ object WorldSimulator {
|
||||
// process the gradual falling of the selected "stack"
|
||||
if (!fallableStackProcessed && fallDownCounter != 0 && isFallable) {
|
||||
// replace blocks
|
||||
world.setTileTerrain(x, y, Block.AIR)
|
||||
world.setTileTerrain(x, y + fallDownCounter, currentTile)
|
||||
world.setTileTerrain(x, y, Block.AIR, true)
|
||||
world.setTileTerrain(x, y + fallDownCounter, currentTile, true)
|
||||
|
||||
fallableStackProcessed = true
|
||||
}
|
||||
@@ -416,7 +417,7 @@ object WorldSimulator {
|
||||
}
|
||||
|
||||
|
||||
fun Int.isFallable() = BlockCodex[this].maxSupport
|
||||
fun ItemID.isFallable() = BlockCodex[this].maxSupport
|
||||
|
||||
|
||||
private val actorMBRConverter = object : MBRConverter<ActorWithBody> {
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.blendNormal
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.fillRect
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.modulebasegame.BuildingMaker
|
||||
@@ -14,6 +15,7 @@ import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.ui.UIItemImageButton
|
||||
import net.torvald.terrarum.ui.UIItemTextButtonList
|
||||
import net.torvald.terrarum.ui.UIItemTextButtonList.Companion.DEFAULT_BACKGROUNDCOL
|
||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
@@ -37,19 +39,10 @@ class UIBuildingMakerBlockChooser(val parent: BuildingMaker): UICanvas() {
|
||||
override var height = HEIGHT
|
||||
override var openCloseTime = 0f
|
||||
|
||||
private val palette = Array<UIItemImageButton>(TILES_X * TILES_Y) {
|
||||
// initialise with terrain blocks
|
||||
UIItemImageButton(
|
||||
this, ItemCodex.getItemImage(it),
|
||||
initialX = MENUBAR_SIZE + (it % 16) * TILESREGION_SIZE,
|
||||
initialY = (it / 16) * TILESREGION_SIZE,
|
||||
highlightable = false,
|
||||
width = TILESREGION_SIZE,
|
||||
height = TILESREGION_SIZE,
|
||||
highlightCol = Color.WHITE,
|
||||
activeCol = Color.WHITE
|
||||
)
|
||||
}
|
||||
val palette = ArrayList<UIItemImageButton>()
|
||||
|
||||
// TODO scrolling of the palette, as the old method flat out won't work with The Flattening
|
||||
|
||||
private val tabs = UIItemTextButtonList(
|
||||
this, arrayOf("Terrain", "Wall", "Wire"),
|
||||
0, 0, textAreaWidth = MENUBAR_SIZE, width = MENUBAR_SIZE,
|
||||
@@ -62,12 +55,25 @@ class UIBuildingMakerBlockChooser(val parent: BuildingMaker): UICanvas() {
|
||||
)
|
||||
|
||||
init {
|
||||
palette.forEachIndexed { index, it ->
|
||||
uiItems.add(it)
|
||||
|
||||
it.clickOnceListener = { _, _, _ ->
|
||||
parent.setPencilColour(paletteScroll * 16 + index)
|
||||
BlockCodex.getAll().forEachIndexed { index, prop ->
|
||||
val paletteItem = UIItemImageButton(
|
||||
this, ItemCodex.getItemImage(prop.id)!!,
|
||||
initialX = MENUBAR_SIZE + (index % 16) * TILESREGION_SIZE,
|
||||
initialY = (index / 16) * TILESREGION_SIZE,
|
||||
highlightable = false,
|
||||
width = TILESREGION_SIZE,
|
||||
height = TILESREGION_SIZE,
|
||||
highlightCol = Color.WHITE,
|
||||
activeCol = Color.WHITE
|
||||
)
|
||||
|
||||
paletteItem.clickOnceListener = { _, _, _ ->
|
||||
parent.setPencilColour(prop.id)
|
||||
}
|
||||
|
||||
uiItems.add(paletteItem)
|
||||
palette.add(paletteItem)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,9 +125,7 @@ class UIBuildingMakerBlockChooser(val parent: BuildingMaker): UICanvas() {
|
||||
}
|
||||
|
||||
private fun rebuildPalette() {
|
||||
palette.forEachIndexed { index, it ->
|
||||
it.image = ItemCodex.getItemImage(paletteScroll * 16 + index)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||
|
||||
@@ -153,7 +153,7 @@ class UIBuildingMakerPenMenu(val parent: BuildingMaker): UICanvas() {
|
||||
|
||||
// draw blocks slot
|
||||
batch.color = blockCellCol
|
||||
val slotConfig = AppLoader.getConfigIntArray("buildingmakerfavs")
|
||||
val slotConfig = AppLoader.getConfigStringArray("buildingmakerfavs")
|
||||
for (i in 0 until PALETTE_SIZE) {
|
||||
val x = blockCellPos[i].x.roundToInt().toFloat()
|
||||
val y = blockCellPos[i].y.roundToInt().toFloat()
|
||||
|
||||
@@ -9,6 +9,7 @@ import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.blendNormal
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.fillRect
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.modulebasegame.BuildingMaker
|
||||
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory.CELLCOLOUR_BLACK
|
||||
@@ -31,8 +32,8 @@ class UIPaletteSelector(val parent: BuildingMaker) : UICanvas() {
|
||||
fun mouseOnTitleBar() =
|
||||
relativeMouseX in 0 until width && relativeMouseY in 0 until LINE_HEIGHT
|
||||
|
||||
var fore = Block.STONE_BRICKS
|
||||
var back = Block.GLASS_CRUDE
|
||||
var fore: ItemID = Block.STONE_BRICKS
|
||||
var back: ItemID = Block.GLASS_CRUDE
|
||||
|
||||
private val titleText = "Pal."
|
||||
|
||||
@@ -102,10 +103,9 @@ class UIPaletteSelector(val parent: BuildingMaker) : UICanvas() {
|
||||
}
|
||||
|
||||
fun swapForeAndBack() {
|
||||
// xor used, because why not?
|
||||
fore = fore xor back
|
||||
back = back xor fore
|
||||
fore = fore xor back
|
||||
val t = fore
|
||||
fore = back
|
||||
back = t
|
||||
}
|
||||
|
||||
override fun doOpening(delta: Float) {
|
||||
|
||||
@@ -86,17 +86,17 @@ class Biomegen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par
|
||||
when (control) {
|
||||
0 -> { // woodlands
|
||||
if (tileThis == Block.DIRT && nearbyTerr.any { it == Block.AIR } && nearbyWall.any { it == Block.AIR }) {
|
||||
world.setTileTerrain(x, y, Block.GRASS)
|
||||
world.setTileTerrain(x, y, Block.GRASS, true)
|
||||
}
|
||||
}
|
||||
1 -> { // shrublands
|
||||
if (tileThis == Block.DIRT && nearbyTerr.any { it == Block.AIR } && nearbyWall.any { it == Block.AIR }) {
|
||||
world.setTileTerrain(x, y, Block.GRASS)
|
||||
world.setTileTerrain(x, y, Block.GRASS, true)
|
||||
}
|
||||
}
|
||||
2, 3 -> { // plains
|
||||
if (tileThis == Block.DIRT && nearbyTerr.any { it == Block.AIR } && nearbyWall.any { it == Block.AIR }) {
|
||||
world.setTileTerrain(x, y, Block.GRASS)
|
||||
world.setTileTerrain(x, y, Block.GRASS, true)
|
||||
}
|
||||
}
|
||||
/*3 -> { // sands
|
||||
@@ -109,8 +109,8 @@ class Biomegen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par
|
||||
}*/
|
||||
4 -> { // rockylands
|
||||
if (tileThis == Block.DIRT) {
|
||||
world.setTileTerrain(x, y, Block.STONE)
|
||||
world.setTileWall(x, y, Block.STONE)
|
||||
world.setTileTerrain(x, y, Block.STONE, true)
|
||||
world.setTileWall(x, y, Block.STONE, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par
|
||||
(0 until world.width).sliceEvenly(genSlices).mapIndexed { i, xs ->
|
||||
ThreadExecutor.submit {
|
||||
val localJoise = getGenerator(seed, params as TerragenParams)
|
||||
val localLock = java.lang.Object() // in an attempt to fix the "premature exit" issue of a thread run
|
||||
synchronized(localLock) { // also see: https://stackoverflow.com/questions/28818494/threads-stopping-prematurely-for-certain-values
|
||||
//val localLock = java.lang.Object() // in an attempt to fix the "premature exit" issue of a thread run
|
||||
//synchronized(localLock) { // also see: https://stackoverflow.com/questions/28818494/threads-stopping-prematurely-for-certain-values
|
||||
for (x in xs) {
|
||||
for (y in 0 until world.height) {
|
||||
val sampleTheta = (x.toDouble() / world.width) * TWO_PI
|
||||
@@ -43,7 +43,7 @@ class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par
|
||||
draw(x, y, noise, world)
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,10 +69,10 @@ class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par
|
||||
val cave = if (noiseValue[1] < 0.5) 0 else 1
|
||||
|
||||
val wallBlock = groundDepthBlock[terr]
|
||||
val terrBlock = wallBlock * cave // AIR is always zero, this is the standard
|
||||
val terrBlock = if (cave == 0) Block.AIR else wallBlock //wallBlock * cave // AIR is always zero, this is the standard
|
||||
|
||||
world.setTileTerrain(x, y, terrBlock)
|
||||
world.setTileWall(x, y, wallBlock)
|
||||
world.setTileTerrain(x, y, terrBlock, true)
|
||||
world.setTileWall(x, y, wallBlock, true)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.torvald.terrarum.serialise
|
||||
|
||||
import com.badlogic.gdx.utils.compression.Lzma
|
||||
import net.torvald.terrarum.AppLoader.printdbg
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.BlockAddress
|
||||
import net.torvald.terrarum.gameworld.BlockLayer
|
||||
import net.torvald.terrarum.gameworld.FluidType
|
||||
@@ -151,6 +152,7 @@ internal object ReadLayerDataLzma {
|
||||
val wallDamages = HashMap<BlockAddress, Float>()
|
||||
val fluidTypes = HashMap<BlockAddress, FluidType>()
|
||||
val fluidFills = HashMap<BlockAddress, Float>()
|
||||
val tileNumToName = HashMap<Int, ItemID>()
|
||||
|
||||
// parse terrain damages
|
||||
for (c in payloadBytes["TdMG"]!!.indices step 10) {
|
||||
@@ -176,6 +178,8 @@ internal object ReadLayerDataLzma {
|
||||
|
||||
// TODO parse fluid(Types|Fills)
|
||||
|
||||
// TODO parse tileNumToName
|
||||
|
||||
|
||||
return ReadLayerDataZip.LayerData(
|
||||
BlockLayer(width, height, payloadBytes["WALL"]!!),
|
||||
@@ -183,7 +187,7 @@ internal object ReadLayerDataLzma {
|
||||
|
||||
spawnPoint.first, spawnPoint.second,
|
||||
|
||||
wallDamages, terrainDamages, fluidTypes, fluidFills
|
||||
wallDamages, terrainDamages, fluidTypes, fluidFills, tileNumToName
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.torvald.terrarum.serialise
|
||||
|
||||
import net.torvald.terrarum.AppLoader.printdbg
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.BlockAddress
|
||||
import net.torvald.terrarum.gameworld.BlockLayer
|
||||
import net.torvald.terrarum.gameworld.FluidType
|
||||
@@ -152,6 +153,7 @@ internal object ReadLayerDataZip {
|
||||
val wallDamages = HashMap<BlockAddress, Float>()
|
||||
val fluidTypes = HashMap<BlockAddress, FluidType>()
|
||||
val fluidFills = HashMap<BlockAddress, Float>()
|
||||
val tileNumberToNameMap = HashMap<Int, ItemID>()
|
||||
|
||||
// parse terrain damages
|
||||
for (c in payloadBytes["TdMG"]!!.indices step 10) {
|
||||
@@ -184,7 +186,7 @@ internal object ReadLayerDataZip {
|
||||
|
||||
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 terrainDamages: HashMap<BlockAddress, Float>,
|
||||
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 {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.torvald.terrarum.serialise
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.AppLoader
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gameactors.AVKey
|
||||
@@ -9,10 +10,31 @@ import net.torvald.terrarum.gameitem.GameItem
|
||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.*
|
||||
import net.torvald.terrarum.utils.JsonWriter.getJsonBuilder
|
||||
import net.torvald.util.SortedArrayList
|
||||
import java.io.File
|
||||
import java.nio.charset.Charset
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
internal class RNGPool() {
|
||||
private val RNG = HQRNG()
|
||||
private val used = SortedArrayList<Int>()
|
||||
|
||||
init {
|
||||
for (i in 0 until 32767) {
|
||||
used.add(i)
|
||||
}
|
||||
}
|
||||
|
||||
fun next(): Int {
|
||||
var n = RNG.nextLong().ushr(32).toInt()
|
||||
while (used.contains(n)) {
|
||||
n = RNG.nextLong().ushr(32).toInt()
|
||||
}
|
||||
used.add(n)
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2018-10-03.
|
||||
*/
|
||||
@@ -20,6 +42,8 @@ object SavegameWriter {
|
||||
|
||||
// TODO create temporary files (worldinfo), create JSON files on RAM, pack those into TEVd as per Savegame container.txt
|
||||
|
||||
private val rngPool = RNGPool()
|
||||
|
||||
private val charset = Charset.forName("UTF-8")
|
||||
|
||||
private lateinit var playerName: String
|
||||
@@ -99,16 +123,16 @@ object SavegameWriter {
|
||||
// actors
|
||||
ingame.actorContainerActive.forEach {
|
||||
VDUtil.registerFile(disk, DiskEntry(
|
||||
it.referenceID!!, ROOT,
|
||||
it.referenceID!!.toString(16).toUpperCase().toByteArray(charset),
|
||||
rngPool.next(), ROOT,
|
||||
it.referenceID.toString(16).toUpperCase().toByteArray(charset),
|
||||
creationDate, creationDate,
|
||||
EntryFile(serialiseActor(it))
|
||||
))
|
||||
}
|
||||
ingame.actorContainerInactive.forEach {
|
||||
VDUtil.registerFile(disk, DiskEntry(
|
||||
it.referenceID!!, ROOT,
|
||||
it.referenceID!!.toString(16).toUpperCase().toByteArray(charset),
|
||||
rngPool.next(), ROOT,
|
||||
it.referenceID.toString(16).toUpperCase().toByteArray(charset),
|
||||
creationDate, creationDate,
|
||||
EntryFile(serialiseActor(it))
|
||||
))
|
||||
@@ -117,8 +141,8 @@ object SavegameWriter {
|
||||
// items
|
||||
ItemCodex.dynamicItemDescription.forEach { dynamicID, item ->
|
||||
VDUtil.registerFile(disk, DiskEntry(
|
||||
item.dynamicID, ROOT,
|
||||
dynamicID.toString(16).toUpperCase().toByteArray(charset),
|
||||
rngPool.next(), ROOT,
|
||||
dynamicID.toByteArray(charset),
|
||||
creationDate, creationDate,
|
||||
EntryFile(serialiseItem(item))
|
||||
))
|
||||
|
||||
@@ -52,8 +52,8 @@ object WriteWorldInfo {
|
||||
val infile = infileList[filenum - 1]
|
||||
|
||||
infile.forEach {
|
||||
outputStream.write("## from file: ${it.nameWithoutExtension()} ##############################\n".toByteArray())
|
||||
val readBytes = it.readBytes()
|
||||
outputStream.write("## from file: ${it.second.nameWithoutExtension()} ##############################\n".toByteArray())
|
||||
val readBytes = it.second.readBytes()
|
||||
outputStream.write(readBytes)
|
||||
outputStream.write("\n".toByteArray())
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
val wireNum = ingame!!.world.getWiringBlocks(mouseTileX, mouseTileY)
|
||||
val fluid = ingame!!.world.getFluid(mouseTileX, mouseTileY)
|
||||
|
||||
printLine(batch, 9, "tile@cursor ${ccO}W$ccG$wallNum ${ccO}T$ccG$tileNum ${ccO}C$ccG${wireNum.toString(2)} $ccY($mtX, $mtY)")
|
||||
printLine(batch, 9, "tile@cursor ${ccO}W$ccG$wallNum ${ccO}T$ccG$tileNum ${ccO}C$ccG${wireNum} $ccY($mtX, $mtY)")
|
||||
printLine(batch, 10, "fluid@cursor ${ccO}Type $ccG${fluid.type.value} ${ccO}Fill $ccG${fluid.amount}f")
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import kotlin.experimental.xor
|
||||
*/
|
||||
object PasswordBase32 {
|
||||
|
||||
private val stringSet = "YBNDRFG8EJKMCPQXOT+VWIS2A345H769="
|
||||
private val stringSet = "YBNDRFG8EJKMCPQXOTLVWIS2A345H769="
|
||||
|
||||
private val substituteSet = hashMapOf(
|
||||
Pair('0', 'O'),
|
||||
|
||||
@@ -8,6 +8,7 @@ import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.AppLoader.printdbg
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||
@@ -54,9 +55,6 @@ internal object BlocksDrawer {
|
||||
|
||||
//val tileItemWall = Image(TILE_SIZE * 16, TILE_SIZE * GameWorld.TILES_SUPPORTED / 16) // 4 MB
|
||||
|
||||
|
||||
val wallOverlayColour = Color(5f / 9f, 5f / 9f, 5f / 9f, 1f)
|
||||
|
||||
const val BREAKAGE_STEPS = 10
|
||||
|
||||
val WALL = GameWorld.WALL
|
||||
@@ -96,23 +94,7 @@ internal object BlocksDrawer {
|
||||
// with TGA, you have a complete control over this, with the expense of added hassle on your side.
|
||||
// -- Torvald, 2018-12-19
|
||||
|
||||
printdbg(this, "Making terrain textures...")
|
||||
|
||||
CreateTileAtlas()
|
||||
//JsonWriter.writeToFile(CreateTileAtlas.tags, "${AppLoader.defaultDir}/test_rendertags.json")
|
||||
// each takes about 60 seconds
|
||||
//printdbg(this, "Writing pixmap as tga: atlas.tga")
|
||||
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlas.tga"), CreateTileAtlas.atlas, false)
|
||||
//printdbg(this, "Writing pixmap as tga: atlasAutumn.tga")
|
||||
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasAutumn.tga"), CreateTileAtlas.atlasAutumn, false)
|
||||
//printdbg(this, "Writing pixmap as tga: atlasWinter.tga")
|
||||
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasWinter.tga"), CreateTileAtlas.atlasWinter, false)
|
||||
//printdbg(this, "Writing pixmap as tga: atlasSpring.tga")
|
||||
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasSpring.tga"), CreateTileAtlas.atlasSpring, false)
|
||||
//printdbg(this, "Writing pixmap as tga: atlasFluid.tga")
|
||||
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasFluid.tga"), CreateTileAtlas.atlasFluid, false)
|
||||
|
||||
|
||||
// CreateTileAtlas.invoke() has been moved to the AppLoader.create() //
|
||||
|
||||
// create terrain texture from pixmaps
|
||||
weatherTerrains = arrayOf(
|
||||
@@ -179,7 +161,7 @@ internal object BlocksDrawer {
|
||||
/**
|
||||
* To interact with external modules
|
||||
*/
|
||||
@JvmStatic fun addBlendMul(blockID: Int): Boolean {
|
||||
@JvmStatic fun addBlendMul(blockID: ItemID): Boolean {
|
||||
return TILES_BLEND_MUL.add(blockID)
|
||||
}
|
||||
|
||||
@@ -307,11 +289,11 @@ internal object BlocksDrawer {
|
||||
val bufferX = x - for_x_start
|
||||
val bufferY = y - for_y_start
|
||||
|
||||
val thisTile = when (mode) {
|
||||
val thisTile: ItemID = when (mode) {
|
||||
WALL -> world.getTileFromWall(x, y)
|
||||
TERRAIN -> world.getTileFromTerrain(x, y)
|
||||
WIRE -> world.getWiringBlocks(x, y).and(drawWires).toBitOrd() * 16
|
||||
FLUID -> world.getFluid(x, y).type.abs()
|
||||
WIRE -> "basegame:-1" // TODO need new wire storing format //world.getWiringBlocks(x, y).and(drawWires).toBitOrd() * 16
|
||||
FLUID -> "basegame:-1" // TODO need new wire storing format //world.getFluid(x, y).type.abs()
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
@@ -344,10 +326,10 @@ internal object BlocksDrawer {
|
||||
if (mode == FLUID)
|
||||
CreateTileAtlas.fluidToTileNumber(world.getFluid(x, y))
|
||||
else if (mode == WIRE)
|
||||
thisTile
|
||||
0 // TODO need new wire storing format
|
||||
else
|
||||
renderTag.tileNumber
|
||||
val tileNumber = if (mode != WIRE && thisTile == 0) 0
|
||||
val tileNumber = if (mode != WIRE && thisTile == Block.AIR) 0
|
||||
// special case: fluids
|
||||
else if (mode == FLUID) tileNumberBase + connectLut47[nearbyTilesInfo]
|
||||
// special case: wires
|
||||
@@ -376,11 +358,11 @@ internal object BlocksDrawer {
|
||||
|
||||
// draw a tile
|
||||
|
||||
if (mode == WIRE && thisTile < 0) {
|
||||
if (mode == WIRE) {
|
||||
// no wire here, draw block id 255 (bottom right)
|
||||
writeToBuffer(mode, bufferX, bufferY, 15, 15, 0)
|
||||
}
|
||||
else if (mode == FLUID || mode == WIRE) {
|
||||
else if (mode == FLUID) {
|
||||
writeToBuffer(mode, bufferX, bufferY, thisTileX, thisTileY, 0)
|
||||
}
|
||||
else {
|
||||
@@ -404,7 +386,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 }
|
||||
|
||||
var ret = 0
|
||||
@@ -423,8 +405,9 @@ internal object BlocksDrawer {
|
||||
*
|
||||
* @return offset from the spritesheet's "base" tile number, 0..15.
|
||||
*/
|
||||
private fun getNearbyWiringInfo(x: Int, y: Int, wire: Int): Int {
|
||||
val nearbyTiles = getNearbyTilesPos(x, y).map { world.getWiringBlocks(it.x, it.y).and(drawWires).toBitOrd() * 16 }
|
||||
private fun getNearbyWiringInfo(x: Int, y: Int, wire: ItemID): Int {
|
||||
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
|
||||
for (i in nearbyTiles.indices) {
|
||||
@@ -433,11 +416,11 @@ internal object BlocksDrawer {
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
return ret*/
|
||||
}
|
||||
|
||||
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
|
||||
for (i in nearbyTiles.indices) {
|
||||
@@ -454,7 +437,7 @@ internal object BlocksDrawer {
|
||||
*/
|
||||
private fun getNearbyTilesInfoFluids(x: Int, y: Int): Int {
|
||||
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
|
||||
for (i in nearbyTiles.indices) {
|
||||
@@ -468,12 +451,12 @@ internal object BlocksDrawer {
|
||||
}
|
||||
|
||||
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
|
||||
nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: Block.NULL
|
||||
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y) ?: Block.NULL
|
||||
nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(TERRAIN, x , y + 1) ?: Block.NULL
|
||||
nearbyTiles[NEARBY_TILE_KEY_BACK] = world.getTileFrom(WALL, x , 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)
|
||||
nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(TERRAIN, x , y + 1)
|
||||
nearbyTiles[NEARBY_TILE_KEY_BACK] = world.getTileFrom(WALL, x , y)
|
||||
|
||||
try {
|
||||
if (BlockCodex[nearbyTiles[NEARBY_TILE_KEY_DOWN]].isSolid)
|
||||
@@ -502,9 +485,11 @@ internal object BlocksDrawer {
|
||||
}
|
||||
|
||||
private fun getNearbyTilesInfoPlatform(x: Int, y: Int): Int {
|
||||
val nearbyTiles = IntArray(4)
|
||||
nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: Block.NULL
|
||||
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y) ?: Block.NULL
|
||||
val nearbyTiles = arrayOf(Block.NULL, Block.NULL, Block.NULL, Block.NULL)
|
||||
val NEARBY_TILE_KEY_BACK = NEARBY_TILE_KEY_UP
|
||||
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 &&
|
||||
BlockCodex[nearbyTiles[NEARBY_TILE_KEY_RIGHT]].isSolid) ||
|
||||
@@ -594,7 +579,7 @@ internal object BlocksDrawer {
|
||||
}
|
||||
val vertexColour = when (mode) {
|
||||
TERRAIN, WIRE, FLUID -> Color.WHITE
|
||||
WALL -> wallOverlayColour
|
||||
WALL -> CreateTileAtlas.wallOverlayColour
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
@@ -753,10 +738,10 @@ internal object BlocksDrawer {
|
||||
fun getRenderEndX(): Int = clampWTile(getRenderStartX() + (WorldCamera.width / 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 isConnectMutual(b: Int): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_MUTUAL
|
||||
fun isWallSticker(b: Int): 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 isConnectSelf(b: ItemID): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_SELF
|
||||
fun isConnectMutual(b: ItemID): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_MUTUAL
|
||||
fun isWallSticker(b: ItemID): Boolean = CreateTileAtlas.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_WALL_STICKER
|
||||
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 tileInCamera(x: Int, y: Int) =
|
||||
|
||||
@@ -6,9 +6,13 @@ import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import net.torvald.gdx.graphics.Cvec
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.AppLoader.printdbg
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||
import net.torvald.terrarum.blockproperties.Fluid
|
||||
import net.torvald.terrarum.gameitem.ItemID
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@@ -28,8 +32,12 @@ object CreateTileAtlas {
|
||||
const val TILE_SIZE = TerrarumAppConfiguration.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
|
||||
|
||||
val wallOverlayColour = Color(5f / 9f, 5f / 9f, 5f / 9f, 1f)
|
||||
|
||||
lateinit var atlas: Pixmap
|
||||
lateinit var atlasAutumn: Pixmap
|
||||
lateinit var atlasWinter: Pixmap
|
||||
@@ -38,32 +46,31 @@ object CreateTileAtlas {
|
||||
lateinit var atlasGlow: Pixmap // glowing won't be affected by the season... for now
|
||||
lateinit var itemTerrainTexture: Texture
|
||||
lateinit var itemWallTexture: Texture
|
||||
lateinit var terrainTileColourMap: GdxColorMap
|
||||
internal lateinit var tags: HashMap<Int, RenderTag>
|
||||
lateinit var terrainTileColourMap: HashMap<ItemID, Cvec>
|
||||
lateinit var tags: HashMap<ItemID, RenderTag> // TileID, RenderTag
|
||||
private set
|
||||
lateinit var itemSheetNumbers: HashMap<ItemID, Int> // TileID, Int
|
||||
private set
|
||||
private val defaultRenderTag = RenderTag(3, RenderTag.CONNECT_SELF, RenderTag.MASK_NA) // 'update' block
|
||||
var initialised = false
|
||||
private set
|
||||
|
||||
/** 0000.tga, 1.tga.gz, 3242423.tga, 000033.tga.gz */
|
||||
// for right now, TGA file only, no gzip
|
||||
private val validFluidTilesFilename = Regex("""fluid_[0-9]+\.tga""")
|
||||
private val tileNameRegex = Regex("""[0-9]+\.tga""")
|
||||
private val tileGlowNameRegex = Regex("""[0-9]+_glow\.tga""")
|
||||
/** 0.tga, 1.tga.gz, 3242423.tga, 33.tga.gz */
|
||||
private val tileNameRegex = Regex("""(0|[1-9][0-9]*)\.tga(\.gz)?""")
|
||||
|
||||
// 16 tiles are reserved for internal use: solid black, solid white, breakage stages.
|
||||
// 0th tile is complete transparent tile and is also a BlockID of zero: air.
|
||||
private var atlasCursor = 0
|
||||
private var atlasCursorGlow = 0
|
||||
private var atlasCursor = 64 // 64 predefined tiles. The normal blocks (e.g. Air) should start from this number
|
||||
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
|
||||
*/
|
||||
operator fun invoke(updateExisting: Boolean = false) { if (updateExisting || !initialised) {
|
||||
|
||||
tags = HashMap<Int, RenderTag>()
|
||||
tags[0] = RenderTag(0, RenderTag.CONNECT_SELF, RenderTag.MASK_NA)
|
||||
tags = HashMap<ItemID, RenderTag>()
|
||||
itemSheetNumbers = HashMap<ItemID, Int>()
|
||||
|
||||
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)
|
||||
@@ -79,34 +86,39 @@ object CreateTileAtlas {
|
||||
atlasFluid.blending = Pixmap.Blending.None
|
||||
atlasGlow.blending = Pixmap.Blending.None
|
||||
|
||||
val initMap = Pixmap(Gdx.files.internal(atlasInit))
|
||||
drawToAtlantes(initMap, nullTile, 16)
|
||||
initMap.dispose()
|
||||
|
||||
// populate the atlantes with atlasInit
|
||||
// this just directly copies the image to the atlantes :p
|
||||
val initPixmap = Pixmap(Gdx.files.internal(atlasInit))
|
||||
atlas.drawPixmap(initPixmap, 0, 0)
|
||||
atlasAutumn.drawPixmap(initPixmap, 0, 0)
|
||||
atlasWinter.drawPixmap(initPixmap, 0, 0)
|
||||
atlasSpring.drawPixmap(initPixmap, 0, 0)
|
||||
|
||||
// get all the files applicable
|
||||
// first, get all the '/blocks' directory, and add all the files, regardless of their extension, to the list
|
||||
val tgaList = ArrayList<FileHandle>()
|
||||
ModMgr.getGdxFilesFromEveryMod("blocks").forEach {
|
||||
if (!it.isDirectory) {
|
||||
throw Error("Path '${it.path()}' is not a directory")
|
||||
val tgaList = ArrayList<Pair<String, FileHandle>>() //Pair of <modname, filehandle>
|
||||
ModMgr.getGdxFilesFromEveryMod("blocks").forEach { (modname, dir) ->
|
||||
if (!dir.isDirectory) {
|
||||
throw Error("Path '${dir.path()}' is not a directory")
|
||||
}
|
||||
|
||||
it.list().forEach { tgaFile ->
|
||||
if (!tgaFile.isDirectory && (tgaFile.name().matches(tileNameRegex))) {
|
||||
tgaList.add(tgaFile)
|
||||
}
|
||||
}
|
||||
|
||||
dir.list().filter { tgaFile -> !tgaFile.isDirectory && (tgaFile.name().matches(tileNameRegex)) }
|
||||
.sortedBy { it.nameWithoutExtension().toInt() }.forEach { tgaFile -> // toInt() to sort by the number, not lexicographically
|
||||
tgaList.add(modname to tgaFile)
|
||||
}
|
||||
}
|
||||
|
||||
// Sift through the file list for blocks, but TGA format first
|
||||
tgaList.forEach {
|
||||
tgaList.forEach { (modname, filehandle) ->
|
||||
printdbg(this, "processing $modname:${filehandle.name()}")
|
||||
|
||||
try {
|
||||
val glowFile = Gdx.files.internal(it.path().dropLast(4) + "_glow.tga") // assuming strict ".tga" file
|
||||
fileToAtlantes(it, if (glowFile.exists()) glowFile else null)
|
||||
val glowFile = Gdx.files.internal(filehandle.path().dropLast(4) + "_glow.tga") // assuming strict ".tga" file for now...
|
||||
fileToAtlantes(modname, filehandle, if (glowFile.exists()) glowFile else null)
|
||||
}
|
||||
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 +139,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
|
||||
|
||||
fun maskTypetoTileIDForItemImage(maskType: Int) = when(maskType) {
|
||||
@@ -204,62 +149,63 @@ object CreateTileAtlas {
|
||||
|
||||
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 terrainColormapPixmap = Pixmap(16, TILES_IN_X, Pixmap.Format.RGBA8888)
|
||||
|
||||
CreateTileAtlas.tags.toMap().forEach { t, u ->
|
||||
val tilePosFromAtlas = u.tileNumber + maskTypetoTileIDForItemImage(u.maskType)
|
||||
CreateTileAtlas.tags.toMap().forEach { id, tag ->
|
||||
val tilePosFromAtlas = tag.tileNumber + maskTypetoTileIDForItemImage(tag.maskType)
|
||||
val srcX = (tilePosFromAtlas % TILES_IN_X) * TILE_SIZE
|
||||
val srcY = (tilePosFromAtlas / TILES_IN_X) * TILE_SIZE
|
||||
val destX = (t % 16) * TILE_SIZE
|
||||
val destY = (t / 16) * TILE_SIZE
|
||||
val t = tileIDtoItemSheetNumber(id)
|
||||
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)
|
||||
itemWallPixmap.drawPixmap(CreateTileAtlas.atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
|
||||
}
|
||||
// darken things for the wall
|
||||
for (y in 0 until itemWallPixmap.height) {
|
||||
for (x in 0 until itemWallPixmap.width) {
|
||||
val c = Color(itemWallPixmap.getPixel(x, y)).mulAndAssign(BlocksDrawer.wallOverlayColour).toRGBA()
|
||||
val c = Color(itemWallPixmap.getPixel(x, y)).mulAndAssign(wallOverlayColour).toRGBA()
|
||||
itemWallPixmap.drawPixel(x, y, c)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// create terrain colourmap
|
||||
terrainTileColourMap = HashMap<ItemID, Cvec>()
|
||||
val pxCount = TILE_SIZE * TILE_SIZE
|
||||
for (id in 0 until BlockCodex.MAX_TERRAIN_TILES) {
|
||||
val tx = (id % 16) * TILE_SIZE
|
||||
val ty = (id / 16) * TILE_SIZE
|
||||
var r = 0; var g = 0; var b = 0; var a = 0
|
||||
for (id in itemSheetNumbers) {
|
||||
val tilenum = id.value
|
||||
val tx = (tilenum % ITEM_ATLAS_TILES_X) * TILE_SIZE
|
||||
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
|
||||
for (y in ty until ty + TILE_SIZE) {
|
||||
for (x in tx until tx + TILE_SIZE) {
|
||||
val data = itemTerrainPixmap.getPixel(x, y)
|
||||
r += (data ushr 24) and 255
|
||||
g += (data ushr 16) and 255
|
||||
b += (data ushr 8) and 255
|
||||
a += data and 255
|
||||
r += ((data ushr 24) and 255).div(255f)
|
||||
g += ((data ushr 16) and 255).div(255f)
|
||||
b += ((data ushr 8) and 255).div(255f)
|
||||
a += (data and 255).div(255f)
|
||||
}
|
||||
}
|
||||
|
||||
terrainColormapPixmap.drawPixel(tx / TILE_SIZE, ty / TILE_SIZE,
|
||||
(r / pxCount).shl(24) or
|
||||
(g / pxCount).shl(16) or
|
||||
(b / pxCount).shl(8) or
|
||||
(a / pxCount)
|
||||
terrainTileColourMap[id.key] = Cvec(
|
||||
(r / pxCount),
|
||||
(g / pxCount),
|
||||
(b / 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)
|
||||
itemWallTexture = Texture(itemWallPixmap)
|
||||
itemTerrainPixmap.dispose()
|
||||
itemWallPixmap.dispose()
|
||||
initPixmap.dispose()
|
||||
|
||||
initialised = true
|
||||
} }
|
||||
|
||||
fun getRenderTag(blockID: Int): RenderTag {
|
||||
fun getRenderTag(blockID: ItemID): RenderTag {
|
||||
return tags.getOrDefault(blockID, defaultRenderTag)
|
||||
}
|
||||
|
||||
@@ -271,12 +217,13 @@ object CreateTileAtlas {
|
||||
16 + (376 * (fluid.type.abs() - 1)) + (47 * (fluidLevel - 1))
|
||||
}
|
||||
|
||||
private val nullTile = Pixmap(TILE_SIZE * 16, TILE_SIZE * 16, Pixmap.Format.RGBA8888)
|
||||
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 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)
|
||||
// predefined by the image dimension: 16x16 for (1,0)
|
||||
@@ -297,7 +244,7 @@ object CreateTileAtlas {
|
||||
// 112x112 or 224x224
|
||||
else {
|
||||
if (tilesPixmap.width != tilesPixmap.height && tilesPixmap.width % (7 * TILE_SIZE) >= 2) {
|
||||
throw IllegalArgumentException("Unrecognized image dimension: ${tilesPixmap.width}x${tilesPixmap.height}")
|
||||
throw IllegalArgumentException("Unrecognized image dimension ${tilesPixmap.width}x${tilesPixmap.height} from $modname:${matte.name()}")
|
||||
}
|
||||
// figure out the tags
|
||||
var connectionType = 0
|
||||
@@ -317,19 +264,29 @@ object CreateTileAtlas {
|
||||
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tileCount)
|
||||
}
|
||||
|
||||
itemSheetNumbers[blockID] = itemSheetCursor
|
||||
itemSheetCursor += 1
|
||||
|
||||
tilesPixmap.dispose()
|
||||
}
|
||||
|
||||
fun tileIDtoAtlasNumber(tileID: ItemID) = tags[tileID]?.tileNumber
|
||||
?: throw NullPointerException("AtlasNumbers mapping from $tileID does not exist")
|
||||
fun tileIDtoItemSheetNumber(tileID: ItemID) = itemSheetNumbers[tileID]
|
||||
?: throw NullPointerException("ItemSheetNumber mapping from $tileID does not exist")
|
||||
|
||||
/**
|
||||
* This function must precede the drawToAtlantes() function, as the marking requires the variable
|
||||
* '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)) {
|
||||
throw Error("Block $id already exists")
|
||||
}
|
||||
|
||||
tags[id] = RenderTag(atlasCursor, connectionType, maskType)
|
||||
|
||||
printdbg(this, "tileName ${id} ->> tileNumber ${atlasCursor}")
|
||||
}
|
||||
|
||||
private fun drawToAtlantes(pixmap: Pixmap, glow: Pixmap, tilesCount: Int) {
|
||||
@@ -391,6 +348,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) {
|
||||
companion object {
|
||||
const val CONNECT_MUTUAL = 0
|
||||
@@ -422,6 +382,8 @@ object CreateTileAtlas {
|
||||
atlasSpring.dispose()
|
||||
atlasFluid.dispose()
|
||||
atlasGlow.dispose()
|
||||
//itemTerrainTexture.dispose() //BlocksDrawer will dispose of it as it disposes of 'tileItemTerrain (TextureRegionPack)'
|
||||
//itemWallTexture.dispose() //BlocksDrawer will dispose of it as it disposes of 'tileItemWall (TextureRegionPack)'
|
||||
|
||||
nullTile.dispose()
|
||||
}
|
||||
|
||||
@@ -27,13 +27,13 @@ object FeaturesDrawer {
|
||||
var colTemp: Int = 0
|
||||
private set
|
||||
|
||||
private val TILES_COLD = intArrayOf(
|
||||
private val TILES_COLD = arrayOf(
|
||||
Block.ICE_MAGICAL
|
||||
, Block.ICE_FRAGILE
|
||||
, Block.ICE_NATURAL
|
||||
, Block.SNOW)
|
||||
|
||||
private val TILES_WARM = intArrayOf(
|
||||
private val TILES_WARM = arrayOf(
|
||||
Block.SAND_DESERT
|
||||
, Block.SAND_RED)
|
||||
|
||||
|
||||
@@ -20,135 +20,5 @@ internal class LightCalculatorContext(
|
||||
private val lightmap: UnsafeCvecArray,
|
||||
private val lanternMap: HashMap<BlockAddress, Cvec>
|
||||
) {
|
||||
|
||||
private val colourNull = Cvec(0)
|
||||
|
||||
private val ambientAccumulator = Cvec(0f,0f,0f,0f)
|
||||
private val lightLevelThis = Cvec(0)
|
||||
private val fluidAmountToCol = Cvec(0)
|
||||
private val thisTileLuminosity = Cvec(0)
|
||||
private val thisTileOpacity = Cvec(0)
|
||||
private val thisTileOpacity2 = Cvec(0) // thisTileOpacity * sqrt(2)
|
||||
private val sunLight = Cvec(0)
|
||||
private var thisFluid = GameWorld.FluidInfo(Fluid.NULL, 0f)
|
||||
private var thisTerrain = 0
|
||||
private var thisWall = 0
|
||||
|
||||
private fun getLightsAndShades(x: Int, y: Int) {
|
||||
val (x, y) = world.coerceXY(x, y)
|
||||
|
||||
lightLevelThis.set(colourNull)
|
||||
thisTerrain = world.getTileFromTerrainRaw(x, y)
|
||||
thisFluid = world.getFluid(x, y)
|
||||
thisWall = world.getTileFromWallRaw(x, y)
|
||||
|
||||
// regarding the issue #26
|
||||
// uncomment this if you're facing diabolically indescribable bugs
|
||||
/*try {
|
||||
val fuck = BlockCodex[thisTerrain].getLumCol(x, y)
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
System.err.println("## NPE -- x: $x, y: $y, value: ${thisTerrain}")
|
||||
e.printStackTrace()
|
||||
// create shitty minidump
|
||||
System.err.println("MINIMINIDUMP START")
|
||||
for (xx in x - 16 until x + 16) {
|
||||
val raw = world.getTileFromTerrain(xx, y)
|
||||
val lsb = raw.and(0xff).toString(16).padStart(2, '0')
|
||||
val msb = raw.ushr(8).and(0xff).toString(16).padStart(2, '0')
|
||||
System.err.print(lsb)
|
||||
System.err.print(msb)
|
||||
System.err.print(" ")
|
||||
}
|
||||
System.err.println("\nMINIMINIDUMP END")
|
||||
|
||||
exitProcess(1)
|
||||
}*/
|
||||
|
||||
if (thisFluid.type != Fluid.NULL) {
|
||||
fluidAmountToCol.set(thisFluid.amount, thisFluid.amount, thisFluid.amount, thisFluid.amount)
|
||||
|
||||
thisTileLuminosity.set(BlockCodex[thisTerrain].getLumCol(x, y))
|
||||
thisTileLuminosity.maxAndAssign(BlockCodex[thisFluid.type].getLumCol(x, y).mul(fluidAmountToCol)) // already been div by four
|
||||
thisTileOpacity.set(BlockCodex[thisTerrain].opacity)
|
||||
thisTileOpacity.maxAndAssign(BlockCodex[thisFluid.type].opacity.mul(fluidAmountToCol)) // already been div by four
|
||||
}
|
||||
else {
|
||||
thisTileLuminosity.set(BlockCodex[thisTerrain].getLumCol(x, y))
|
||||
thisTileOpacity.set(BlockCodex[thisTerrain].opacity)
|
||||
}
|
||||
|
||||
thisTileOpacity2.set(thisTileOpacity); thisTileOpacity2.mul(1.41421356f)
|
||||
//sunLight.set(world.globalLight); sunLight.mul(DIV_FLOAT) // moved to fireRecalculateEvent()
|
||||
|
||||
|
||||
// open air || luminous tile backed by sunlight
|
||||
if ((thisTerrain == AIR && thisWall == AIR) || (thisTileLuminosity.nonZero() && thisWall == AIR)) {
|
||||
lightLevelThis.set(sunLight)
|
||||
}
|
||||
|
||||
// blend lantern
|
||||
lightLevelThis.maxAndAssign(thisTileLuminosity).maxAndAssign(lanternMap[LandUtil.getBlockAddr(world, x, y)] ?: colourNull)
|
||||
}
|
||||
|
||||
fun calculateAndAssign(worldX: Int, worldY: Int) {
|
||||
|
||||
//if (inNoopMask(worldX, worldY)) return
|
||||
|
||||
// O(9n) == O(n) where n is a size of the map
|
||||
|
||||
getLightsAndShades(worldX, worldY)
|
||||
|
||||
val x = worldX.convX()
|
||||
val y = worldY.convY()
|
||||
|
||||
// calculate ambient
|
||||
/* + * + 0 4 1
|
||||
* * @ * 6 @ 7
|
||||
* + * + 2 5 3
|
||||
* sample ambient for eight points and apply attenuation for those
|
||||
* maxblend eight values and use it
|
||||
*/
|
||||
|
||||
// will "overwrite" what's there in the lightmap if it's the first pass
|
||||
// takes about 2 ms on 6700K
|
||||
/* + */lightLevelThis.maxAndAssign(LightmapRenderer.darkenColoured(x - 1, y - 1, thisTileOpacity2))
|
||||
/* + */lightLevelThis.maxAndAssign(LightmapRenderer.darkenColoured(x + 1, y - 1, thisTileOpacity2))
|
||||
/* + */lightLevelThis.maxAndAssign(LightmapRenderer.darkenColoured(x - 1, y + 1, thisTileOpacity2))
|
||||
/* + */lightLevelThis.maxAndAssign(LightmapRenderer.darkenColoured(x + 1, y + 1, thisTileOpacity2))
|
||||
/* * */lightLevelThis.maxAndAssign(LightmapRenderer.darkenColoured(x, y - 1, thisTileOpacity))
|
||||
/* * */lightLevelThis.maxAndAssign(LightmapRenderer.darkenColoured(x, y + 1, thisTileOpacity))
|
||||
/* * */lightLevelThis.maxAndAssign(LightmapRenderer.darkenColoured(x - 1, y, thisTileOpacity))
|
||||
/* * */lightLevelThis.maxAndAssign(LightmapRenderer.darkenColoured(x + 1, y, thisTileOpacity))
|
||||
|
||||
|
||||
//return lightLevelThis.cpy() // it HAS to be a cpy(), otherwise all cells gets the same instance
|
||||
//setLightOf(lightmap, x, y, lightLevelThis.cpy())
|
||||
|
||||
lightmap.setR(x, y, lightLevelThis.r)
|
||||
lightmap.setG(x, y, lightLevelThis.g)
|
||||
lightmap.setB(x, y, lightLevelThis.b)
|
||||
lightmap.setA(x, y, lightLevelThis.a)
|
||||
}
|
||||
|
||||
private fun Cvec.maxAndAssign(other: Cvec): Cvec {
|
||||
// TODO investigate: if I use assignment instead of set(), it blackens like the vector branch. --Torvald, 2019-06-07
|
||||
// that was because you forgot 'this.r/g/b/a = ' part, bitch. --Torvald, 2019-06-07
|
||||
this.r = if (this.r > other.r) this.r else other.r
|
||||
this.g = if (this.g > other.g) this.g else other.g
|
||||
this.b = if (this.b > other.b) this.b else other.b
|
||||
this.a = if (this.a > other.a) this.a else other.a
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
private fun Cvec.nonZero() = this.r.abs() > LightmapRenderer.epsilon ||
|
||||
this.g.abs() > LightmapRenderer.epsilon ||
|
||||
this.b.abs() > LightmapRenderer.epsilon ||
|
||||
this.a.abs() > LightmapRenderer.epsilon
|
||||
|
||||
/** World coord to array coord */
|
||||
private inline fun Int.convX() = this - LightmapRenderer.for_x_start + LightmapRenderer.overscan_open
|
||||
/** World coord to array coord */
|
||||
private inline fun Int.convY() = this - LightmapRenderer.for_y_start + LightmapRenderer.overscan_open
|
||||
// No longer in use because of the much efficient light updating method
|
||||
}
|
||||
@@ -487,14 +487,14 @@ object LightmapRenderer {
|
||||
if (_thisFluid.type != Fluid.NULL) {
|
||||
_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
|
||||
_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
|
||||
}
|
||||
else {
|
||||
_thisTileLuminosity.set(BlockCodex[_thisTerrain].getLumCol(worldX, worldY))
|
||||
_mapThisTileOpacity.setVec(lx, ly, BlockCodex[_thisTerrain].opacity)
|
||||
_thisTileLuminosity.set(BlockCodex[world.tileNumberToNameMap[_thisTerrain]].getLumCol(worldX, worldY))
|
||||
_mapThisTileOpacity.setVec(lx, ly, BlockCodex[world.tileNumberToNameMap[_thisTerrain]].opacity)
|
||||
}
|
||||
|
||||
_mapThisTileOpacity2.setR(lx, ly, _mapThisTileOpacity.getR(lx, ly) * 1.41421356f)
|
||||
@@ -504,7 +504,8 @@ object LightmapRenderer {
|
||||
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ Files contained the TerranVirtualDisk is as follows:
|
||||
Has fixed Entry ID of 32763
|
||||
world[n] -- Layer Data (TEMD); [n] is a serial number of the world (starts at 1)
|
||||
Has fixed Entry ID of [n]
|
||||
(any random number in Hex ACTORID_MIN..FFFFFFFF) -- Serialised Entity Information (including Player)
|
||||
(PLAYER_REF_ID in Hex -- 91A7E2) -- Player Character Information (Serialised--JSON'd--Entity Information)
|
||||
(51621D) -- The Debug Player (Serialised Entity Information)
|
||||
(any random number in Hex ACTORID_MIN..FFFFFFFF) -- Serialised Entity Information (including Player), Entry ID is random
|
||||
(PLAYER_REF_ID in Hex -- 91A7E2) -- Player Character Information (Serialised--JSON'd--Entity Information), Entry ID is random
|
||||
(51621D) -- The Debug Player (Serialised Entity Information), Entry ID is random
|
||||
load_order.txt -- LoadOrder.csv (NOT zipped)
|
||||
Has fixed Entry ID of 32767
|
||||
|
||||
|
||||
@@ -43,17 +43,17 @@ Ord Hex Description
|
||||
# A payload is consisted as follows:
|
||||
#
|
||||
# Literal Description
|
||||
# "\0pLd" Payload header [00, 70, 4C, 64]
|
||||
# "\0pLd" Payload header [00, 70, 4C, 64]
|
||||
# [4] Identifier. 4 lettres ASCII string
|
||||
# [6] Uncompressed size of DEFLATEd binary (max size 256 TB)
|
||||
# [6] Length of the actual payload (max size 256 TB)
|
||||
# [..] DEFLATEd binary (begins with one of these: 0x789C, 0x78DA, 0x7801)
|
||||
# "EndPYLd\xFF" Payload footer [45, 6E, 64, 50, 59, 4C, 64, FF]
|
||||
|
||||
|
||||
Payload "TERR" -- world terrain data in Uint16
|
||||
Uncompressed size will be 2x of (width * height)
|
||||
|
||||
Payload "WALL" -- world walls data in Unit16
|
||||
Payload "WALL" -- world walls data in Uint16
|
||||
Uncompressed size will be 2x of (width * height)
|
||||
|
||||
Payload "TdMG" -- world terrain damage data, array of: (Int48 tileAddress, Float32 damage)
|
||||
@@ -71,11 +71,17 @@ Payload "FlFL" -- world fluid fills, array of: (Int48 tileAddress, Float32 amoun
|
||||
|
||||
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
|
||||
|
||||
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 6E n
|
||||
@@ -86,7 +92,3 @@ EOF 4D M
|
||||
EOF FF Byte order mark
|
||||
EOF FE Byte order mark
|
||||
|
||||
|
||||
* To read layers: you'll need to search for specific strings, namely ["TERR", "WALL", "WIRE"]
|
||||
* It is possible that compressed data happen to replicate any of the internal identifiers
|
||||
(e.g. "\0pLdTERR", "EndTEM\xFF\xFE", "EndPYLd\xFF"), but such probability is very low (0.000000000000000005421 %)
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user