mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-07 09:04:05 +09:00
Compare commits
12 Commits
world-chun
...
v0.5.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a24eab209b | ||
|
|
6ec5ba5603 | ||
|
|
8cf4b5d9a9 | ||
|
|
5bf60cfa82 | ||
|
|
5cc7db8ecc | ||
|
|
89b12aabb4 | ||
|
|
f5846d9bae | ||
|
|
d460447331 | ||
|
|
63fe28eee2 | ||
|
|
2d7ef6e9ff | ||
|
|
fa3a129991 | ||
|
|
4cc74a85d1 |
@@ -3,6 +3,7 @@ CheatWarnTest
|
||||
CodexEdictis
|
||||
ExportAtlas
|
||||
ExportCodices
|
||||
ExportFBO
|
||||
ExportMap
|
||||
ExportMap2
|
||||
ExportWorld
|
||||
|
||||
|
@@ -132,8 +132,8 @@ id;classname;tags
|
||||
320;net.torvald.terrarum.modulebasegame.gameitems.ItemWorldPortal;FIXTURE,STATION
|
||||
|
||||
# industrial
|
||||
2048;net.torvald.terrarum.modulebasegame.gameitems.ItemInductionMotor;FIXTURE,POWER,KINETIC
|
||||
2049;net.torvald.terrarum.modulebasegame.gameitems.ItemGearbox;FIXTURE,POWER,KINETIC
|
||||
#2048;net.torvald.terrarum.modulebasegame.gameitems.ItemInductionMotor;FIXTURE,POWER,KINETIC
|
||||
#2049;net.torvald.terrarum.modulebasegame.gameitems.ItemGearbox;FIXTURE,POWER,KINETIC
|
||||
|
||||
# data storage (discs; 256)
|
||||
# 32768 is a reserved number for a blank disc
|
||||
@@ -179,5 +179,5 @@ id;classname;tags
|
||||
1048835;net.torvald.terrarum.modulebasegame.gameitems.ItemBucketIron03;FLUIDSTORAGE,OPENSTORAGE
|
||||
|
||||
# reserved for debug items
|
||||
16777216;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessWaterBucket;DEBUG,TOOL
|
||||
16777217;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessLavaBucket;DEBUG,TOOL
|
||||
#16777216;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessWaterBucket;DEBUG,TOOL
|
||||
#16777217;net.torvald.terrarum.modulebasegame.gameitems.ItemBottomlessLavaBucket;DEBUG,TOOL
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"ITEM_ALLOYING_FURNACE": "Alloying Furnace",
|
||||
"ITEM_AXLE": "Axle",
|
||||
"ITEM_BRICK_SINGULAR": "Brick", /* always singular */
|
||||
"ITEM_BUCKET_IRON": "Iron Bucket %1$s",
|
||||
"ITEM_BUCKET_WOODEN": "Wooden Bucket %1$s",
|
||||
@@ -17,6 +18,7 @@
|
||||
"ITEM_ELECTRIC_WORKBENCH": "Electric Workbench",
|
||||
"ITEM_ENGRAVING_WORKBENCH": "Engraving Workbench",
|
||||
"ITEM_FURNACE_AND_ANVIL": "Furnace and Anvil",
|
||||
"ITEM_GEARBOX": "Gearbox",
|
||||
"ITEM_GEM_RUBY": "Raw Ruby",
|
||||
"ITEM_GEM_EMERALD": "Raw Emerald",
|
||||
"ITEM_GEM_SAPPHIRE": "Raw Sapphire",
|
||||
@@ -30,6 +32,7 @@
|
||||
"ITEM_HATCHET_STEEL": "Steel Axe",
|
||||
"ITEM_HATCHET_STONE": "Stone Axe",
|
||||
"ITEM_HATCHET_WOODEN": "Wooden Axe",
|
||||
"ITEM_INDUCTION_MOTOR": "Induction Motor",
|
||||
"ITEM_INGOT_BRASS": "Brass Ingot",
|
||||
"ITEM_INGOT_BRONZE": "Bronze Ingot",
|
||||
"ITEM_INGOT_COPPER": "Copper Ingot",
|
||||
|
||||
@@ -9,7 +9,7 @@ id;drop;name;renderclass;accept;inputcount;inputtype;outputtype;javaclass;invent
|
||||
2;2;WIRE_POWER_HIGH;power;power_high;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,6,4;1;"POWERWIRE_HIGH"
|
||||
16;16;WIRE_ETHERNET;network;10base2;3;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceSignalWire;basegame.items,7,4;1;"ETHERNETWIRE"
|
||||
|
||||
256;256;AXLE;axle;axle;1;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceAxle;basegame.items,1,5;0;"AXLE"
|
||||
#256;256;AXLE;axle;axle;1;N/A;N/A;net.torvald.terrarum.modulebasegame.gameitems.WirePieceAxle;basegame.items,1,5;0;"AXLE"
|
||||
|
||||
# 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
|
||||
|
||||
|
@@ -31,7 +31,6 @@ import net.torvald.terrarum.gamecontroller.KeyToggler;
|
||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent;
|
||||
import net.torvald.terrarum.gameitems.GameItem;
|
||||
import net.torvald.terrarum.gameworld.GameWorld;
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld;
|
||||
import net.torvald.terrarum.imagefont.BigAlphNum;
|
||||
import net.torvald.terrarum.imagefont.TinyAlphNum;
|
||||
import net.torvald.terrarum.langpack.Lang;
|
||||
@@ -39,6 +38,7 @@ import net.torvald.terrarum.modulebasegame.IngameRenderer;
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame;
|
||||
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory;
|
||||
import net.torvald.terrarum.serialise.WriteConfig;
|
||||
import net.torvald.terrarum.ui.BlurMgr;
|
||||
import net.torvald.terrarum.ui.Toolkit;
|
||||
import net.torvald.terrarum.utils.JsonFetcher;
|
||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas;
|
||||
@@ -53,12 +53,14 @@ import org.apache.commons.csv.CSVParser;
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import javax.tools.Tool;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import static java.lang.Thread.MAX_PRIORITY;
|
||||
import static net.torvald.terrarum.TerrarumKt.*;
|
||||
@@ -765,7 +767,7 @@ public class App implements ApplicationListener {
|
||||
FrameBufferManager.begin(fb);
|
||||
try {
|
||||
Pixmap p = Pixmap.createFromFrameBuffer(0, 0, fb.getWidth(), fb.getHeight());
|
||||
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, 9, true);
|
||||
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, Deflater.DEFAULT_COMPRESSION, true);
|
||||
p.dispose();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
@@ -1017,7 +1019,7 @@ public class App implements ApplicationListener {
|
||||
|
||||
ModMgr.INSTANCE.disposeMods();
|
||||
|
||||
TheGameWorld.Companion.makeNullWorld().dispose();
|
||||
GameWorld.Companion.makeNullWorld().dispose();
|
||||
|
||||
Terrarum.INSTANCE.dispose();
|
||||
|
||||
@@ -1027,6 +1029,9 @@ public class App implements ApplicationListener {
|
||||
|
||||
deleteTempfiles();
|
||||
|
||||
Toolkit.INSTANCE.dispose();
|
||||
BlurMgr.INSTANCE.dispose();
|
||||
|
||||
disposables.forEach((it) -> {
|
||||
try {
|
||||
it.dispose();
|
||||
|
||||
@@ -33,7 +33,7 @@ object CheckUpdate {
|
||||
private val checkUpdateURL = setOf(
|
||||
"https://github.com/curioustorvald/Terrarum/releases/tag/v$versionNumOnly",
|
||||
"https://github.com/curioustorvald/Terrarum/releases/tag/v$versionNumFull",
|
||||
).toList()
|
||||
).map { it.replace(' ', '_') }
|
||||
|
||||
private fun wget(url: String): String? {
|
||||
printdbg(this, "wget $url")
|
||||
|
||||
@@ -12,8 +12,6 @@ import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.gameworld.TitlescreenGameWorld
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
@@ -107,7 +105,7 @@ open class IngameInstance(val batch: FlippingSpriteBatch, val isMultiplayer: Boo
|
||||
printStackTrace(this)
|
||||
}
|
||||
|
||||
open var world: GameWorld = TheGameWorld.makeNullWorld()
|
||||
open var world: GameWorld = GameWorld.makeNullWorld()
|
||||
set(value) {
|
||||
val oldWorld = field
|
||||
newWorldLoadedLatch = true
|
||||
|
||||
@@ -69,7 +69,7 @@ basegame
|
||||
* e.g. 0x02010034 will be translated as 2.1.52
|
||||
*
|
||||
*/
|
||||
const val VERSION_RAW: Long = 0x0000_000004_000004
|
||||
const val VERSION_RAW: Long = 0x0000_000005_000001
|
||||
// Commit counts up to the Release 0.3.0: 2259
|
||||
// Commit counts up to the Release 0.3.1: 2278
|
||||
// Commit counts up to the Release 0.3.2: 2732
|
||||
@@ -77,6 +77,8 @@ basegame
|
||||
// Commit counts up to the Release 0.4.0: 3631
|
||||
// Commit counts up to the Release 0.4.1: 3678
|
||||
// Commit counts up to the Release 0.4.2: 3762
|
||||
// Commit counts up to the Release 0.5.0: 4090
|
||||
// Commit counts up to the Release 0.5.1: 4097
|
||||
|
||||
val DEV_CYCLE: Map<String, Long> = mapOf(
|
||||
"Alpha" to 0x0000_000004_000000,
|
||||
|
||||
@@ -95,7 +95,7 @@ class UIFakeBlurOverlay(val blurRadius: Float, val nodarken: Boolean) : UICanvas
|
||||
batchDrawCol.a = openness
|
||||
batch.color = batchDrawCol
|
||||
if (App.getConfigBoolean("fx_backgroundblur")) {
|
||||
Toolkit.blurEntireScreen(batch, camera as OrthographicCamera, blurRadius * openness, 0, 0, width, height)
|
||||
Toolkit.blurEntireScreen(batch, blurRadius * openness, 0, 0, width, height)
|
||||
}
|
||||
|
||||
if (!nodarken) {
|
||||
|
||||
@@ -2,17 +2,26 @@ package net.torvald.terrarum.blockstats
|
||||
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import com.badlogic.gdx.utils.Queue
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.abs
|
||||
import net.torvald.terrarum.concurrent.ThreadExecutor
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_HEIGHT
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIInventoryMinimap.Companion.MINIMAP_WIDTH
|
||||
import net.torvald.terrarum.sqr
|
||||
import net.torvald.terrarum.toInt
|
||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.Companion.WALL_OVERLAY_COLOUR
|
||||
import java.util.concurrent.Callable
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object MinimapComposer : Disposable {
|
||||
|
||||
@@ -23,7 +32,7 @@ object MinimapComposer : Disposable {
|
||||
val MINIMAP_TILE_WIDTH = (MINIMAP_WIDTH.toInt() * 3) / SQUARE_SIZE + 4
|
||||
val MINIMAP_TILE_HEIGHT = (MINIMAP_HEIGHT.toInt() * 3) / SQUARE_SIZE + 4
|
||||
|
||||
private var world: GameWorld = TheGameWorld.makeNullWorld()
|
||||
private var world: GameWorld = GameWorld.makeNullWorld()
|
||||
|
||||
fun setWorld(world: GameWorld) {
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.torvald.terrarum.console
|
||||
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import net.torvald.terrarum.modulebasegame.console.GetAV.isNum
|
||||
*/
|
||||
internal object GetGR : ConsoleCommand {
|
||||
override fun execute(args: Array<String>) {
|
||||
val gameRules = (INGAME.world as TheGameWorld).gameRules
|
||||
val gameRules = INGAME.world.gameRules
|
||||
|
||||
// check if args[1] is number or not
|
||||
if (args.size > 1 && !args[1].isNum()) { // args[1] is Gamerule name
|
||||
|
||||
@@ -67,7 +67,7 @@ class SavegameCracker(
|
||||
private val cmds: HashMap<String, KFunction<*>> = HashMap()
|
||||
init {
|
||||
SavegameCracker::class.declaredFunctions
|
||||
.filter { it.findAnnotation<Command>() != null }
|
||||
.filter { it.findAnnotation<SavegameCrackerCommand>() != null }
|
||||
// .forEach { it.isAccessible = true; cmds[it.name] = it }
|
||||
.forEach { cmds[it.name] = it }
|
||||
}
|
||||
@@ -100,7 +100,7 @@ class SavegameCracker(
|
||||
printerrln("${args[0]}: command not found")
|
||||
else {
|
||||
try {
|
||||
val annot = it.findAnnotation<Command>()!!
|
||||
val annot = it.findAnnotation<SavegameCrackerCommand>()!!
|
||||
// check arguments
|
||||
val synopsis = annot.synopsis.split(' ').filter { it.isNotBlank() }
|
||||
// print out synopsis
|
||||
@@ -185,14 +185,14 @@ class SavegameCracker(
|
||||
return this + sb.toString()
|
||||
}
|
||||
|
||||
@Command("Loads a disk archive", "path-to-file")
|
||||
@SavegameCrackerCommand("Loads a disk archive", "path-to-file")
|
||||
fun load(args: List<String>) {
|
||||
file = File(args[1])
|
||||
disk = VDUtil.readDiskArchive(file!!, Level.INFO) { printerrln("# Warning: $it") }
|
||||
file!!.copyTo(File(file!!.absolutePath + ".bak"), true)
|
||||
}
|
||||
|
||||
@Command("Lists contents of the disk")
|
||||
@SavegameCrackerCommand("Lists contents of the disk")
|
||||
fun ls(args: List<String>) {
|
||||
letdisk {
|
||||
it.entries.toSortedMap().forEach { (i, entry) ->
|
||||
@@ -207,19 +207,19 @@ class SavegameCracker(
|
||||
}
|
||||
}
|
||||
|
||||
@Command("Prints out available commands and their usage")
|
||||
@SavegameCrackerCommand("Prints out available commands and their usage")
|
||||
fun help(args: List<String>) {
|
||||
cmds.forEach { name, it ->
|
||||
println("$ccNoun${name.padStart(8)}$cc0 - ${it.findAnnotation<Command>()!!.help}")
|
||||
println("$ccNoun${name.padStart(8)}$cc0 - ${it.findAnnotation<SavegameCrackerCommand>()!!.help}")
|
||||
}
|
||||
}
|
||||
|
||||
@Command("Exits the program")
|
||||
@SavegameCrackerCommand("Exits the program")
|
||||
fun exit(args: List<String>) { this.exit = true }
|
||||
@Command("Exits the program")
|
||||
@SavegameCrackerCommand("Exits the program")
|
||||
fun quit(args: List<String>) = exit(args)
|
||||
|
||||
@Command("Exports contents of the entry into a real file", "entry-id output-file")
|
||||
@SavegameCrackerCommand("Exports contents of the entry into a real file", "entry-id output-file")
|
||||
fun export(args: List<String>) {
|
||||
letdisk {
|
||||
val entryID = args[1].toLong(10)
|
||||
@@ -228,7 +228,7 @@ class SavegameCracker(
|
||||
}
|
||||
}
|
||||
|
||||
@Command("Changes one entry-ID into another", "change-from change-to")
|
||||
@SavegameCrackerCommand("Changes one entry-ID into another", "change-from change-to")
|
||||
fun renum(args: List<String>) {
|
||||
letdisk {
|
||||
val id0 = args[1].toLong(10)
|
||||
@@ -244,7 +244,7 @@ class SavegameCracker(
|
||||
}
|
||||
}
|
||||
|
||||
@Command("Imports a real file onto the savefile", "input-file entry-id")
|
||||
@SavegameCrackerCommand("Imports a real file onto the savefile", "input-file entry-id")
|
||||
fun import(args: List<String>) {
|
||||
letdisk {
|
||||
val file = File(args[1])
|
||||
@@ -257,7 +257,7 @@ class SavegameCracker(
|
||||
}
|
||||
}
|
||||
|
||||
@Command("Removes a file within the savefile", "entry-id")
|
||||
@SavegameCrackerCommand("Removes a file within the savefile", "entry-id")
|
||||
fun rm(args: List<String>) {
|
||||
letdisk {
|
||||
val id = args[1].toLong(10)
|
||||
@@ -266,14 +266,14 @@ class SavegameCracker(
|
||||
}
|
||||
}
|
||||
|
||||
@Command("Saves changes onto the savefile")
|
||||
@SavegameCrackerCommand("Saves changes onto the savefile")
|
||||
fun save(args: List<String>) {
|
||||
letdisk {
|
||||
VDUtil.dumpToRealMachine(it, file!!)
|
||||
}
|
||||
}
|
||||
|
||||
@Command("Retrieves all UUIDs found (player UUID, current world UUID, etc.")
|
||||
@SavegameCrackerCommand("Retrieves all UUIDs found (player UUID, current world UUID, etc.")
|
||||
fun uuid(args: List<String>) {
|
||||
letdisk {
|
||||
val jsonFile = it.getFile(-1) ?: throw FileNotFoundException("savegameinfo.json (entry ID -1) not found")
|
||||
@@ -294,7 +294,7 @@ class SavegameCracker(
|
||||
}
|
||||
}
|
||||
|
||||
@Command("Removes the specified chunk(s) completely", "IDs")
|
||||
@SavegameCrackerCommand("Removes the specified chunk(s) completely", "IDs")
|
||||
fun discardchunk(args: List<String>) {
|
||||
letdisk { disk ->
|
||||
val ids = args[1]
|
||||
@@ -320,7 +320,7 @@ class SavegameCracker(
|
||||
}
|
||||
}
|
||||
|
||||
internal annotation class Command(val help: String = "", val synopsis: String = "")
|
||||
internal annotation class SavegameCrackerCommand(val help: String = "", val synopsis: String = "")
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
SavegameCracker(args).invoke()
|
||||
|
||||
@@ -18,7 +18,6 @@ import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameparticles.createRandomBlockParticle
|
||||
import net.torvald.terrarum.gameworld.BlockAddress
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.itemproperties.Calculate
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
|
||||
@@ -5,48 +5,17 @@ import com.badlogic.gdx.utils.Disposable
|
||||
/**
|
||||
* Created by minjaesong on 2023-10-10.
|
||||
*/
|
||||
open class BlockLayer() : Disposable {
|
||||
// abstract val chunkPool: ChunkPool
|
||||
open val width: Int = 0
|
||||
open val height: Int = 0
|
||||
open val bytesPerBlock: Long = 0
|
||||
open fun unsafeToBytes(x: Int, y: Int): ByteArray = byteArrayOf(0,0,0,0)
|
||||
open fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) { }
|
||||
// for I16; other layer must throw UnsupportedOperationException
|
||||
open fun unsafeSetTile(x: Int, y: Int, tile: Int) { }
|
||||
// for I16F16; other layer must throw UnsupportedOperationException
|
||||
open fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) { }
|
||||
// for I16I8; other layer must throw UnsupportedOperationException
|
||||
open fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) { }
|
||||
interface BlockLayer : Disposable {
|
||||
|
||||
open fun unsafeGetTile(x: Int, y: Int): Int = 0
|
||||
|
||||
open fun getOffset(x: Int, y: Int): Long {
|
||||
return this.bytesPerBlock * (y * this.width + x)
|
||||
}
|
||||
|
||||
open val disposed: Boolean = false
|
||||
override fun dispose() {
|
||||
}
|
||||
|
||||
open fun unsafeGetTileI16F16(x: Int, y: Int): Pair<Int, Float> = 0 to 0f
|
||||
open fun unsafeGetTileI16I8(x: Int, y: Int): Pair<Int, Int> = 0 to 0
|
||||
|
||||
open fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) { }
|
||||
val width: Int
|
||||
val height: Int
|
||||
val bytesPerBlock: Long
|
||||
fun unsafeToBytes(x: Int, y: Int): ByteArray
|
||||
fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray)
|
||||
fun unsafeGetTile(x: Int, y: Int): Int
|
||||
|
||||
}
|
||||
|
||||
abstract class BlockLayerWithChunkPool : BlockLayer() {
|
||||
abstract val chunkPool: ChunkPool
|
||||
|
||||
/**
|
||||
* Unsupported for BlockLayerWithChunkPool
|
||||
*/
|
||||
override fun getOffset(x: Int, y: Int): Long {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
/*inline fun BlockLayer.getOffset(x: Int, y: Int): Long {
|
||||
inline fun BlockLayer.getOffset(x: Int, y: Int): Long {
|
||||
return this.bytesPerBlock * (y * this.width + x)
|
||||
}*/
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.serialise.toUint
|
||||
import net.torvald.unsafe.UnsafeHelper
|
||||
import net.torvald.unsafe.UnsafePtr
|
||||
import net.torvald.util.Float16
|
||||
|
||||
const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smaller than epsilon of float16)
|
||||
@@ -14,81 +15,97 @@ const val FLUID_MIN_MASS = 1f / 1024f //Ignore cells that are almost dry (smalle
|
||||
* * ```
|
||||
* * where a_n is a fluid number, f_n is a fluid fill
|
||||
*
|
||||
* Unsafe version Created by minjaesong on 2023-10-10.
|
||||
* Chunkpool version Created by minjaesong on 2024-10-22.
|
||||
* Created by minjaesong on 2023-10-10.
|
||||
*/
|
||||
class BlockLayerFluidI16F16 : BlockLayerWithChunkPool {
|
||||
|
||||
override val width: Int
|
||||
override val height: Int
|
||||
override val chunkPool: ChunkPool
|
||||
|
||||
constructor(
|
||||
width: Int,
|
||||
height: Int,
|
||||
disk: ClusteredFormatDOM,
|
||||
layerNum: Int,
|
||||
world: TheGameWorld
|
||||
) {
|
||||
this.width = width
|
||||
this.height = height
|
||||
|
||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
||||
}
|
||||
|
||||
constructor(
|
||||
width: Int,
|
||||
height: Int,
|
||||
disk: DiskSkimmer,
|
||||
layerNum: Int,
|
||||
world: TheGameWorld
|
||||
) {
|
||||
this.width = width
|
||||
this.height = height
|
||||
|
||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, ChunkPool.getRenameFunFluids(world))
|
||||
}
|
||||
|
||||
|
||||
class BlockLayerFluidI16F16(override val width: Int, override val height: Int) : BlockLayer {
|
||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||
|
||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
return unsafeGetTileI16F16(x, y).first
|
||||
// for some reason, all the efforts of saving the memory space were futile.
|
||||
|
||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
||||
|
||||
val ptrDestroyed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
init {
|
||||
ptr.fillWith(-1)
|
||||
}
|
||||
|
||||
override fun unsafeGetTileI16F16(x: Int, y: Int): Pair<Int, Float> {
|
||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||
return chunkPool.getTileI16F16(chunk, ox, oy)
|
||||
/**
|
||||
* @param data Byte array representation of the layer
|
||||
*/
|
||||
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||
TODO()
|
||||
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over stored bytes.
|
||||
*
|
||||
* @return an Iterator.
|
||||
*/
|
||||
fun bytesIterator(): Iterator<Byte> {
|
||||
return object : Iterator<Byte> {
|
||||
private var iteratorCount = 0L
|
||||
override fun hasNext(): Boolean {
|
||||
return iteratorCount < width * height * bytesPerBlock
|
||||
}
|
||||
override fun next(): Byte {
|
||||
iteratorCount += 1
|
||||
return ptr[iteratorCount - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
|
||||
return lsb.toUint() or msb.toUint().shl(8)
|
||||
}
|
||||
|
||||
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Float> {
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
val hbits = (ptr[offset + 2].toUint() or ptr[offset + 3].toUint().shl(8)).toShort()
|
||||
val fill = Float16.toFloat(hbits)
|
||||
|
||||
return lsb.toUint() or msb.toUint().shl(8) to fill
|
||||
}
|
||||
|
||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||
val (tile, fill0) = unsafeGetTileI16F16(x, y)
|
||||
val fill = Float16.fromFloat(fill0).toUint()
|
||||
return byteArrayOf(
|
||||
((tile ushr 8) and 255).toByte(),
|
||||
(tile and 255).toByte(),
|
||||
((fill ushr 8) and 255).toByte(),
|
||||
(fill and 255).toByte(), )
|
||||
val offset = getOffset(x, y)
|
||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 3], ptr[offset + 2])
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
internal fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
||||
val offset = getOffset(x, y)
|
||||
val hbits = Float16.fromFloat(fill).toInt().and(0xFFFF)
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
val tile = if (fill < FLUID_MIN_MASS) 0 else tile0
|
||||
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
val hlsb = hbits.and(0xff).toByte()
|
||||
val hmsb = hbits.ushr(8).and(0xff).toByte()
|
||||
|
||||
ptr[offset] = lsb
|
||||
ptr[offset + 1] = msb
|
||||
ptr[offset + 2] = hlsb
|
||||
ptr[offset + 3] = hmsb
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||
val fill = Float16.fromFloat(fill).toUint()
|
||||
chunkPool.setTileRaw(chunk, ox, oy, tile0.and(65535) or fill.shl(16))
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||
val tile = bytes[1].toUint().shl(8) or bytes[0].toUint()
|
||||
val fill = Float16.toFloat((bytes[3].toUint().shl(8) or bytes[2].toUint()).toShort())
|
||||
unsafeSetTile(x, y, tile, fill)
|
||||
val offset = getOffset(x, y)
|
||||
ptr[offset] = bytes[1]
|
||||
ptr[offset + 1] = bytes[0]
|
||||
ptr[offset + 2] = bytes[3]
|
||||
ptr[offset + 3] = bytes[2]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,18 +123,14 @@ class BlockLayerFluidI16F16 : BlockLayerWithChunkPool {
|
||||
|
||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||
|
||||
override var disposed: Boolean = false
|
||||
|
||||
override fun dispose() {
|
||||
chunkPool.dispose()
|
||||
disposed = true
|
||||
ptr.destroy()
|
||||
App.printdbg(this, "BlockLayerI16F16 with ptr ($ptr) successfully freed")
|
||||
}
|
||||
|
||||
override fun toString(): String = "BlockLayerI16F16 (${width}x$height)"
|
||||
override fun toString(): String = ptr.toString("BlockLayerI16F16")
|
||||
|
||||
companion object {
|
||||
@Transient val BYTES_PER_BLOCK = 4L
|
||||
|
||||
private fun Short.toUint() = this.toInt().and(65535)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||
import net.torvald.terrarum.serialise.toUint
|
||||
import net.torvald.unsafe.UnsafeHelper
|
||||
import net.torvald.unsafe.UnsafePtr
|
||||
|
||||
/**
|
||||
* Memory layout:
|
||||
@@ -15,89 +18,80 @@ import net.torvald.terrarum.serialise.toUint
|
||||
*
|
||||
* Original version Created by minjaesong on 2016-01-17.
|
||||
* Unsafe version Created by minjaesong on 2019-06-08.
|
||||
* Chunkpool version Created by minjaesong on 2024-10-22.
|
||||
*
|
||||
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
|
||||
*/
|
||||
class BlockLayerGenericI16: BlockLayerWithChunkPool {
|
||||
|
||||
override val width: Int
|
||||
override val height: Int
|
||||
override val chunkPool: ChunkPool
|
||||
|
||||
private var _hashcode = 0
|
||||
|
||||
constructor(
|
||||
width: Int,
|
||||
height: Int,
|
||||
disk: ClusteredFormatDOM,
|
||||
layerNum: Int,
|
||||
world: TheGameWorld
|
||||
) {
|
||||
this.width = width
|
||||
this.height = height
|
||||
|
||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, when (layerNum) {
|
||||
TERRAIN -> ChunkPool.getRenameFunTerrain(world)
|
||||
WALL -> ChunkPool.getRenameFunTerrain(world)
|
||||
else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum")
|
||||
})
|
||||
|
||||
_hashcode = disk.uuid.hashCode()
|
||||
}
|
||||
|
||||
constructor(
|
||||
width: Int,
|
||||
height: Int,
|
||||
disk: DiskSkimmer,
|
||||
layerNum: Int,
|
||||
world: TheGameWorld
|
||||
) {
|
||||
this.width = width
|
||||
this.height = height
|
||||
|
||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, -1, when (layerNum) {
|
||||
TERRAIN -> ChunkPool.getRenameFunTerrain(world)
|
||||
WALL -> ChunkPool.getRenameFunTerrain(world)
|
||||
else -> throw IllegalArgumentException("Unknown layer number for I16: $layerNum")
|
||||
})
|
||||
|
||||
_hashcode = disk.diskFile.hashCode()
|
||||
}
|
||||
|
||||
override fun hashCode() = _hashcode
|
||||
class BlockLayerGenericI16(
|
||||
override val width: Int,
|
||||
override val height: Int,
|
||||
): BlockLayer {
|
||||
|
||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||
|
||||
// for some reason, all the efforts of saving the memory space were futile.
|
||||
|
||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
||||
|
||||
val ptrDestroyed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
init {
|
||||
ptr.fillWith(-1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over stored bytes.
|
||||
*
|
||||
* @return an Iterator.
|
||||
*/
|
||||
fun bytesIterator(): Iterator<Byte> {
|
||||
return object : Iterator<Byte> {
|
||||
private var iteratorCount = 0L
|
||||
override fun hasNext(): Boolean {
|
||||
return iteratorCount < width * height * bytesPerBlock
|
||||
}
|
||||
override fun next(): Byte {
|
||||
iteratorCount += 1
|
||||
return ptr[iteratorCount - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||
return chunkPool.getTileI16(chunk, ox, oy)
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
|
||||
return lsb.toUint() or msb.toUint().shl(8)
|
||||
}
|
||||
|
||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||
val bytes = unsafeGetTile(x, y)
|
||||
return byteArrayOf(
|
||||
((bytes ushr 8) and 255).toByte(),
|
||||
(bytes and 255).toByte()
|
||||
)
|
||||
val offset = getOffset(x, y)
|
||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0])
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||
chunkPool.setTileRaw(chunk, ox, oy, tile)
|
||||
}
|
||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||
val offset = getOffset(x, y)
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
|
||||
// try {
|
||||
ptr[offset] = lsb
|
||||
ptr[offset + 1] = msb
|
||||
// }
|
||||
// catch (e: IndexOutOfBoundsException) {
|
||||
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
||||
// throw e
|
||||
// }
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||
val tile = (0..1).fold(0) { acc, i -> acc or (bytes[i].toUint()).shl(8*i) }
|
||||
unsafeSetTile(x, y, tile)
|
||||
val offset = getOffset(x, y)
|
||||
ptr[offset] = bytes[1]
|
||||
ptr[offset + 1] = bytes[0]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,14 +109,12 @@ class BlockLayerGenericI16: BlockLayerWithChunkPool {
|
||||
|
||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||
|
||||
override var disposed: Boolean = false
|
||||
|
||||
override fun dispose() {
|
||||
chunkPool.dispose()
|
||||
disposed = true
|
||||
ptr.destroy()
|
||||
printdbg(this, "BlockLayerI16 with ptr ($ptr) successfully freed")
|
||||
}
|
||||
|
||||
override fun toString(): String = "BlockLayerI16 (${width}x$height)"
|
||||
override fun toString(): String = ptr.toString("BlockLayerI16")
|
||||
|
||||
companion object {
|
||||
@Transient val BYTES_PER_BLOCK = 2L
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import com.badlogic.gdx.utils.Disposable
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||
import net.torvald.terrarum.serialise.toUint
|
||||
import net.torvald.unsafe.UnsafeHelper
|
||||
import net.torvald.unsafe.UnsafePtr
|
||||
|
||||
/**
|
||||
* Memory layout:
|
||||
* ```
|
||||
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 ||
|
||||
* ```
|
||||
* where a_n is a tile number
|
||||
*
|
||||
* Original version Created by minjaesong on 2016-01-17.
|
||||
* Unsafe version Created by minjaesong on 2019-06-08.
|
||||
*
|
||||
* Note to self: refrain from using shorts--just do away with two bytes: different system have different endianness
|
||||
*/
|
||||
class BlockLayerInMemoryI16(
|
||||
override val width: Int,
|
||||
override val height: Int,
|
||||
): BlockLayer() {
|
||||
|
||||
private constructor() : this(0, 0)
|
||||
|
||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||
|
||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
||||
|
||||
val ptrDestroyed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
init {
|
||||
ptr.fillWith(-1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over stored bytes.
|
||||
*
|
||||
* @return an Iterator.
|
||||
*/
|
||||
fun bytesIterator(): Iterator<Byte> {
|
||||
return object : Iterator<Byte> {
|
||||
private var iteratorCount = 0L
|
||||
override fun hasNext(): Boolean {
|
||||
return iteratorCount < width * height * bytesPerBlock
|
||||
}
|
||||
override fun next(): Byte {
|
||||
iteratorCount += 1
|
||||
return ptr[iteratorCount - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
|
||||
return lsb.toUint() or msb.toUint().shl(8)
|
||||
}
|
||||
|
||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||
val offset = getOffset(x, y)
|
||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0])
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||
val offset = getOffset(x, y)
|
||||
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
|
||||
// try {
|
||||
ptr[offset] = lsb
|
||||
ptr[offset + 1] = msb
|
||||
// }
|
||||
// catch (e: IndexOutOfBoundsException) {
|
||||
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
||||
// throw e
|
||||
// }
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||
val offset = getOffset(x, y)
|
||||
ptr[offset] = bytes[1]
|
||||
ptr[offset + 1] = bytes[0]
|
||||
}
|
||||
|
||||
/**
|
||||
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
||||
*/
|
||||
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
||||
val offset = BYTES_PER_BLOCK * blockOffset
|
||||
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
unsafe.putByte(layerPtr + offset, lsb)
|
||||
unsafe.putByte(layerPtr + offset + 1, msb)
|
||||
}*/
|
||||
|
||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||
|
||||
override val disposed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
override fun dispose() {
|
||||
ptr.destroy()
|
||||
printdbg(this, "BlockLayerI16 with ptr ($ptr) successfully freed")
|
||||
}
|
||||
|
||||
override fun toString(): String = ptr.toString("BlockLayerI16")
|
||||
|
||||
companion object {
|
||||
@Transient val BYTES_PER_BLOCK = 2L
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.serialise.toUint
|
||||
import net.torvald.unsafe.UnsafeHelper
|
||||
import net.torvald.unsafe.UnsafePtr
|
||||
import net.torvald.util.Float16
|
||||
|
||||
/**
|
||||
* * Memory layout:
|
||||
* * ```
|
||||
* * a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | f7 f6 f5 f4 f3 f2 f1 f0 | fF fE fD fC fB fA f9 f8 ||
|
||||
* * ```
|
||||
* * where a_n is a fluid number, f_n is a fluid fill
|
||||
*
|
||||
* Created by minjaesong on 2023-10-10.
|
||||
*/
|
||||
class BlockLayerInMemoryI16F16(override val width: Int, override val height: Int) : BlockLayer() {
|
||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||
|
||||
// for some reason, all the efforts of saving the memory space were futile.
|
||||
|
||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
||||
|
||||
val ptrDestroyed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
init {
|
||||
ptr.fillWith(-1)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data Byte array representation of the layer
|
||||
*/
|
||||
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||
TODO()
|
||||
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over stored bytes.
|
||||
*
|
||||
* @return an Iterator.
|
||||
*/
|
||||
fun bytesIterator(): Iterator<Byte> {
|
||||
return object : Iterator<Byte> {
|
||||
private var iteratorCount = 0L
|
||||
override fun hasNext(): Boolean {
|
||||
return iteratorCount < width * height * bytesPerBlock
|
||||
}
|
||||
override fun next(): Byte {
|
||||
iteratorCount += 1
|
||||
return ptr[iteratorCount - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
|
||||
return lsb.toUint() or msb.toUint().shl(8)
|
||||
}
|
||||
|
||||
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Float> {
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
val hbits = (ptr[offset + 2].toUint() or ptr[offset + 3].toUint().shl(8)).toShort()
|
||||
val fill = Float16.toFloat(hbits)
|
||||
|
||||
return lsb.toUint() or msb.toUint().shl(8) to fill
|
||||
}
|
||||
|
||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||
val offset = getOffset(x, y)
|
||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 3], ptr[offset + 2])
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile0: Int, fill: Float) {
|
||||
val offset = getOffset(x, y)
|
||||
val hbits = Float16.fromFloat(fill).toInt().and(0xFFFF)
|
||||
|
||||
val tile = if (fill < FLUID_MIN_MASS) 0 else tile0
|
||||
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
val hlsb = hbits.and(0xff).toByte()
|
||||
val hmsb = hbits.ushr(8).and(0xff).toByte()
|
||||
|
||||
ptr[offset] = lsb
|
||||
ptr[offset + 1] = msb
|
||||
ptr[offset + 2] = hlsb
|
||||
ptr[offset + 3] = hmsb
|
||||
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||
val offset = getOffset(x, y)
|
||||
ptr[offset] = bytes[1]
|
||||
ptr[offset + 1] = bytes[0]
|
||||
ptr[offset + 2] = bytes[3]
|
||||
ptr[offset + 3] = bytes[2]
|
||||
}
|
||||
|
||||
/**
|
||||
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
||||
*/
|
||||
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
||||
val offset = BYTES_PER_BLOCK * blockOffset
|
||||
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
unsafe.putByte(layerPtr + offset, lsb)
|
||||
unsafe.putByte(layerPtr + offset + 1, msb)
|
||||
}*/
|
||||
|
||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||
|
||||
override val disposed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
override fun dispose() {
|
||||
ptr.destroy()
|
||||
App.printdbg(this, "BlockLayerI16F16 with ptr ($ptr) successfully freed")
|
||||
}
|
||||
|
||||
override fun toString(): String = ptr.toString("BlockLayerI16F16")
|
||||
|
||||
companion object {
|
||||
@Transient val BYTES_PER_BLOCK = 4L
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.serialise.toUint
|
||||
import net.torvald.unsafe.UnsafeHelper
|
||||
import net.torvald.unsafe.UnsafePtr
|
||||
|
||||
/**
|
||||
* Memory layout:
|
||||
* ```
|
||||
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | p7 p6 p5 p4 p3 p2 p1 p0 ||
|
||||
* ```
|
||||
* where a_n is a tile number, p_n is a placement index
|
||||
* Created by minjaesong on 2023-10-10.
|
||||
*/
|
||||
class BlockLayerInMemoryI16I8 (override val width: Int, override val height: Int) : BlockLayer() {
|
||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||
|
||||
// for some reason, all the efforts of saving the memory space were futile.
|
||||
|
||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
||||
|
||||
val ptrDestroyed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
init {
|
||||
ptr.fillWith(0) // there is no NOT-GENERATED for ores, keep it as 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data Byte array representation of the layer
|
||||
*/
|
||||
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||
TODO()
|
||||
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over stored bytes.
|
||||
*
|
||||
* @return an Iterator.
|
||||
*/
|
||||
fun bytesIterator(): Iterator<Byte> {
|
||||
return object : Iterator<Byte> {
|
||||
private var iteratorCount = 0L
|
||||
override fun hasNext(): Boolean {
|
||||
return iteratorCount < width * height * bytesPerBlock
|
||||
}
|
||||
override fun next(): Byte {
|
||||
iteratorCount += 1
|
||||
return ptr[iteratorCount - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
val placement = ptr[offset + 2]
|
||||
|
||||
return lsb.toUint() + msb.toUint().shl(8)
|
||||
}
|
||||
|
||||
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Int> {
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
val placement = ptr[offset + 2]
|
||||
|
||||
return lsb.toUint() or msb.toUint().shl(8) to placement.toUint()
|
||||
}
|
||||
|
||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||
val offset = getOffset(x, y)
|
||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 2])
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||
val offset = getOffset(x, y)
|
||||
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
|
||||
// try {
|
||||
ptr[offset] = lsb
|
||||
ptr[offset + 1] = msb
|
||||
ptr[offset + 2] = placement.toByte()
|
||||
// }
|
||||
// catch (e: IndexOutOfBoundsException) {
|
||||
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
||||
// throw e
|
||||
// }
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||
val offset = getOffset(x, y)
|
||||
ptr[offset] = bytes[1]
|
||||
ptr[offset + 1] = bytes[0]
|
||||
ptr[offset + 2] = bytes[2]
|
||||
}
|
||||
|
||||
override fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) {
|
||||
val offset = getOffset(x, y)
|
||||
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
ptr[offset] = lsb
|
||||
ptr[offset + 1] = msb
|
||||
}
|
||||
|
||||
/**
|
||||
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
|
||||
*/
|
||||
/*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
|
||||
val offset = BYTES_PER_BLOCK * blockOffset
|
||||
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
unsafe.putByte(layerPtr + offset, lsb)
|
||||
unsafe.putByte(layerPtr + offset + 1, msb)
|
||||
}*/
|
||||
|
||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||
|
||||
override val disposed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
override fun dispose() {
|
||||
ptr.destroy()
|
||||
App.printdbg(this, "BlockLayerI16I8 with ptr ($ptr) successfully freed")
|
||||
}
|
||||
|
||||
override fun toString(): String = ptr.toString("BlockLayerI16I8")
|
||||
|
||||
companion object {
|
||||
@Transient val BYTES_PER_BLOCK = 3L
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.serialise.toUint
|
||||
import net.torvald.unsafe.UnsafeHelper
|
||||
import net.torvald.unsafe.UnsafePtr
|
||||
|
||||
/**
|
||||
* Memory layout:
|
||||
@@ -10,85 +11,105 @@ import net.torvald.terrarum.serialise.toUint
|
||||
* a7 a6 a5 a4 a3 a2 a1 a0 | aF aE aD aC aB aA a9 a8 | p7 p6 p5 p4 p3 p2 p1 p0 ||
|
||||
* ```
|
||||
* where a_n is a tile number, p_n is a placement index
|
||||
*
|
||||
* Unsafe version Created by minjaesong on 2023-10-10.
|
||||
* Chunkpool version Created by minjaesong on 2024-10-22.
|
||||
* Created by minjaesong on 2023-10-10.
|
||||
*/
|
||||
class BlockLayerOresI16I8 : BlockLayerWithChunkPool {
|
||||
|
||||
override val width: Int
|
||||
override val height: Int
|
||||
override val chunkPool: ChunkPool
|
||||
|
||||
constructor(
|
||||
width: Int,
|
||||
height: Int,
|
||||
disk: ClusteredFormatDOM,
|
||||
layerNum: Int,
|
||||
world: TheGameWorld
|
||||
) {
|
||||
this.width = width
|
||||
this.height = height
|
||||
|
||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
||||
}
|
||||
|
||||
constructor(
|
||||
width: Int,
|
||||
height: Int,
|
||||
disk: DiskSkimmer,
|
||||
layerNum: Int,
|
||||
world: TheGameWorld
|
||||
) {
|
||||
this.width = width
|
||||
this.height = height
|
||||
|
||||
chunkPool = ChunkPool(disk, layerNum, BYTES_PER_BLOCK, world, 0, ChunkPool.getRenameFunOres(world))
|
||||
}
|
||||
|
||||
|
||||
class BlockLayerOresI16I8 (override val width: Int, override val height: Int) : BlockLayer {
|
||||
override val bytesPerBlock = BYTES_PER_BLOCK
|
||||
|
||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
return unsafeGetTileI16I8(x, y).first
|
||||
// for some reason, all the efforts of saving the memory space were futile.
|
||||
|
||||
// using unsafe pointer gets you 100 fps, whereas using directbytebuffer gets you 90
|
||||
internal val ptr: UnsafePtr = UnsafeHelper.allocate(width * height * bytesPerBlock)
|
||||
|
||||
val ptrDestroyed: Boolean
|
||||
get() = ptr.destroyed
|
||||
|
||||
init {
|
||||
ptr.fillWith(0) // there is no NOT-GENERATED for ores, keep it as 0
|
||||
}
|
||||
|
||||
override fun unsafeGetTileI16I8(x: Int, y: Int): Pair<Int, Int> {
|
||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||
return chunkPool.getTileI16I8(chunk, ox, oy)
|
||||
/**
|
||||
* @param data Byte array representation of the layer
|
||||
*/
|
||||
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
|
||||
TODO()
|
||||
data.forEachIndexed { index, byte -> UnsafeHelper.unsafe.putByte(ptr.ptr + index, byte) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over stored bytes.
|
||||
*
|
||||
* @return an Iterator.
|
||||
*/
|
||||
fun bytesIterator(): Iterator<Byte> {
|
||||
return object : Iterator<Byte> {
|
||||
private var iteratorCount = 0L
|
||||
override fun hasNext(): Boolean {
|
||||
return iteratorCount < width * height * bytesPerBlock
|
||||
}
|
||||
override fun next(): Byte {
|
||||
iteratorCount += 1
|
||||
return ptr[iteratorCount - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun unsafeGetTile(x: Int, y: Int): Int {
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
val placement = ptr[offset + 2]
|
||||
|
||||
return lsb.toUint() + msb.toUint().shl(8)
|
||||
}
|
||||
|
||||
internal fun unsafeGetTile1(x: Int, y: Int): Pair<Int, Int> {
|
||||
val offset = getOffset(x, y)
|
||||
val lsb = ptr[offset]
|
||||
val msb = ptr[offset + 1]
|
||||
val placement = ptr[offset + 2]
|
||||
|
||||
return lsb.toUint() or msb.toUint().shl(8) to placement.toUint()
|
||||
}
|
||||
|
||||
override fun unsafeToBytes(x: Int, y: Int): ByteArray {
|
||||
val (tile, fill) = unsafeGetTileI16I8(x, y)
|
||||
return byteArrayOf(
|
||||
((tile ushr 8) and 255).toByte(),
|
||||
(tile and 255).toByte(),
|
||||
(fill and 255).toByte()
|
||||
)
|
||||
val offset = getOffset(x, y)
|
||||
return byteArrayOf(ptr[offset + 1], ptr[offset + 0], ptr[offset + 2])
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
internal fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||
val offset = getOffset(x, y)
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, fill: Float) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, tile: Int, placement: Int) {
|
||||
val (chunk, ox, oy) = chunkPool.worldXYChunkNumAndOffset(x, y)
|
||||
chunkPool.setTileRaw(chunk, ox, oy, tile or placement.shl(16))
|
||||
|
||||
// try {
|
||||
ptr[offset] = lsb
|
||||
ptr[offset + 1] = msb
|
||||
ptr[offset + 2] = placement.toByte()
|
||||
// }
|
||||
// catch (e: IndexOutOfBoundsException) {
|
||||
// printdbgerr(this, "IndexOutOfBoundsException: x = $x, y = $y; offset = $offset")
|
||||
// throw e
|
||||
// }
|
||||
}
|
||||
|
||||
override fun unsafeSetTile(x: Int, y: Int, bytes: ByteArray) {
|
||||
val tile = bytes[1].toUint().shl(8) or bytes[0].toUint()
|
||||
val placement = bytes[2].toUint()
|
||||
unsafeSetTile(x, y, tile, placement)
|
||||
val offset = getOffset(x, y)
|
||||
ptr[offset] = bytes[1]
|
||||
ptr[offset + 1] = bytes[0]
|
||||
ptr[offset + 2] = bytes[2]
|
||||
}
|
||||
|
||||
override fun unsafeSetTileKeepOrePlacement(x: Int, y: Int, tile: Int) {
|
||||
val oldPlacement = unsafeGetTileI16I8(x, y).second
|
||||
unsafeSetTile(x, y, tile, oldPlacement)
|
||||
internal fun unsafeSetTileKeepPlacement(x: Int, y: Int, tile: Int) {
|
||||
val offset = getOffset(x, y)
|
||||
|
||||
val lsb = tile.and(0xff).toByte()
|
||||
val msb = tile.ushr(8).and(0xff).toByte()
|
||||
|
||||
ptr[offset] = lsb
|
||||
ptr[offset + 1] = msb
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,14 +127,12 @@ class BlockLayerOresI16I8 : BlockLayerWithChunkPool {
|
||||
|
||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||
|
||||
override var disposed: Boolean = false
|
||||
|
||||
override fun dispose() {
|
||||
chunkPool.dispose()
|
||||
disposed = true
|
||||
ptr.destroy()
|
||||
App.printdbg(this, "BlockLayerI16I8 with ptr ($ptr) successfully freed")
|
||||
}
|
||||
|
||||
override fun toString(): String = "BlockLayerI16I8 (${width}x$height)"
|
||||
override fun toString(): String = ptr.toString("BlockLayerI16I8")
|
||||
|
||||
companion object {
|
||||
@Transient val BYTES_PER_BLOCK = 3L
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.torvald.terrarum.gameworld
|
||||
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.INGAME
|
||||
import net.torvald.terrarum.Point2i
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
|
||||
@@ -9,7 +8,6 @@ import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.Clustf
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
||||
import net.torvald.terrarum.savegame.ByteArray64
|
||||
import net.torvald.terrarum.savegame.DiskEntry
|
||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||
import net.torvald.terrarum.savegame.EntryFile
|
||||
@@ -37,74 +35,25 @@ enum class ChunkAllocClass {
|
||||
}
|
||||
|
||||
/**
|
||||
* WHAT IF instead of reading chunks directly from the savegame, I treat ChunkPool as a mere disk-cache?
|
||||
*
|
||||
* FIXME: loading a chunk from disk will attempt to create a chunk because the chunk-to-be-loaded
|
||||
* is not on the pointers map, and this operation will want to create a new chunk file but the file already exists
|
||||
*
|
||||
* Single layer gets single Chunk Pool.
|
||||
*
|
||||
* Created by minjaesong on 2024-09-07.
|
||||
*/
|
||||
open class ChunkPool {
|
||||
|
||||
private enum class ChunkLoadingStatus {
|
||||
LOADING_REQUESTED, RAW, LOADED_FROM_DISK, NEWLY_GENERATED
|
||||
}
|
||||
|
||||
open class ChunkPool(
|
||||
// `DiskSkimmer` or `ClusteredFormatDOM`
|
||||
private val disk: Any
|
||||
private val layerIndex: Int
|
||||
private val wordSizeInBytes: Long
|
||||
private val world: TheGameWorld
|
||||
private val initialValue: Int // bytes to fill the new chunk
|
||||
private val renumberFun: (Int) -> Int
|
||||
|
||||
private val chunkStatus = HashMap<Long, ChunkLoadingStatus>()
|
||||
val disk: Any,
|
||||
val layerIndex: Int,
|
||||
val wordSizeInBytes: Long,
|
||||
val world: GameWorld,
|
||||
val renumberFun: (Int) -> Int,
|
||||
) {
|
||||
private val pointers = TreeMap<Long, Long>()
|
||||
private var allocCap = 32
|
||||
private var allocMap = Array<ChunkAllocation?>(allocCap) { null }
|
||||
private var allocCounter = 0
|
||||
private val chunkSize: Long
|
||||
private val pool: UnsafePtr
|
||||
|
||||
constructor(
|
||||
disk: DiskSkimmer,
|
||||
layerIndex: Int,
|
||||
wordSizeInBytes: Long,
|
||||
world: TheGameWorld,
|
||||
initialValue: Int,
|
||||
renumberFun: (Int) -> Int,
|
||||
) {
|
||||
this.disk = disk
|
||||
this.layerIndex = layerIndex
|
||||
this.wordSizeInBytes = wordSizeInBytes
|
||||
this.world = world
|
||||
this.initialValue = initialValue
|
||||
this.renumberFun = renumberFun
|
||||
|
||||
chunkSize = wordSizeInBytes * CHUNK_W * CHUNK_H
|
||||
pool = UnsafeHelper.allocate(chunkSize * allocCap)
|
||||
}
|
||||
|
||||
constructor(
|
||||
disk: ClusteredFormatDOM,
|
||||
layerIndex: Int,
|
||||
wordSizeInBytes: Long,
|
||||
world: TheGameWorld,
|
||||
initialValue: Int,
|
||||
renumberFun: (Int) -> Int,
|
||||
) {
|
||||
this.disk = disk
|
||||
this.layerIndex = layerIndex
|
||||
this.wordSizeInBytes = wordSizeInBytes
|
||||
this.world = world
|
||||
this.initialValue = initialValue
|
||||
this.renumberFun = renumberFun
|
||||
|
||||
chunkSize = wordSizeInBytes * CHUNK_W * CHUNK_H
|
||||
pool = UnsafeHelper.allocate(chunkSize * allocCap)
|
||||
}
|
||||
private val chunkSize = (wordSizeInBytes * CHUNK_W * CHUNK_H)
|
||||
private val pool = UnsafeHelper.allocate(chunkSize * allocCap)
|
||||
|
||||
init {
|
||||
allocMap.fill(null)
|
||||
@@ -115,9 +64,6 @@ open class ChunkPool {
|
||||
return UnsafePtr(baseAddr, chunkSize)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer and the offset from the pointer. The offset is given in bytes, but always word-aligned (if block offset is `(2, 0)`, the returning offset will be `8`, assuming word size of 4)
|
||||
*/
|
||||
private fun createPointerViewOfChunk(chunkNumber: Long, offsetX: Int, offsetY: Int): Pair<UnsafePtr, Long> {
|
||||
val baseAddr = pointers[chunkNumber]!!
|
||||
return UnsafePtr(baseAddr, chunkSize) to wordSizeInBytes * (offsetY * CHUNK_W + offsetX)
|
||||
@@ -222,17 +168,12 @@ open class ChunkPool {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `unit` if IO operation was successful, `null` if failed (e.g. file not exists)
|
||||
*/
|
||||
private fun fetchFromDisk(chunkNumber: Long): Unit? {
|
||||
private fun fetchFromDisk(chunkNumber: Long) {
|
||||
val fileName = chunkNumToFileNum(layerIndex, chunkNumber)
|
||||
|
||||
// read data from the disk
|
||||
return if (disk is ClusteredFormatDOM) {
|
||||
val fileName = chunkNumToFileNumType17(layerIndex, chunkNumber)
|
||||
|
||||
if (disk is ClusteredFormatDOM) {
|
||||
Clustfile(disk, fileName).let {
|
||||
if (!it.exists()) return@let null
|
||||
|
||||
val bytes = Common.unzip(it.readBytes())
|
||||
val ptr = allocate(chunkNumber)
|
||||
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
||||
@@ -240,42 +181,21 @@ open class ChunkPool {
|
||||
}
|
||||
}
|
||||
else if (disk is DiskSkimmer) {
|
||||
val fileID = chunkNumToFileEntryID(layerIndex, chunkNumber)
|
||||
|
||||
disk.getFile(fileID).let {
|
||||
printdbg(this, "Reading chunk data: Layer $layerIndex Chunk $chunkNumber (fileID: $fileID), file: $it")
|
||||
|
||||
if (it == null) return@let null
|
||||
|
||||
val fileID = fileName.toLong()
|
||||
disk.getFile(fileID)!!.let {
|
||||
val bytes = Common.unzip(it.bytes)
|
||||
val ptr = allocate(chunkNumber)
|
||||
memcpyFromByteArray64ToPtr(bytes, 0L, ptr, 0L, bytes.size)
|
||||
UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size)
|
||||
renumber(ptr)
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
|
||||
private fun memcpyFromByteArray64ToPtr(ba: ByteArray64, srcIndex: Long, destPtr: UnsafePtr, destOffset: Long, copyLen: Long) {
|
||||
// TODO temporary
|
||||
val obj = ba.toByteArray()
|
||||
UnsafeHelper.memcpyFromArrToPtr(obj, srcIndex.toInt(), destPtr.ptr + destOffset, copyLen)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `unit` if IO operation was successful, `null` if failed (e.g. file not exists)
|
||||
*/
|
||||
private fun createNewChunkFile(chunkNumber: Long): Unit? {
|
||||
TODO()
|
||||
}
|
||||
|
||||
private fun storeToDisk(chunkNumber: Long) {
|
||||
val fileName = chunkNumToFileNum(layerIndex, chunkNumber)
|
||||
|
||||
// write to the disk (the disk must be an autosaving copy of the original)
|
||||
if (disk is ClusteredFormatDOM) {
|
||||
val fileName = chunkNumToFileNumType17(layerIndex, chunkNumber)
|
||||
|
||||
Clustfile(disk, fileName).let {
|
||||
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
||||
it.overwrite(bytes.toByteArray())
|
||||
@@ -283,7 +203,7 @@ open class ChunkPool {
|
||||
}
|
||||
// append the new entry
|
||||
else if (disk is DiskSkimmer) {
|
||||
val fileID = chunkNumToFileEntryID(layerIndex, chunkNumber)
|
||||
val fileID = fileName.toLong()
|
||||
|
||||
val bytes = Common.zip(serialise(chunkNumber).iterator())
|
||||
val oldEntry = disk.getEntry(fileID)
|
||||
@@ -294,7 +214,7 @@ open class ChunkPool {
|
||||
|
||||
private fun checkForChunk(chunkNumber: Long) {
|
||||
if (!pointers.containsKey(chunkNumber)) {
|
||||
fetchFromDisk(chunkNumber) ?: createNewChunkFile(chunkNumber) ?: TODO("handle IO error")
|
||||
fetchFromDisk(chunkNumber)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,19 +225,6 @@ open class ChunkPool {
|
||||
return out
|
||||
}
|
||||
|
||||
fun worldXYChunkNumAndOffset(worldx: Int, worldy: Int): Triple<Long, Int, Int> {
|
||||
val chunkX = worldx / CHUNK_W
|
||||
val chunkY = worldy / CHUNK_H
|
||||
val chunkOx = worldx % CHUNK_W
|
||||
val chunkOy = worldy % CHUNK_H
|
||||
|
||||
val chunkNum = LandUtil.chunkXYtoChunkNum(world, chunkX, chunkY)
|
||||
return Triple(chunkNum, chunkOx, chunkOy)
|
||||
}
|
||||
|
||||
private fun updateAccessTime(chunkNumber: Long) {
|
||||
allocMap.find { it?.chunkNumber == chunkNumber }!!.let { it.lastAccessTime = System.nanoTime() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
||||
@@ -328,7 +235,7 @@ open class ChunkPool {
|
||||
*/
|
||||
fun getTileRaw(chunkNumber: Long, offX: Int, offY: Int): Int {
|
||||
checkForChunk(chunkNumber)
|
||||
updateAccessTime(chunkNumber)
|
||||
allocMap.find { it?.chunkNumber == chunkNumber }!!.let { it.lastAccessTime = System.nanoTime() }
|
||||
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
||||
val numIn = (0 until wordSizeInBytes.toInt()).fold(0) { acc, off ->
|
||||
acc or (ptr[ptrOff].toUint().shl(8 * off))
|
||||
@@ -336,23 +243,6 @@ open class ChunkPool {
|
||||
return numIn
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the bytes of Int `B3_B2_B1_B0`
|
||||
* Saved as:
|
||||
* - word size is 4: `[B0, B1, B2, B3]`
|
||||
* - word size is 3: `[B0, B1, B2]` (B3 is ignored)
|
||||
* - word size is 2: `[B0, B1]` (B2 and B3 are ignored)
|
||||
*/
|
||||
fun setTileRaw(chunkNumber: Long, offX: Int, offY: Int, bytes: Int) {
|
||||
checkForChunk(chunkNumber)
|
||||
updateAccessTime(chunkNumber)
|
||||
val (ptr, ptrOff) = createPointerViewOfChunk(chunkNumber, offX, offY)
|
||||
for (i in 0 until wordSizeInBytes.toInt()) {
|
||||
val b = bytes.ushr(8*i).and(255)
|
||||
ptr[ptrOff + i] = b.toByte()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`,
|
||||
* Return format:
|
||||
@@ -390,18 +280,11 @@ open class ChunkPool {
|
||||
return ibits to jbits
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun chunkNumToFileNumType17(layerNum: Int, chunkNum: Long): String {
|
||||
fun chunkNumToFileNum(layerNum: Int, chunkNum: Long): String {
|
||||
val entryID = Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
||||
return Common.type254EntryIDtoType17Filename(entryID)
|
||||
}
|
||||
fun chunkNumToFileEntryID(layerNum: Int, chunkNum: Long): Long {
|
||||
return Common.layerAndChunkNumToEntryID(layerNum, chunkNum)
|
||||
}
|
||||
|
||||
private fun Int.get1SS() = this and 65535
|
||||
private fun Int.get2SS() = (this ushr 16) and 65535
|
||||
@@ -417,7 +300,7 @@ open class ChunkPool {
|
||||
private fun Int.get2LSB() = this.get3MSB()
|
||||
private fun Int.getLSB() = this.get4MSB()
|
||||
|
||||
fun getRenameFunTerrain(world: TheGameWorld): (Int) -> Int {
|
||||
fun getRenameFunTerrain(world: GameWorld): (Int) -> Int {
|
||||
// word size: 2
|
||||
return { oldTileNum ->
|
||||
val oldOreName = world.oldTileNumberToNameMap[oldTileNum.toLong()]
|
||||
@@ -426,7 +309,7 @@ open class ChunkPool {
|
||||
}
|
||||
}
|
||||
|
||||
fun getRenameFunOres(world: TheGameWorld): (Int) -> Int {
|
||||
fun getRenameFunOres(world: GameWorld): (Int) -> Int {
|
||||
// word size: 3
|
||||
return { oldTileNumRaw ->
|
||||
val oldOreNum = oldTileNumRaw and 0x0000FFFF
|
||||
@@ -437,7 +320,7 @@ open class ChunkPool {
|
||||
}
|
||||
}
|
||||
|
||||
fun getRenameFunFluids(world: TheGameWorld): (Int) -> Int {
|
||||
fun getRenameFunFluids(world: GameWorld): (Int) -> Int {
|
||||
// word size: 4
|
||||
return { oldTileNumRaw ->
|
||||
val oldFluidNum = oldTileNumRaw and 0x0000FFFF
|
||||
@@ -448,8 +331,7 @@ open class ChunkPool {
|
||||
}
|
||||
}
|
||||
|
||||
// this list does NOT contain `Point2i(0,0)`
|
||||
val chunkOffsetsNearPlayer = listOf(
|
||||
private val chunkOffsetsNearPlayer = listOf(
|
||||
Point2i(-1,-2), Point2i(0,-2),Point2i(1,-2),
|
||||
Point2i(-2,-1),Point2i(-1,-1),Point2i(0,-1),Point2i(1,-1),Point2i(2,-1),
|
||||
Point2i(-2,0),Point2i(-1,0),Point2i(1,0),Point2i(2,0),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,6 @@ package net.torvald.terrarum.modulebasegame
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input.Keys
|
||||
import com.badlogic.gdx.InputAdapter
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
@@ -15,14 +14,14 @@ import net.torvald.terrarum.gameactors.*
|
||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||
import net.torvald.terrarum.gameworld.*
|
||||
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIScreenZoom
|
||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||
import net.torvald.terrarum.savegame.VDUtil
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import net.torvald.terrarum.serialise.PointOfInterest
|
||||
import net.torvald.terrarum.serialise.POILayer
|
||||
@@ -62,7 +61,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
- Set…
|
||||
""".trimIndent())
|
||||
|
||||
lateinit var gameWorld: TheGameWorld
|
||||
lateinit var gameWorld: GameWorld
|
||||
|
||||
override val musicStreamer = TerrarumMusicAndAmbientStreamer()
|
||||
|
||||
@@ -420,7 +419,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
for (x in for_x_start..for_x_end) {
|
||||
if (wiringCounter >= maxRenderableWires) break
|
||||
|
||||
val (wires, nodes) = gameWorld.getAllWiresFrom(x, y)
|
||||
val (wires, nodes) = world.getAllWiresFrom(x, y)
|
||||
|
||||
wires?.forEach {
|
||||
val wireActor = wireActorsContainer[wiringCounter]
|
||||
@@ -554,7 +553,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
)
|
||||
}
|
||||
private fun getNearbyOres8(x: Int, y: Int): List<OrePlacement> {
|
||||
return getNearbyTilesPos8(x, y).map { gameWorld.getTileFromOre(it.x, it.y) }
|
||||
return getNearbyTilesPos8(x, y).map { world.getTileFromOre(it.x, it.y) }
|
||||
}
|
||||
|
||||
private fun makePenWork(x: Int, y: Int) {
|
||||
@@ -878,8 +877,8 @@ class YamlCommandToolExportTest : YamlInvokable {
|
||||
ui.world.tileNameToNumberMap
|
||||
)
|
||||
val layer = POILayer(name)
|
||||
val terr = BlockLayerInMemoryI16(poi.w, poi.h)
|
||||
val wall = BlockLayerInMemoryI16(poi.w, poi.h)
|
||||
val terr = BlockLayerGenericI16(poi.w, poi.h)
|
||||
val wall = BlockLayerGenericI16(poi.w, poi.h)
|
||||
layer.blockLayer = arrayListOf(terr, wall)
|
||||
poi.layers.add(layer)
|
||||
|
||||
@@ -935,13 +934,8 @@ class YamlCommandNewFlatTerrain : YamlInvokable {
|
||||
|
||||
println("[BuildingMaker] Generating builder world...")
|
||||
|
||||
val tempFile = FileHandle.tempFile("terrarumbuildingmaker").file()
|
||||
val tempDisk = VDUtil.createNewDisk(1L shl 30, "buildingmaker", Common.CHARSET)
|
||||
VDUtil.dumpToRealMachine(tempDisk, tempFile)
|
||||
val tempDiskSkimmer = DiskSkimmer(tempFile)
|
||||
|
||||
val timeNow = System.currentTimeMillis() / 1000
|
||||
ui.gameWorld = TheGameWorld(90*12, 90*4, tempDiskSkimmer, timeNow, timeNow)
|
||||
ui.gameWorld = GameWorld(90*12, 90*4, timeNow, timeNow)
|
||||
|
||||
// remove null tiles
|
||||
for (y in 0 until ui.gameWorld.height) {
|
||||
|
||||
@@ -4,8 +4,9 @@ import net.torvald.terrarum.BlockCodex
|
||||
import net.torvald.terrarum.ItemCodex
|
||||
import net.torvald.terrarum.OreCodex
|
||||
import net.torvald.terrarum.ceilToInt
|
||||
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
|
||||
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.getOffset
|
||||
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
|
||||
import net.torvald.unsafe.UnsafeHelper
|
||||
import java.util.concurrent.*
|
||||
@@ -33,7 +34,7 @@ object ExplosionManager {
|
||||
val lineMax = world.height - ty + CALC_RADIUS
|
||||
|
||||
// create a copy of the tilemap
|
||||
val tilemap = BlockLayerInMemoryI16(CALC_WIDTH, CALC_WIDTH)
|
||||
val tilemap = BlockLayerGenericI16(CALC_WIDTH, CALC_WIDTH)
|
||||
val breakmap = UnsafeFloatArray(CALC_WIDTH, CALC_WIDTH)
|
||||
|
||||
// fill in the tilemap copy
|
||||
@@ -68,9 +69,9 @@ object ExplosionManager {
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun memcpyFromWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerInMemoryI16) {
|
||||
private fun memcpyFromWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerGenericI16) {
|
||||
// if the bounding box must wrap around
|
||||
/*if (xStart > world.width - CALC_RADIUS) {
|
||||
if (xStart > world.width - CALC_RADIUS) {
|
||||
val lenLeft = world.width - xStart
|
||||
val lenRight = CALC_WIDTH - lenLeft
|
||||
|
||||
@@ -97,18 +98,12 @@ object ExplosionManager {
|
||||
out.getOffset(0, yOff),
|
||||
world.layerTerrain.bytesPerBlock * CALC_WIDTH
|
||||
)
|
||||
}*/
|
||||
// temporary: copy one by one
|
||||
for (ox in xStart until xStart + CALC_WIDTH) {
|
||||
val (x, y) = world.coerceXY(ox, yStart + yOff)
|
||||
val tileInWorld = world.layerTerrain.unsafeGetTile(x, y)
|
||||
out.unsafeSetTile(x, y, tileInWorld)
|
||||
}
|
||||
}
|
||||
|
||||
private fun memcpyToWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerInMemoryI16) {
|
||||
private fun memcpyToWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerGenericI16) {
|
||||
// if the bounding box must wrap around
|
||||
/*if (xStart > world.width - CALC_RADIUS) {
|
||||
if (xStart > world.width - CALC_RADIUS) {
|
||||
val lenLeft = world.width - xStart
|
||||
val lenRight = CALC_WIDTH - lenLeft
|
||||
|
||||
@@ -135,12 +130,6 @@ object ExplosionManager {
|
||||
world.layerTerrain.getOffset(xStart, yStart + yOff),
|
||||
world.layerTerrain.bytesPerBlock * CALC_WIDTH
|
||||
)
|
||||
}*/
|
||||
// temporary: copy one by one
|
||||
for (ox in xStart until xStart + CALC_WIDTH) {
|
||||
val (x, y) = world.coerceXY(ox, yStart + yOff)
|
||||
val tileInWorld = out.unsafeGetTile(x, y)
|
||||
world.layerTerrain.unsafeSetTile(x, y, tileInWorld)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +155,7 @@ object ExplosionManager {
|
||||
CALC_RADIUS: Int, CALC_WIDTH: Int,
|
||||
world: GameWorld,
|
||||
breakmap: UnsafeFloatArray,
|
||||
tilemap: BlockLayerInMemoryI16,
|
||||
tilemap: BlockLayerGenericI16,
|
||||
tx: Int, ty: Int,
|
||||
power: Float,
|
||||
dropProbNonOre: Float,
|
||||
|
||||
@@ -27,11 +27,11 @@ import net.torvald.terrarum.gameitems.GameItem
|
||||
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
import net.torvald.terrarum.modulebasegame.gameitems.ItemThrowable
|
||||
import net.torvald.terrarum.modulebasegame.gameitems.getThrowPosAndVector
|
||||
import net.torvald.terrarum.ui.BlurMgr
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||
@@ -44,6 +44,8 @@ import kotlin.math.min
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This will be rendered to a postprocessor FBO.
|
||||
*
|
||||
@@ -73,6 +75,17 @@ object IngameRenderer : Disposable {
|
||||
private lateinit var fboA_lightMixed: Float16FrameBuffer
|
||||
private lateinit var fboEmissive: Float16FrameBuffer
|
||||
private lateinit var fboMixedOut: Float16FrameBuffer
|
||||
|
||||
private lateinit var fboRGBactorsBehind: Float16FrameBuffer // for small shadow eff; A channel is for glow effects so they don't get shadow effects
|
||||
private lateinit var fboRGBactorsMiddle: Float16FrameBuffer // for large shadow eff; A channel is for glow effects so they don't get shadow effects
|
||||
private lateinit var fboRGBterrain: Float16FrameBuffer // for large shadow eff; A channel is for glow effects so they don't get shadow effects
|
||||
|
||||
private lateinit var fboRGBactorsBehindShadow: Float16FrameBuffer // for small shadow eff; A channel is for glow effects so they don't get shadow effects
|
||||
private lateinit var fboRGBactorsMiddleShadow: Float16FrameBuffer // for large shadow eff; A channel is for glow effects so they don't get shadow effects
|
||||
private lateinit var fboRGBterrainShadow: Float16FrameBuffer // for large shadow eff; A channel is for glow effects so they don't get shadow effects
|
||||
|
||||
private lateinit var fboRGBwall: Float16FrameBuffer // for masking away the shadows
|
||||
|
||||
private lateinit var rgbTex: TextureRegion
|
||||
private lateinit var aTex: TextureRegion
|
||||
private lateinit var mixedOutTex: TextureRegion
|
||||
@@ -102,6 +115,8 @@ object IngameRenderer : Disposable {
|
||||
val shaderBlendGlow: ShaderProgram
|
||||
val shaderBlendGlowTex1Flip: ShaderProgram
|
||||
val shaderForActors: ShaderProgram
|
||||
val shaderShadowShallow: ShaderProgram
|
||||
val shaderShadowDeep: ShaderProgram
|
||||
val shaderDemultiply: ShaderProgram
|
||||
|
||||
val shaderBayerAlpha: ShaderProgram
|
||||
@@ -129,7 +144,7 @@ object IngameRenderer : Disposable {
|
||||
//var renderingParticleCount = 0
|
||||
// private set
|
||||
|
||||
var world: GameWorld = TheGameWorld.makeNullWorld()
|
||||
var world: GameWorld = GameWorld.makeNullWorld()
|
||||
private set // the grammar "IngameRenderer.world = gameWorld" seemes mundane and this function needs special care!
|
||||
|
||||
private var newWorldLoadedLatch = false
|
||||
@@ -144,6 +159,8 @@ object IngameRenderer : Disposable {
|
||||
|
||||
|
||||
shaderForActors = App.loadShaderFromClasspath("shaders/default.vert", "shaders/actors.frag")
|
||||
shaderShadowShallow = App.loadShaderFromClasspath("shaders/default.vert", "shaders/shadowshallow.frag")
|
||||
shaderShadowDeep = App.loadShaderFromClasspath("shaders/default.vert", "shaders/shadowdeep.frag")
|
||||
shaderBlendGlow = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/blendGlow.frag")
|
||||
shaderBlendGlowTex1Flip = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/blendGlowTex1Flip.frag")
|
||||
shaderDemultiply = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/demultiply.frag")
|
||||
@@ -391,16 +408,11 @@ object IngameRenderer : Disposable {
|
||||
|
||||
blendNormalStraightAlpha(batch)
|
||||
|
||||
val (vo, vg) = if (world is TheGameWorld) {
|
||||
(world as TheGameWorld).weatherbox.let {
|
||||
if (it.currentWeather.identifier == "titlescreen")
|
||||
1f to 1f
|
||||
else
|
||||
it.currentVibrancy.x to it.currentVibrancy.y
|
||||
}
|
||||
}
|
||||
else {
|
||||
1f to 1f
|
||||
val (vo, vg) = world.weatherbox.let {
|
||||
if (it.currentWeather.identifier == "titlescreen")
|
||||
1f to 1f
|
||||
else
|
||||
it.currentVibrancy.x to it.currentVibrancy.y
|
||||
}
|
||||
|
||||
mixedOutTex.texture.bind(0)
|
||||
@@ -500,10 +512,9 @@ object IngameRenderer : Disposable {
|
||||
fboRGB_lightMixed0.inAction(null, null) { clearBuffer() }
|
||||
fboRGB_lightMixed.inAction(null, null) { clearBuffer() }
|
||||
|
||||
fboRGB.inAction(camera, batch) {
|
||||
|
||||
fboRGBactorsBehind.inAction(camera, batch) {
|
||||
clearBuffer()
|
||||
setCameraPosition(0f, 0f)
|
||||
BlocksDrawer.drawWall(batch.projectionMatrix, false)
|
||||
|
||||
batch.inUse {
|
||||
batch.shader = shaderForActors
|
||||
@@ -511,21 +522,103 @@ object IngameRenderer : Disposable {
|
||||
moveCameraToWorldCoord()
|
||||
actorsRenderFarBehind?.forEach { it.drawBody(frameDelta, batch) }
|
||||
actorsRenderBehind?.forEach { it.drawBody(frameDelta, batch) }
|
||||
}
|
||||
}
|
||||
BlurMgr.makeBlur(fboRGBactorsBehind, fboRGBactorsBehindShadow, 0.25f)
|
||||
|
||||
fboRGBactorsMiddle.inAction(camera, batch) {
|
||||
clearBuffer()
|
||||
setCameraPosition(0f, 0f)
|
||||
|
||||
batch.inUse {
|
||||
batch.shader = shaderForActors
|
||||
batch.color = Color.WHITE
|
||||
moveCameraToWorldCoord()
|
||||
actorsRenderMiddle?.forEach { it.drawBody(frameDelta, batch) }
|
||||
}
|
||||
}
|
||||
BlurMgr.makeBlur(fboRGBactorsMiddle, fboRGBactorsMiddleShadow, 2.5f)
|
||||
|
||||
fboRGBwall.inAction(camera, batch) {
|
||||
clearBuffer()
|
||||
setCameraPosition(0f, 0f)
|
||||
BlocksDrawer.drawWall(batch.projectionMatrix, false)
|
||||
}
|
||||
|
||||
fboRGBterrain.inAction(camera, batch) {
|
||||
clearBuffer()
|
||||
setCameraPosition(0f, 0f)
|
||||
BlocksDrawer.drawTerrain(batch.projectionMatrix, false)
|
||||
}
|
||||
BlurMgr.makeBlur(fboRGBterrain, fboRGBterrainShadow, 2.5f)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fboRGB.inAction(camera, batch) {
|
||||
setCameraPosition(0f, 0f)
|
||||
|
||||
batch.inUse {
|
||||
batch.shader = null
|
||||
batch.color = Color.WHITE
|
||||
batch.drawFlipped(fboRGBwall.colorBufferTexture, 0f, 0f)
|
||||
}
|
||||
|
||||
// draw actor shadow BEFORE the terrain draw
|
||||
fboRGBwall.colorBufferTexture.bind(1)
|
||||
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
|
||||
|
||||
batch.inUse {
|
||||
batch.shader = shaderShadowShallow
|
||||
shaderShadowShallow.setUniformi("u_wall", 1)
|
||||
setCameraPosition(0f, 0f)
|
||||
batch.drawFlipped(fboRGBactorsBehindShadow.colorBufferTexture, 0f, 0f)
|
||||
}
|
||||
|
||||
fboRGBwall.colorBufferTexture.bind(1)
|
||||
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
|
||||
|
||||
batch.inUse {
|
||||
batch.shader = shaderShadowDeep
|
||||
shaderShadowDeep.setUniformi("u_wall", 1)
|
||||
setCameraPosition(0f, 0f)
|
||||
batch.drawFlipped(fboRGBterrainShadow.colorBufferTexture, 0f, 0f)
|
||||
batch.drawFlipped(fboRGBactorsMiddleShadow.colorBufferTexture, 0f, 0f)
|
||||
}
|
||||
|
||||
// Gdx.gl20.glActiveTexture(0)
|
||||
|
||||
// draw behind actors and particles
|
||||
batch.inUse {
|
||||
batch.shader = shaderForActors
|
||||
batch.color = Color.WHITE
|
||||
|
||||
setCameraPosition(0f, 0f)
|
||||
batch.color = Color.WHITE
|
||||
batch.drawFlipped(fboRGBactorsBehind.colorBufferTexture, 0f, 0f)
|
||||
|
||||
moveCameraToWorldCoord()
|
||||
particlesContainer?.forEach { it.drawBody(frameDelta, batch) }
|
||||
}
|
||||
|
||||
setCameraPosition(0f, 0f)
|
||||
BlocksDrawer.drawTerrain(batch.projectionMatrix, false)
|
||||
// draw just the terrain
|
||||
batch.inUse {
|
||||
batch.shader = null
|
||||
setCameraPosition(0f, 0f)
|
||||
batch.color = Color.WHITE
|
||||
batch.drawFlipped(fboRGBterrain.colorBufferTexture, 0f, 0f)
|
||||
}
|
||||
|
||||
batch.shader = shaderForActors
|
||||
batch.inUse {
|
||||
batch.shader = shaderForActors
|
||||
batch.color = Color.WHITE
|
||||
/////////////////
|
||||
// draw actors //
|
||||
/////////////////
|
||||
setCameraPosition(0f, 0f)
|
||||
batch.color = Color.WHITE
|
||||
batch.drawFlipped(fboRGBactorsMiddle.colorBufferTexture, 0f, 0f)
|
||||
|
||||
moveCameraToWorldCoord()
|
||||
actorsRenderMiddle?.forEach { it.drawBody(frameDelta, batch) }
|
||||
actorsRenderMidTop?.forEach { it.drawBody(frameDelta, batch) }
|
||||
player?.drawBody(frameDelta, batch)
|
||||
actorsRenderFront?.forEach { it.drawBody(frameDelta, batch) }
|
||||
@@ -1212,6 +1305,13 @@ object IngameRenderer : Disposable {
|
||||
fboA_lightMixed = Float16FrameBuffer(width, height, false)
|
||||
fboEmissive = Float16FrameBuffer(width, height, false)
|
||||
fboMixedOut = Float16FrameBuffer(width, height, false)
|
||||
fboRGBactorsBehind = Float16FrameBuffer(width, height, false)
|
||||
fboRGBactorsMiddle = Float16FrameBuffer(width, height, false)
|
||||
fboRGBterrain = Float16FrameBuffer(width, height, false)
|
||||
fboRGBactorsBehindShadow = Float16FrameBuffer(width, height, false)
|
||||
fboRGBactorsMiddleShadow = Float16FrameBuffer(width, height, false)
|
||||
fboRGBterrainShadow = Float16FrameBuffer(width, height, false)
|
||||
fboRGBwall = Float16FrameBuffer(width, height, false)
|
||||
lightmapFbo = Float16FrameBuffer(
|
||||
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
|
||||
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
|
||||
@@ -1274,6 +1374,13 @@ object IngameRenderer : Disposable {
|
||||
if (::fboEmissive.isInitialized) fboEmissive.tryDispose()
|
||||
if (::fboMixedOut.isInitialized) fboMixedOut.tryDispose()
|
||||
if (::lightmapFbo.isInitialized) lightmapFbo.tryDispose()
|
||||
if (::fboRGBactorsBehind.isInitialized) fboRGBactorsBehind.tryDispose()
|
||||
if (::fboRGBactorsMiddle.isInitialized) fboRGBactorsMiddle.tryDispose()
|
||||
if (::fboRGBterrain.isInitialized) fboRGBterrain.tryDispose()
|
||||
if (::fboRGBactorsBehindShadow.isInitialized) fboRGBactorsBehindShadow.tryDispose()
|
||||
if (::fboRGBactorsMiddleShadow.isInitialized) fboRGBactorsMiddleShadow.tryDispose()
|
||||
if (::fboRGBterrainShadow.isInitialized) fboRGBterrainShadow.tryDispose()
|
||||
if (::fboRGBwall.isInitialized) fboRGBwall.tryDispose()
|
||||
|
||||
blurtex0.tryDispose()
|
||||
|
||||
@@ -1297,6 +1404,8 @@ object IngameRenderer : Disposable {
|
||||
shaderBlendGlow.dispose()
|
||||
shaderBlendGlowTex1Flip.dispose()
|
||||
shaderForActors.dispose()
|
||||
shaderShadowShallow.dispose()
|
||||
shaderShadowDeep.dispose()
|
||||
shaderDemultiply.dispose()
|
||||
|
||||
shaderBayerAlpha.dispose()
|
||||
|
||||
@@ -28,7 +28,6 @@ import net.torvald.terrarum.gameitems.GameItem
|
||||
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
||||
@@ -47,7 +46,6 @@ import net.torvald.terrarum.modulebasegame.worldgenerator.WorldgenParams
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_H
|
||||
import net.torvald.terrarum.realestate.LandUtil.CHUNK_W
|
||||
import net.torvald.terrarum.savegame.DiskSkimmer
|
||||
import net.torvald.terrarum.savegame.VDUtil
|
||||
import net.torvald.terrarum.savegame.VirtualDisk
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
@@ -350,7 +348,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
data class Codices(
|
||||
val disk: VirtualDisk, // WORLD disk
|
||||
val world: TheGameWorld,
|
||||
val world: GameWorld,
|
||||
// val meta: WriteMeta.WorldMeta,
|
||||
// val block: BlockCodex,
|
||||
// val item: ItemCodex,
|
||||
@@ -385,8 +383,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
|
||||
// feed info to the worldgen
|
||||
if (world is TheGameWorld)
|
||||
Worldgen.attachMap(world as TheGameWorld, WorldgenParams.getParamsByVersion(codices.worldGenver, world.generatorSeed))
|
||||
Worldgen.attachMap(world, WorldgenParams.getParamsByVersion(codices.worldGenver, world.generatorSeed))
|
||||
}
|
||||
|
||||
loadCallback = codices.callbackAfterLoad
|
||||
@@ -446,6 +443,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// try to unstuck the repositioned player
|
||||
codices.player.tryUnstuck()
|
||||
|
||||
@@ -522,18 +520,13 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
}
|
||||
else {
|
||||
App.getLoadScreen().addMessage("${App.GAME_NAME} ${App.getVERSION_STRING()}")
|
||||
|
||||
App.getLoadScreen().addMessage("Creating new world")
|
||||
|
||||
|
||||
val worldFile = getWorldSaveFiledesc(worldSavefileName)
|
||||
VDUtil.dumpToRealMachine(worldDisk, worldFile)
|
||||
val skimmer = DiskSkimmer(worldFile)
|
||||
|
||||
// init map as chosen size
|
||||
val timeNow = App.getTIME_T()
|
||||
|
||||
world = TheGameWorld(worldParams.width, worldParams.height, skimmer, timeNow, timeNow) // new game, so the creation time is right now
|
||||
|
||||
world = GameWorld(worldParams.width, worldParams.height, timeNow, timeNow) // new game, so the creation time is right now
|
||||
world.generatorSeed = worldParams.worldGenSeed
|
||||
//gameworldIndices.add(world.worldIndex)
|
||||
world.extraFields["basegame.economy"] = GameEconomy()
|
||||
|
||||
@@ -24,15 +24,18 @@ import net.torvald.terrarum.gameactors.ai.ActorAI
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||
import net.torvald.terrarum.gameparticles.ParticleBase
|
||||
import net.torvald.terrarum.gameworld.*
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.ui.UILoadGovernor
|
||||
import net.torvald.terrarum.modulebasegame.ui.UIRemoCon
|
||||
import net.torvald.terrarum.modulebasegame.ui.UITitleRemoConYaml
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.serialise.ReadTitlescreenGameWorld
|
||||
import net.torvald.terrarum.serialise.ReadSimpleWorld
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
import net.torvald.terrarum.ui.UIItemTextButton
|
||||
import net.torvald.terrarum.utils.OpenURL
|
||||
import net.torvald.terrarum.weather.WeatherMixer
|
||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||
@@ -66,7 +69,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
|
||||
//private var loadDone = false // not required; draw-while-loading is implemented in the AppLoader
|
||||
|
||||
private lateinit var demoWorld: TitlescreenGameWorld
|
||||
private lateinit var demoWorld: GameWorld
|
||||
private lateinit var cameraNodes: FloatArray // camera Y-pos
|
||||
private val cameraNodeWidth = 15
|
||||
private val lookaheadDist = cameraNodeWidth * TILE_SIZED
|
||||
@@ -162,19 +165,19 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
val file = ModMgr.getFile("basegame", "demoworld")
|
||||
val reader = java.io.FileReader(file)
|
||||
//ReadWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader)
|
||||
val world = ReadTitlescreenGameWorld(reader, file)
|
||||
val world = ReadSimpleWorld(reader, file)
|
||||
demoWorld = world
|
||||
demoWorld.worldTime.timeDelta = 30
|
||||
printdbg(this, "Demo world loaded")
|
||||
}
|
||||
catch (e: IOException) {
|
||||
demoWorld = TitlescreenGameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H)
|
||||
demoWorld = GameWorld(LandUtil.CHUNK_W, LandUtil.CHUNK_H, 0L, 0L)
|
||||
demoWorld.worldTime.timeDelta = 30
|
||||
printdbg(this, "Demo world not found, using empty world")
|
||||
}
|
||||
|
||||
this.world = demoWorld
|
||||
demoWorld.renumberTilesAfterLoad()
|
||||
this.world = demoWorld
|
||||
|
||||
// set initial time to summer
|
||||
demoWorld.worldTime.addTime(WorldTime.DAY_LENGTH * 32)
|
||||
@@ -362,7 +365,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
||||
gdxClearAndEnableBlend(.64f, .754f, .84f, 1f)
|
||||
|
||||
|
||||
if (!demoWorld.disposed) { // FIXME q&d hack to circumvent the dangling pointer issue #26
|
||||
if (!demoWorld.layerTerrain.ptr.destroyed) { // FIXME q&d hack to circumvent the dangling pointer issue #26
|
||||
WorldCamera.update(demoWorld, cameraPlayer)
|
||||
|
||||
IngameRenderer.invoke(
|
||||
|
||||
@@ -12,7 +12,6 @@ import net.torvald.terrarum.gameactors.Controllable
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame.Companion.inUpdateRange
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.*
|
||||
import net.torvald.terrarum.modulebasegame.gameitems.AxeCore
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@@ -97,7 +96,7 @@ class WorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidt
|
||||
|
||||
try {
|
||||
// q&d solution for the dangling pointer; i'm doing this only because it's this fucking load screen that's fucking the dead pointer
|
||||
if (!world.layerTerrain.disposed) {
|
||||
if (!world.layerTerrain.ptrDestroyed) {
|
||||
val outCol = if (BlockCodex[world.getTileFromTerrain(wx, wy)].isSolid) COL_TERR
|
||||
else if (BlockCodex[world.getTileFromWall(wx, wy)].isSolid) COL_WALLED
|
||||
else COL_AIR
|
||||
|
||||
142
src/net/torvald/terrarum/modulebasegame/console/ExportFBO.kt
Normal file
142
src/net/torvald/terrarum/modulebasegame/console/ExportFBO.kt
Normal file
@@ -0,0 +1,142 @@
|
||||
package net.torvald.terrarum.modulebasegame.console
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.GL20
|
||||
import com.badlogic.gdx.graphics.GL30
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.PixmapIO
|
||||
import com.badlogic.gdx.graphics.glutils.Float16FrameBuffer
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||
import com.badlogic.gdx.utils.BufferUtils
|
||||
import net.torvald.reflection.extortField
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.ccG
|
||||
import net.torvald.terrarum.ccO
|
||||
import net.torvald.terrarum.ccW
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.console.EchoError
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.unicode.BULLET
|
||||
import net.torvald.unicode.EMDASH
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.zip.Deflater
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.full.declaredFunctions
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.full.hasAnnotation
|
||||
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2024-11-24.
|
||||
*/
|
||||
internal object ExportFBO : ConsoleCommand {
|
||||
|
||||
private val cmds: HashMap<String, KFunction<*>> = HashMap()
|
||||
private val helpMessages: List<Pair<String, String>>
|
||||
|
||||
init {
|
||||
val helpMsgs: HashMap<String, String> = HashMap()
|
||||
|
||||
ExportFBO::class.declaredFunctions.filter { it.hasAnnotation<ExportFBOCmd>() }.forEach {
|
||||
cmds[it.name.lowercase()] = it
|
||||
helpMsgs[it.name.lowercase()] = it.findAnnotation<ExportFBOCmd>()!!.description
|
||||
}
|
||||
|
||||
helpMessages = helpMsgs.keys.toList().sorted().map {
|
||||
it to helpMsgs[it]!!
|
||||
}
|
||||
}
|
||||
|
||||
override fun execute(args: Array<String>) {
|
||||
if (args.size != 3) { printUsage(); return }
|
||||
val fn = cmds[args[1].lowercase()]
|
||||
if (fn == null) { printUsage(); return }
|
||||
|
||||
try {
|
||||
val filename = "${args[2]}-${args[1]}.png"
|
||||
val fileHandle = Gdx.files.absolute("${App.defaultDir}/Exports/$filename")
|
||||
|
||||
val fbo = fn.call(this) as FrameBuffer
|
||||
|
||||
// cannot use createFromFrameBuffer because the specific FBO must be bound in a way we can control
|
||||
val pixels: ByteBuffer = BufferUtils.newByteBuffer(fbo.width * fbo.height * 4)
|
||||
Gdx.gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fbo.framebufferHandle)
|
||||
Gdx.gl.glReadPixels(0, 0, fbo.width, fbo.height, GL30.GL_RGBA, GL30.GL_UNSIGNED_BYTE, pixels)
|
||||
Gdx.gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0)
|
||||
|
||||
val pixmap: Pixmap = Pixmap(fbo.width, fbo.height, Pixmap.Format.RGBA8888)
|
||||
BufferUtils.copy(pixels, pixmap.pixels, pixels.capacity())
|
||||
|
||||
PixmapIO.writePNG(fileHandle, pixmap, Deflater.DEFAULT_COMPRESSION, true)
|
||||
|
||||
Echo("Framebuffer exported to$ccG Exports/$filename")
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
EchoError("Could not retrieve the framebuffer: ${e.message}")
|
||||
System.err.println(e)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
override fun printUsage() {
|
||||
Echo("Usage: exportfbo <identifier> <filename without extension>")
|
||||
Echo("Available identifiers are:")
|
||||
|
||||
helpMessages.forEach { (name, desc) ->
|
||||
Echo(" $BULLET $ccG$name $ccW$EMDASH $ccO$desc")
|
||||
}
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Main RGB channel of the IngameRenderer without lighting")
|
||||
fun fborgb(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGB")!!
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Main A channel of the IngameRenderer without lighting")
|
||||
fun fboa(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboA")!!
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Main Emissive channel of the IngameRenderer without lighting")
|
||||
fun fboemissive(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboEmissive")!!
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Framebuffer for render-behind actors used for creating shallow shadow effects")
|
||||
fun fborgbactorsbehind(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBactorsBehind")!!
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Framebuffer for render-middle actors used for creating large shadow effects")
|
||||
fun fborgbactorsmiddle(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBactorsMiddle")!!
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Framebuffer for terrain blocks used for creating large shadow effects")
|
||||
fun fborgbterrain(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBterrain")!!
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Framebuffer for render-behind actors used for creating shallow shadow effects")
|
||||
fun fborgbactorsbehindshadow(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBactorsBehindShadow")!!
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Framebuffer for render-middle actors used for creating large shadow effects")
|
||||
fun fborgbactorsmiddleshadow(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBactorsMiddleShadow")!!
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Framebuffer for terrain blocks used for creating large shadow effects")
|
||||
fun fborgbterrainshadow(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBterrainShadow")!!
|
||||
}
|
||||
|
||||
@ExportFBOCmd("Framebuffer for wall blocks")
|
||||
fun fborgbwall(): FrameBuffer {
|
||||
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBwall")!!
|
||||
}
|
||||
}
|
||||
|
||||
internal annotation class ExportFBOCmd(val description: String)
|
||||
@@ -4,9 +4,9 @@ import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.gameworld.TitlescreenGameWorld
|
||||
import net.torvald.terrarum.gameworld.SimpleGameWorld
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.serialise.WriteTitlescreenGameWorld
|
||||
import net.torvald.terrarum.serialise.WriteSimpleWorld
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
@@ -21,12 +21,12 @@ object ExportWorld : ConsoleCommand {
|
||||
try {
|
||||
val ingame = Terrarum.ingame!! as TerrarumIngame
|
||||
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
|
||||
val simpleworld = TitlescreenGameWorld(ingame.world.width, ingame.world.height).also {
|
||||
val simpleworld = SimpleGameWorld(ingame.world.width, ingame.world.height).also {
|
||||
it.layerTerrain = ingame.world.layerTerrain
|
||||
it.layerWall = ingame.world.layerWall
|
||||
it.tileNumberToNameMap.putAll(ingame.world.tileNumberToNameMap)
|
||||
}
|
||||
file.writeText(WriteTitlescreenGameWorld(ingame, simpleworld, listOf()))
|
||||
file.writeText(WriteSimpleWorld(ingame, simpleworld, listOf()))
|
||||
Echo("Exportworld: exported the world as ${args[1]}.json")
|
||||
}
|
||||
catch (e: IOException) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.console.ConsoleCommand
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.serialise.ReadTitlescreenGameWorld
|
||||
import net.torvald.terrarum.serialise.ReadSimpleWorld
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
@@ -20,7 +20,7 @@ object ImportWorld : ConsoleCommand {
|
||||
try {
|
||||
val file = File(App.defaultDir + "/Exports/${args[1]}.json")
|
||||
val reader = java.io.FileReader(file)
|
||||
ReadTitlescreenGameWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader, file)
|
||||
ReadSimpleWorld.readWorldAndSetNewWorld(Terrarum.ingame!! as TerrarumIngame, reader, file)
|
||||
Echo("Importworld: imported a world from ${args[1]}.json")
|
||||
}
|
||||
catch (e: IOException) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.torvald.terrarum.modulebasegame.gameactors
|
||||
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.gameactors.ActorID
|
||||
import net.torvald.terrarum.gameactors.PhysProperties
|
||||
import net.torvald.terrarum.ui.UICanvas
|
||||
@@ -16,7 +17,7 @@ open class Electric : FixtureBase {
|
||||
|
||||
protected constructor() : super() {
|
||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
// newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,7 +46,7 @@ open class Electric : FixtureBase {
|
||||
App.disposables.add(mainUI)
|
||||
|
||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
// newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -137,7 +138,7 @@ open class Electric : FixtureBase {
|
||||
getWireEmissionAt(offsetX, offsetY).x <= ELECTRIC_THRESHOLD_LOW
|
||||
|
||||
protected var oldSinkStatus: Array<Vector2>
|
||||
protected var newSinkStatus: Array<Vector2>
|
||||
// protected var newSinkStatus: Array<Vector2>
|
||||
|
||||
open fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {
|
||||
val index = pointToBlockBoxIndex(offsetX, offsetY)
|
||||
@@ -149,9 +150,6 @@ open class Electric : FixtureBase {
|
||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
oldSinkStatus[index].set(new2)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,35 +165,35 @@ open class Electric : FixtureBase {
|
||||
for (x in 0 until blockBox.width) {
|
||||
// get indices of "rising edges"
|
||||
// get indices of "falling edges"
|
||||
|
||||
val wx = x + worldBlockPos!!.x
|
||||
val wy = y + worldBlockPos!!.y
|
||||
val new = WireCodex.getAllWiresThatAccepts(getWireSinkAt(x, y) ?: "").fold(Vector2()) { acc, (id, _) ->
|
||||
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
||||
}
|
||||
}
|
||||
val index = pointToBlockBoxIndex(x, y)
|
||||
val type = getWireSinkAt(index) ?: ""
|
||||
|
||||
if (new.x - oldSinkStatus[index].x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x >= ELECTRIC_THRESHOLD_HIGH)
|
||||
risingEdgeIndices.add(index)
|
||||
else if (oldSinkStatus[index].x - new.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x <= ELECTRIC_THRESHOLD_LOW)
|
||||
fallingEdgeIndices.add(index)
|
||||
if (type.isNotBlank()) {
|
||||
val old = oldSinkStatus[index]
|
||||
val new = getWireStateAt(x, y, type)
|
||||
|
||||
val wx = x + worldBlockPos!!.x
|
||||
val wy = y + worldBlockPos!!.y
|
||||
|
||||
// println("Wxy($wx,$wy) getWireState($type)=$new, oldState($type)=$old")
|
||||
|
||||
if (new.x - old.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x >= ELECTRIC_THRESHOLD_HIGH)
|
||||
risingEdgeIndices.add(index)
|
||||
else if (old.x - new.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x <= ELECTRIC_THRESHOLD_LOW)
|
||||
fallingEdgeIndices.add(index)
|
||||
|
||||
|
||||
oldSinkStatus[index].set(new)
|
||||
oldSinkStatus[index].set(new)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (risingEdgeIndices.isNotEmpty()) {
|
||||
// println("risingEdgeIndices=$risingEdgeIndices")
|
||||
// }
|
||||
|
||||
risingEdgeIndices.forEach { onRisingEdge(it) }
|
||||
fallingEdgeIndices.forEach { onFallingEdge(it) }
|
||||
updateSignal()
|
||||
|
||||
|
||||
|
||||
/*oldSinkStatus.indices.forEach { index ->
|
||||
oldSinkStatus[index].set(new)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,12 @@ import org.dyn4j.geometry.Vector2
|
||||
*/
|
||||
class FixtureLogicSignalAdder : Electric, Reorientable {
|
||||
|
||||
@Transient override val spawnNeedsFloor = true
|
||||
@Transient override val spawnNeedsFloor = false
|
||||
@Transient override val spawnNeedsWall = true
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 2, 2),
|
||||
renderOrder = RenderOrder.BEHIND,
|
||||
nameFun = { Lang["ITEM_LOGIC_SIGNAL_ADDER"] }
|
||||
)
|
||||
|
||||
|
||||
@@ -34,11 +34,12 @@ interface Reorientable {
|
||||
*/
|
||||
class FixtureLogicSignalBlocker : Electric, Reorientable {
|
||||
|
||||
@Transient override val spawnNeedsFloor = true
|
||||
@Transient override val spawnNeedsFloor = false
|
||||
@Transient override val spawnNeedsWall = true
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 2, 2),
|
||||
renderOrder = RenderOrder.BEHIND,
|
||||
nameFun = { Lang["ITEM_LOGIC_SIGNAL_BLOCKER"] }
|
||||
)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class FixtureLogicSignalBulb : Electric {
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 1, 1),
|
||||
renderOrder = RenderOrder.BEHIND,
|
||||
nameFun = { Lang["ITEM_COPPER_BULB"] }
|
||||
)
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@ import org.dyn4j.geometry.Vector2
|
||||
*/
|
||||
class FixtureLogicSignalLatch : Electric, Reorientable {
|
||||
|
||||
@Transient override val spawnNeedsFloor = true
|
||||
@Transient override val spawnNeedsFloor = false
|
||||
@Transient override val spawnNeedsWall = true
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 2, 3),
|
||||
renderOrder = RenderOrder.BEHIND,
|
||||
nameFun = { Lang["ITEM_LOGIC_SIGNAL_LATCH"] }
|
||||
)
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@ import org.dyn4j.geometry.Vector2
|
||||
class FixtureLogicSignalRepeaterHorz : Electric, Reorientable {
|
||||
|
||||
|
||||
@Transient override val spawnNeedsFloor = true
|
||||
@Transient override val spawnNeedsFloor = false
|
||||
@Transient override val spawnNeedsWall = true
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 2, 1),
|
||||
renderOrder = RenderOrder.BEHIND,
|
||||
nameFun = { Lang["ITEM_LOGIC_SIGNAL_REPEATER"] }
|
||||
)
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@ import org.dyn4j.geometry.Vector2
|
||||
*/
|
||||
class FixtureLogicSignalSwitchManual : Electric {
|
||||
|
||||
@Transient override val spawnNeedsFloor = true
|
||||
@Transient override val spawnNeedsFloor = false
|
||||
@Transient override val spawnNeedsWall = true
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 1, 1),
|
||||
renderOrder = RenderOrder.BEHIND,
|
||||
nameFun = { Lang["ITEM_LOGIC_SIGNAL_SWITCH"] }
|
||||
)
|
||||
|
||||
@@ -74,11 +75,12 @@ class FixtureLogicSignalSwitchManual : Electric {
|
||||
*/
|
||||
class FixtureLogicSignalPushbutton : Electric {
|
||||
|
||||
@Transient override val spawnNeedsFloor = true
|
||||
@Transient override val spawnNeedsFloor = false
|
||||
@Transient override val spawnNeedsWall = true
|
||||
|
||||
constructor() : super(
|
||||
BlockBox(BlockBox.NO_COLLISION, 1, 1),
|
||||
renderOrder = RenderOrder.BEHIND,
|
||||
nameFun = { Lang["ITEM_LOGIC_SIGNAL_PUSHBUTTON"] }
|
||||
)
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ class FixtureTextSignCopper : Electric {
|
||||
blockBox = BlockBox(BlockBox.NO_COLLISION, panelCount, 2)
|
||||
setHitboxDimension(TILE_SIZE * blockBox.width, TILE_SIZE * blockBox.height, 0, 2)
|
||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
// newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||
}
|
||||
|
||||
// must be re-spawned on reload to make it visible after load
|
||||
|
||||
@@ -62,10 +62,12 @@ class FixtureWorldPortal : Electric {
|
||||
}
|
||||
|
||||
override fun onRisingEdge(readFrom: BlockBoxIndex) {
|
||||
// printdbg(this, "readFrom=$readFrom; getWireSinkAt(readFrom)=${getWireSinkAt(readFrom)}")
|
||||
|
||||
if (getWireSinkAt(readFrom) != "digital_bit") return
|
||||
|
||||
|
||||
printdbg(this, "teleport! $teleportRequest")
|
||||
// printdbg(this, "teleport! $teleportRequest")
|
||||
teleportRequest?.let {
|
||||
if (it.worldDiskToLoad != null && it.worldLoadParam != null) {
|
||||
throw InternalError("Contradiction -- worldDiskToLoad and worldLoadParam are both not null: $teleportRequest")
|
||||
|
||||
@@ -9,7 +9,6 @@ import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameitems.isWall
|
||||
import net.torvald.terrarum.gameitems.mouseInInteractableRange
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package net.torvald.terrarum.modulebasegame.serialise
|
||||
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
|
||||
import net.torvald.terrarum.console.Echo
|
||||
import net.torvald.terrarum.gameworld.*
|
||||
import net.torvald.terrarum.gameworld.ChunkPool.Companion.chunkOffsetsNearPlayer
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.ORES
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||
import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16
|
||||
import net.torvald.terrarum.gameworld.BlockLayerOresI16I8
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.FancyWorldReadLoadScreen
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
@@ -16,7 +13,6 @@ import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.savegame.*
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import org.dyn4j.geometry.Vector2
|
||||
import java.io.Reader
|
||||
import java.util.logging.Level
|
||||
import kotlin.experimental.or
|
||||
@@ -64,10 +60,11 @@ object LoadSavegame {
|
||||
val worldDiskSavegameInfo = ByteArray64Reader(worldDisk.getFile(VDFileID.SAVEGAMEINFO)!!.bytes, Common.CHARSET)
|
||||
val world = ReadWorld(worldDiskSavegameInfo, worldDisk.diskFile)
|
||||
|
||||
world.layerTerrain = BlockLayerGenericI16(world.width, world.height, worldDisk, TERRAIN, world)
|
||||
world.layerWall = BlockLayerGenericI16(world.width, world.height, worldDisk, WALL, world)
|
||||
world.layerOres = BlockLayerOresI16I8(world.width, world.height, worldDisk, ORES, world)
|
||||
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height, worldDisk, FLUID, world)
|
||||
|
||||
world.layerTerrain = BlockLayerGenericI16(world.width, world.height)
|
||||
world.layerWall = BlockLayerGenericI16(world.width, world.height)
|
||||
world.layerOres = BlockLayerOresI16I8(world.width, world.height)
|
||||
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height)
|
||||
world.chunkFlags = Array(world.height / LandUtil.CHUNK_H) { ByteArray(world.width / LandUtil.CHUNK_W) }
|
||||
|
||||
newIngame.world = world // must be set before the loadscreen, otherwise the loadscreen will try to read from the NullWorld which is already destroyed
|
||||
@@ -122,24 +119,12 @@ object LoadSavegame {
|
||||
val (cx, cy) = LandUtil.chunkNumToChunkXY(world, chunk)
|
||||
|
||||
ReadWorld.decodeChunkToLayer(chunkFile.getContent(), worldLayer[layer]!!, cx, cy)
|
||||
world.chunkFlags[cy][cx] = world.chunkFlags[cy][cx] or TheGameWorld.CHUNK_LOADED
|
||||
world.chunkFlags[cy][cx] = world.chunkFlags[cy][cx] or GameWorld.CHUNK_LOADED
|
||||
}
|
||||
}
|
||||
loadscreen.progress.getAndAdd(1)
|
||||
}
|
||||
|
||||
val playerChunk = player.hitbox.canonVec.let {
|
||||
(it.x / (cw * TILE_SIZED)).toInt() to (it.y / (ch * TILE_SIZED)).toInt()
|
||||
}.let { Point2i(it.first, it.second) }
|
||||
|
||||
val chunksToLoad = chunkOffsetsNearPlayer.map {
|
||||
playerChunk + it
|
||||
} + playerChunk
|
||||
|
||||
/*for (layer in worldLayer) {
|
||||
(layer as? BlockLayerWithChunkPool)?.chunkPool?.
|
||||
}*/
|
||||
|
||||
loadscreen.addMessage(Lang["MENU_IO_LOAD_UPDATING_BLOCK_MAPPINGS"])
|
||||
world.renumberTilesAfterLoad()
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
@@ -119,7 +118,7 @@ class QuickSingleplayerWorldSavingThread(
|
||||
|
||||
// println("Chunk xy from number $chunkNumber -> (${chunkXY.x}, ${chunkXY.y})")
|
||||
|
||||
if (chunkFlag and 0x7F == TheGameWorld.CHUNK_LOADED) {
|
||||
if (chunkFlag and 0x7F == GameWorld.CHUNK_LOADED) {
|
||||
val chunkBytes = WriteWorld.encodeChunk(layer, cx, cy)
|
||||
val entryID = 0x1_0000_0000L or layerNum.toLong().shl(24) or chunkNumber.toLong()
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ package net.torvald.terrarum.modulebasegame.serialise
|
||||
|
||||
import net.torvald.gdx.graphics.PixmapIO2
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.CHUNK_LOADED
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.FLUID
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.ORES
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld.Companion.CHUNK_LOADED
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
|
||||
|
||||
@@ -5,7 +5,6 @@ import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameactors.NoSerialise
|
||||
import net.torvald.terrarum.gameworld.BlockLayer
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
|
||||
@@ -96,12 +95,12 @@ object WriteWorld {
|
||||
*/
|
||||
object ReadWorld {
|
||||
|
||||
operator fun invoke(worldDataStream: Reader, origin: File?): TheGameWorld =
|
||||
Common.jsoner.fromJson(TheGameWorld::class.java, worldDataStream).also {
|
||||
operator fun invoke(worldDataStream: Reader, origin: File?): GameWorld =
|
||||
Common.jsoner.fromJson(GameWorld::class.java, worldDataStream).also {
|
||||
fillInDetails(origin, it)
|
||||
}
|
||||
|
||||
private fun fillInDetails(origin: File?, world: TheGameWorld) {
|
||||
private fun fillInDetails(origin: File?, world: GameWorld) {
|
||||
world.tileNumberToNameMap.forEach { l, s ->
|
||||
world.tileNameToNumberMap[s] = l.toInt()
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class UICheatDetected : UICanvas() {
|
||||
Terrarum.ingame?.consoleHandler?.setAsClose()
|
||||
Terrarum.ingame?.consoleHandler?.isVisible = false
|
||||
|
||||
Toolkit.blurEntireScreen(batch, camera as OrthographicCamera, 2f, 0, 0, width, height)
|
||||
Toolkit.blurEntireScreen(batch, 2f, 0, 0, width, height)
|
||||
batch.color = backgroundCol
|
||||
Toolkit.fillArea(batch, 0f, 0f, width.toFloat(), height.toFloat())
|
||||
|
||||
@@ -80,7 +80,7 @@ class UIPauseTheGame : UICanvas() {
|
||||
Terrarum.ingame?.consoleHandler?.setAsClose()
|
||||
Terrarum.ingame?.consoleHandler?.isVisible = false
|
||||
|
||||
Toolkit.blurEntireScreen(batch, camera as OrthographicCamera, 2f, 0, 0, width, height)
|
||||
Toolkit.blurEntireScreen(batch, 2f, 0, 0, width, height)
|
||||
batch.color = backgroundCol
|
||||
Toolkit.fillArea(batch, 0f, 0f, width.toFloat(), height.toFloat())
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ class UIWorldPortalSearch(val full: UIWorldPortal) : UICanvas() {
|
||||
|
||||
|
||||
override fun show() {
|
||||
clearTooltip()
|
||||
uiItems.forEach { it.show() }
|
||||
seedInput.clearText()
|
||||
seedInput.refreshPlaceholder()
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.torvald.terrarum.serialise.toBig64
|
||||
import net.torvald.terrarum.toInt
|
||||
import net.torvald.terrarum.utils.OrePlacement
|
||||
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2023-10-26.
|
||||
|
||||
@@ -10,7 +10,6 @@ import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.BlockAddress
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.langpack.Lang
|
||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||
@@ -164,14 +163,14 @@ object Worldgen {
|
||||
val jobs = getJobs()
|
||||
printdbg(this, "Generating chunk on ($cx, $cy)")
|
||||
Thread {
|
||||
world.chunkFlags[cy][cx] = TheGameWorld.CHUNK_GENERATING
|
||||
world.chunkFlags[cy][cx] = GameWorld.CHUNK_GENERATING
|
||||
|
||||
for (i in jobs.indices) {
|
||||
val it = jobs[i]
|
||||
it.theWork.getChunkDone(cx, cy)
|
||||
}
|
||||
|
||||
world.chunkFlags[cy][cx] = TheGameWorld.CHUNK_LOADED
|
||||
world.chunkFlags[cy][cx] = GameWorld.CHUNK_LOADED
|
||||
callback(cx, cy)
|
||||
}.let {
|
||||
it.priority = 2
|
||||
@@ -567,7 +566,7 @@ abstract class Gen(val world: GameWorld, val isFinal: Boolean, val seed: Long, v
|
||||
draw(chunkX * LandUtil.CHUNK_W, chunkY * CHUNK_H, localJoise, sampleOffset)
|
||||
loadscreen?.progress?.addAndGet(1L)
|
||||
|
||||
world.chunkFlags[chunkY][chunkX] = if (isFinal) TheGameWorld.CHUNK_LOADED else TheGameWorld.CHUNK_GENERATING
|
||||
world.chunkFlags[chunkY][chunkX] = if (isFinal) GameWorld.CHUNK_LOADED else GameWorld.CHUNK_GENERATING
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,8 @@ import io.airlift.compress.zstd.ZstdOutputStream
|
||||
import net.torvald.random.HQRNG
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.console.EchoError
|
||||
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
|
||||
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
import net.torvald.terrarum.savegame.ByteArray64
|
||||
import net.torvald.terrarum.savegame.ByteArray64GrowableOutputStream
|
||||
@@ -42,7 +41,7 @@ object Common {
|
||||
val CHARSET = Charsets.UTF_8
|
||||
|
||||
/** dispose of the `offendingObject` after rejection! */
|
||||
class BlockLayerHashMismatchError(val oldHash: String, val newHash: String, val offendingObject: BlockLayerInMemoryI16) : Error("Old Hash $oldHash != New Hash $newHash")
|
||||
class BlockLayerHashMismatchError(val oldHash: String, val newHash: String, val offendingObject: BlockLayerGenericI16) : Error("Old Hash $oldHash != New Hash $newHash")
|
||||
|
||||
private fun Byte.tostr() = this.toInt().and(255).toString(16).padStart(2,'0')
|
||||
private val digester = DigestUtils.getSha256Digest()
|
||||
@@ -75,8 +74,8 @@ object Common {
|
||||
}
|
||||
})
|
||||
// BlockLayer
|
||||
it.setSerializer(BlockLayerInMemoryI16::class.java, object : Json.Serializer<BlockLayerInMemoryI16> {
|
||||
override fun write(json: Json, obj: BlockLayerInMemoryI16, knownType: Class<*>?) {
|
||||
it.setSerializer(BlockLayerGenericI16::class.java, object : Json.Serializer<BlockLayerGenericI16> {
|
||||
override fun write(json: Json, obj: BlockLayerGenericI16, knownType: Class<*>?) {
|
||||
digester.reset()
|
||||
obj.bytesIterator().forEachRemaining { digester.update(it) }
|
||||
val hash = StringBuilder().let { sb -> digester.digest().forEach { sb.append(it.tostr()) }; sb.toString() }
|
||||
@@ -86,7 +85,7 @@ object Common {
|
||||
json.writeValue(layer)
|
||||
}
|
||||
|
||||
override fun read(json: Json, jsonData: JsonValue, type: Class<*>): BlockLayerInMemoryI16 {
|
||||
override fun read(json: Json, jsonData: JsonValue, type: Class<*>): BlockLayerGenericI16 {
|
||||
// full manual
|
||||
try {
|
||||
return strToBlockLayer(LayerInfo(
|
||||
@@ -436,12 +435,12 @@ object Common {
|
||||
* @param b a BlockLayer
|
||||
* @return Bytes in [b] which are GZip'd then Ascii85-encoded
|
||||
*/
|
||||
private fun blockLayerToStr(b: BlockLayerInMemoryI16): String {
|
||||
private fun blockLayerToStr(b: BlockLayerGenericI16): String {
|
||||
return bytesToZipdStr(b.bytesIterator())
|
||||
}
|
||||
|
||||
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayerInMemoryI16 {
|
||||
val layer = BlockLayerInMemoryI16(layerInfo.x, layerInfo.y)
|
||||
private fun strToBlockLayer(layerInfo: LayerInfo): BlockLayerGenericI16 {
|
||||
val layer = BlockLayerGenericI16(layerInfo.x, layerInfo.y)
|
||||
val unzipdBytes = strToBytes(StringReader(layerInfo.b))
|
||||
|
||||
// write to blocklayer and the digester
|
||||
|
||||
@@ -6,7 +6,6 @@ import net.torvald.terrarum.TerrarumAppConfiguration
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.BlockLayerGenericI16
|
||||
import net.torvald.terrarum.gameworld.BlockLayerInMemoryI16
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.TERRAIN
|
||||
import net.torvald.terrarum.gameworld.GameWorld.Companion.WALL
|
||||
@@ -129,7 +128,7 @@ class POILayer(
|
||||
constructor() : this("undefined")
|
||||
|
||||
@Transient var name = name
|
||||
@Transient internal lateinit var blockLayer: ArrayList<BlockLayerInMemoryI16>
|
||||
@Transient internal lateinit var blockLayer: ArrayList<BlockLayerGenericI16>
|
||||
@Transient internal lateinit var dat: Array<ByteArray>
|
||||
|
||||
@Deprecated("Used for debug print", ReplaceWith("name")) @Transient internal var id = ""
|
||||
@@ -180,10 +179,10 @@ class POILayer(
|
||||
if (::blockLayer.isInitialized) {
|
||||
blockLayer.forEach { it.dispose() }
|
||||
}
|
||||
blockLayer = ArrayList()
|
||||
blockLayer = ArrayList<BlockLayerGenericI16>()
|
||||
|
||||
dat.forEachIndexed { layerIndex, layer ->
|
||||
val currentBlockLayer = BlockLayerInMemoryI16(width, height).also {
|
||||
val currentBlockLayer = BlockLayerGenericI16(width, height).also {
|
||||
blockLayer.add(it)
|
||||
}
|
||||
for (w in 0 until layer.size / byteLength) {
|
||||
|
||||
@@ -4,53 +4,56 @@ import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.IngameInstance
|
||||
import net.torvald.terrarum.ItemCodex
|
||||
import net.torvald.terrarum.gameactors.Actor
|
||||
import net.torvald.terrarum.gameworld.*
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.gameworld.BlockLayerFluidI16F16
|
||||
import net.torvald.terrarum.gameworld.BlockLayerOresI16I8
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.SimpleGameWorld
|
||||
import java.io.File
|
||||
import java.io.Reader
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2022-09-03.
|
||||
*/
|
||||
object ReadTitlescreenGameWorld {
|
||||
object ReadSimpleWorld {
|
||||
|
||||
operator fun invoke(worldDataStream: Reader, origin: File?): TitlescreenGameWorld =
|
||||
Common.jsoner.fromJson(TitlescreenGameWorld::class.java, worldDataStream).also {
|
||||
operator fun invoke(worldDataStream: Reader, origin: File?): GameWorld =
|
||||
Common.jsoner.fromJson(SimpleGameWorld::class.java, worldDataStream).also {
|
||||
fillInDetails(origin, it)
|
||||
}
|
||||
|
||||
private fun fillInDetails(origin: File?, world: TitlescreenGameWorld) {
|
||||
private fun fillInDetails(origin: File?, world: GameWorld) {
|
||||
world.tileNumberToNameMap.forEach { l, s ->
|
||||
world.tileNameToNumberMap[s] = l.toInt()
|
||||
}
|
||||
world.layerOres = BlockLayerInMemoryI16I8(world.width, world.height)
|
||||
world.layerFluids = BlockLayerInMemoryI16F16(world.width, world.height)
|
||||
world.layerOres = BlockLayerOresI16I8(world.width, world.height)
|
||||
world.layerFluids = BlockLayerFluidI16F16(world.width, world.height)
|
||||
|
||||
ItemCodex.loadFromSave(origin, world.dynamicToStaticTable, world.dynamicItemInventory)
|
||||
}
|
||||
|
||||
fun readWorldAndSetNewWorld(ingame: IngameInstance, worldDataStream: Reader, origin: File?): TitlescreenGameWorld {
|
||||
fun readWorldAndSetNewWorld(ingame: IngameInstance, worldDataStream: Reader, origin: File?): GameWorld {
|
||||
val world = invoke(worldDataStream, origin)
|
||||
ingame.world = world
|
||||
|
||||
return world
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
object WriteTitlescreenGameWorld {
|
||||
object WriteSimpleWorld {
|
||||
|
||||
private fun preWrite(ingame: IngameInstance, time_t: Long, world: TitlescreenGameWorld, actorsList: List<Actor>) {
|
||||
private fun preWrite(ingame: IngameInstance, time_t: Long, world: SimpleGameWorld, actorsList: List<Actor>) {
|
||||
val currentPlayTime_t = time_t - ingame.loadedTime_t
|
||||
|
||||
world.comp = Common.getCompIndex()
|
||||
world.lastPlayTime = time_t
|
||||
world.totalPlayTime += currentPlayTime_t
|
||||
|
||||
// world.actors.clear()
|
||||
// world.actors.addAll(actorsList.map { it.referenceID }.sorted().distinct())
|
||||
world.actors.clear()
|
||||
world.actors.addAll(actorsList.map { it.referenceID }.sorted().distinct())
|
||||
}
|
||||
|
||||
operator fun invoke(ingame: IngameInstance, world: TitlescreenGameWorld, actorsList: List<Actor>): String {
|
||||
operator fun invoke(ingame: IngameInstance, world: SimpleGameWorld, actorsList: List<Actor>): String {
|
||||
val time_t = App.getTIME_T()
|
||||
preWrite(ingame, time_t, world, actorsList)
|
||||
val s = Common.jsoner.toJson(world)
|
||||
@@ -18,7 +18,6 @@ import net.torvald.terrarum.audio.AudioMixer.Companion.DS_FLTIDX_PAN
|
||||
import net.torvald.terrarum.audio.dsp.*
|
||||
import net.torvald.terrarum.controller.TerrarumController
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.imagefont.TinyAlphNum
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
@@ -316,7 +315,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
||||
val wallNum = it.getTileFromWall(mouseTileX, mouseTileY)
|
||||
val tileNum = it.getTileFromTerrain(mouseTileX, mouseTileY)
|
||||
val (oreNum, orePlacement) = it.getTileFromOre(mouseTileX, mouseTileY)
|
||||
val wires = if (it is TheGameWorld) it.getAllWiresFrom(mouseTileX, mouseTileY) else null to null
|
||||
val wires = it.getAllWiresFrom(mouseTileX, mouseTileY)
|
||||
val fluid = it.getFluid(mouseTileX, mouseTileY)
|
||||
val wireCount = wires.first?.size?.toString() ?: "no"
|
||||
val tdmg = it.getTerrainDamage(mouseTileX, mouseTileY).toIntAndFrac(2,2)
|
||||
|
||||
159
src/net/torvald/terrarum/ui/BlurMgr.kt
Normal file
159
src/net/torvald/terrarum/ui/BlurMgr.kt
Normal file
@@ -0,0 +1,159 @@
|
||||
package net.torvald.terrarum.ui
|
||||
|
||||
import com.badlogic.gdx.graphics.*
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.glutils.Float16FrameBuffer
|
||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.ceilToInt
|
||||
import net.torvald.terrarum.gdxClearAndEnableBlend
|
||||
import net.torvald.terrarum.inAction
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2024-11-23.
|
||||
*/
|
||||
object BlurMgr {
|
||||
|
||||
private class FrameBufferSet(val width: Int, val height: Int) {
|
||||
private val internalWidth = (width.toFloat() / 4f).ceilToInt() * 4
|
||||
private val internalHeight = (height.toFloat() / 4f).ceilToInt() * 4
|
||||
|
||||
val full = Float16FrameBuffer(width, height, false)
|
||||
val half = Float16FrameBuffer(internalWidth / 2, internalHeight / 2, false)
|
||||
val quarter = Float16FrameBuffer(internalWidth / 4, internalHeight / 4, false)
|
||||
val camera = OrthographicCamera(width.toFloat(), height.toFloat())
|
||||
|
||||
val quadFull = Mesh(
|
||||
true, 4, 4,
|
||||
VertexAttribute.Position(),
|
||||
VertexAttribute.ColorUnpacked(),
|
||||
VertexAttribute.TexCoords(0)
|
||||
)
|
||||
val quadHalf = Mesh(
|
||||
true, 4, 4,
|
||||
VertexAttribute.Position(),
|
||||
VertexAttribute.ColorUnpacked(),
|
||||
VertexAttribute.TexCoords(0)
|
||||
)
|
||||
val quadQuarter = Mesh(
|
||||
true, 4, 4,
|
||||
VertexAttribute.Position(),
|
||||
VertexAttribute.ColorUnpacked(),
|
||||
VertexAttribute.TexCoords(0)
|
||||
)
|
||||
|
||||
init {
|
||||
camera.setToOrtho(true)
|
||||
|
||||
quadFull.setVertices(floatArrayOf(
|
||||
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
|
||||
width.toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
|
||||
width.toFloat(), height.toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
|
||||
0f, height.toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
|
||||
quadFull.setIndices(shortArrayOf(0, 1, 2, 3))
|
||||
|
||||
quadHalf.setVertices(floatArrayOf(
|
||||
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
|
||||
width.div(2).toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
|
||||
width.div(2).toFloat(), height.div(2).toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
|
||||
0f, height.div(2).toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
|
||||
quadHalf.setIndices(shortArrayOf(0, 1, 2, 3))
|
||||
|
||||
quadQuarter.setVertices(floatArrayOf(
|
||||
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
|
||||
width.div(4).toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
|
||||
width.div(4).toFloat(), height.div(4).toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
|
||||
0f, height.div(4).toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
|
||||
quadQuarter.setIndices(shortArrayOf(0, 1, 2, 3))
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
full.dispose()
|
||||
half.dispose()
|
||||
quarter.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
private val fboDict = HashMap<Long, FrameBufferSet>()
|
||||
|
||||
private lateinit var blurtex0: Texture
|
||||
private lateinit var blurtex1: Texture
|
||||
private lateinit var blurtex2: Texture
|
||||
private lateinit var blurtex3: Texture
|
||||
|
||||
private val shaderKawaseDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawasedown.frag")
|
||||
private val shaderKawaseUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawaseup.frag")
|
||||
|
||||
fun makeBlur(`in`: FrameBuffer, out: FrameBuffer, strength: Float) {
|
||||
assert(`in`.width == out.width && `in`.height == out.height) {
|
||||
"Input and Output dimension mismatch: In(${`in`.width}x${`in`.height}), Out(${out.width}x${out.height})"
|
||||
}
|
||||
|
||||
val fbos = fboDict.getOrPut(`in`.width.toLong().shl(32) or `in`.height.toLong()) {
|
||||
FrameBufferSet(`in`.width, `in`.height)
|
||||
}
|
||||
|
||||
val batch: SpriteBatch? = null // placeholder
|
||||
|
||||
val radius3 = FastMath.pow(strength / 2, 0.5f)//(blurRadius - 3f) / 8f
|
||||
fbos.half.inAction(fbos.camera, batch) {
|
||||
gdxClearAndEnableBlend(0f,0f,0f,0f)
|
||||
|
||||
blurtex0 = `in`.colorBufferTexture
|
||||
blurtex0.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex0.bind(0)
|
||||
shaderKawaseDown.bind()
|
||||
shaderKawaseDown.setUniformMatrix("u_projTrans", fbos.camera.combined)
|
||||
shaderKawaseDown.setUniformi("u_texture", 0)
|
||||
shaderKawaseDown.setUniformf("halfpixel", radius3 / fbos.half.width, radius3 / fbos.half.height)
|
||||
fbos.quadHalf.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
|
||||
}
|
||||
|
||||
fbos.quarter.inAction(fbos.camera, batch) {
|
||||
gdxClearAndEnableBlend(0f,0f,0f,0f)
|
||||
|
||||
blurtex1 = fbos.half.colorBufferTexture
|
||||
blurtex1.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex1.bind(0)
|
||||
shaderKawaseDown.bind()
|
||||
shaderKawaseDown.setUniformMatrix("u_projTrans", fbos.camera.combined)
|
||||
shaderKawaseDown.setUniformi("u_texture", 0)
|
||||
shaderKawaseDown.setUniformf("halfpixel", radius3 / fbos.quarter.width, radius3 / fbos.quarter.height)
|
||||
fbos.quadQuarter.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
|
||||
}
|
||||
|
||||
fbos.half.inAction(fbos.camera, batch) {
|
||||
gdxClearAndEnableBlend(0f,0f,0f,0f)
|
||||
|
||||
blurtex2 = fbos.quarter.colorBufferTexture
|
||||
blurtex2.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex2.bind(0)
|
||||
shaderKawaseUp.bind()
|
||||
shaderKawaseUp.setUniformMatrix("u_projTrans", fbos.camera.combined)
|
||||
shaderKawaseUp.setUniformi("u_texture", 0)
|
||||
shaderKawaseUp.setUniformf("halfpixel", radius3 / fbos.quarter.width, radius3 / fbos.quarter.height)
|
||||
fbos.quadHalf.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
|
||||
}
|
||||
|
||||
out.inAction(fbos.camera, batch) {
|
||||
gdxClearAndEnableBlend(0f,0f,0f,0f)
|
||||
|
||||
blurtex3 = fbos.half.colorBufferTexture
|
||||
blurtex3.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex3.bind(0)
|
||||
shaderKawaseUp.bind()
|
||||
shaderKawaseUp.setUniformMatrix("u_projTrans", fbos.camera.combined)
|
||||
shaderKawaseUp.setUniformi("u_texture", 0)
|
||||
shaderKawaseUp.setUniformf("halfpixel", radius3 / fbos.half.width, radius3 / fbos.half.height)
|
||||
fbos.quadFull.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
|
||||
}
|
||||
}
|
||||
|
||||
fun dispose() {
|
||||
fboDict.values.forEach { it.dispose() }
|
||||
shaderKawaseUp.dispose()
|
||||
shaderKawaseDown.dispose()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,12 +40,12 @@ class ConsoleWindow : UICanvas() {
|
||||
private var commandHistory = CircularArray<String>(COMMAND_HISTORY_MAX, true)
|
||||
|
||||
private val LINE_HEIGHT = 20
|
||||
private val MESSAGES_DISPLAY_COUNT = 11
|
||||
private val MESSAGES_DISPLAY_COUNT = 12
|
||||
|
||||
private val inputToMsgboxGap = 3
|
||||
|
||||
override var width: Int = App.scr.width
|
||||
override var height: Int = LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT + 1) + inputToMsgboxGap
|
||||
override var height: Int = LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT + 1) + inputToMsgboxGap + 4
|
||||
|
||||
override var openCloseTime = 0f
|
||||
|
||||
|
||||
@@ -44,19 +44,7 @@ object Toolkit : Disposable {
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
private val shaderKawaseDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawasedown.frag")
|
||||
private val shaderKawaseUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawaseup.frag")
|
||||
private val shaderBoxDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/boxdown.frag")
|
||||
private val shaderBoxUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/boxup.frag")
|
||||
|
||||
private lateinit var fboBlur: Float16FrameBuffer
|
||||
private lateinit var fboBlurHalf: Float16FrameBuffer
|
||||
private lateinit var fboBlurQuarter: Float16FrameBuffer
|
||||
private lateinit var blurWriteQuad: Mesh
|
||||
private lateinit var blurWriteQuad2: Mesh
|
||||
private lateinit var blurWriteQuad4: Mesh
|
||||
|
||||
// val baloonTile = TextureRegionPack("assets/graphics/gui/message_black_tileable.tga", 36, 36)
|
||||
val shadowTile = TextureRegionPack("assets/graphics/gui/blur_shadow.tga", 32, 32)
|
||||
@@ -82,19 +70,6 @@ object Toolkit : Disposable {
|
||||
// baloonTile.dispose()
|
||||
textureWhiteSquare.dispose()
|
||||
textureWhiteCircle.dispose()
|
||||
|
||||
fboBlur.dispose()
|
||||
fboBlurHalf.dispose()
|
||||
fboBlurQuarter.dispose()
|
||||
|
||||
blurWriteQuad.dispose()
|
||||
blurWriteQuad2.dispose()
|
||||
blurWriteQuad4.dispose()
|
||||
|
||||
shaderKawaseUp.dispose()
|
||||
shaderKawaseDown.dispose()
|
||||
shaderBoxDown.dispose()
|
||||
shaderBoxUp.dispose()
|
||||
}
|
||||
|
||||
val drawWidth: Int
|
||||
@@ -201,87 +176,11 @@ object Toolkit : Disposable {
|
||||
pixmap.fillRectangle(x + w, y, 1, h)
|
||||
}
|
||||
|
||||
private lateinit var blurtex0: Texture
|
||||
private lateinit var blurtex1: Texture
|
||||
private lateinit var blurtex2: Texture
|
||||
private lateinit var blurtex3: Texture
|
||||
|
||||
fun blurEntireScreen(batch: SpriteBatch, camera: OrthographicCamera, blurRadius0: Float, x: Int, y: Int, w: Int, h: Int) {
|
||||
fun blurEntireScreen(batch: SpriteBatch, blurRadius0: Float, x: Int, y: Int, w: Int, h: Int) {
|
||||
batch.end()
|
||||
|
||||
// val blurRadius = FastMath.pow(blurRadius0, 0.5f)
|
||||
val renderTarget = FrameBufferManager.peek()
|
||||
|
||||
//if (blurRadius > 3f) {
|
||||
val radius3 = FastMath.pow(blurRadius0 / 2, 0.5f)//(blurRadius - 3f) / 8f
|
||||
fboBlurHalf.inAction(camera, batch) {
|
||||
blurtex0 = renderTarget.colorBufferTexture
|
||||
blurtex0.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex0.bind(0)
|
||||
shaderKawaseDown.bind()
|
||||
shaderKawaseDown.setUniformMatrix("u_projTrans", camera.combined)
|
||||
shaderKawaseDown.setUniformi("u_texture", 0)
|
||||
shaderKawaseDown.setUniformf("halfpixel", radius3 / fboBlurHalf.width, radius3 / fboBlurHalf.height)
|
||||
blurWriteQuad2.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
|
||||
}
|
||||
|
||||
fboBlurQuarter.inAction(camera, batch) {
|
||||
blurtex1 = fboBlurHalf.colorBufferTexture
|
||||
blurtex1.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex1.bind(0)
|
||||
shaderKawaseDown.bind()
|
||||
shaderKawaseDown.setUniformMatrix("u_projTrans", camera.combined)
|
||||
shaderKawaseDown.setUniformi("u_texture", 0)
|
||||
shaderKawaseDown.setUniformf("halfpixel", radius3 / fboBlurQuarter.width, radius3 / fboBlurQuarter.height)
|
||||
blurWriteQuad4.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
|
||||
}
|
||||
|
||||
fboBlurHalf.inAction(camera, batch) {
|
||||
blurtex2 = fboBlurQuarter.colorBufferTexture
|
||||
blurtex2.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex2.bind(0)
|
||||
shaderKawaseUp.bind()
|
||||
shaderKawaseUp.setUniformMatrix("u_projTrans", camera.combined)
|
||||
shaderKawaseUp.setUniformi("u_texture", 0)
|
||||
shaderKawaseUp.setUniformf("halfpixel", radius3 / fboBlurQuarter.width, radius3 / fboBlurQuarter.height)
|
||||
blurWriteQuad2.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
|
||||
}
|
||||
|
||||
fboBlur.inAction(camera, batch) {
|
||||
blurtex3 = fboBlurHalf.colorBufferTexture
|
||||
blurtex3.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex3.bind(0)
|
||||
shaderKawaseUp.bind()
|
||||
shaderKawaseUp.setUniformMatrix("u_projTrans", camera.combined)
|
||||
shaderKawaseUp.setUniformi("u_texture", 0)
|
||||
shaderKawaseUp.setUniformf("halfpixel", radius3 / fboBlurHalf.width, radius3 / fboBlurHalf.height)
|
||||
blurWriteQuad.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
|
||||
}
|
||||
//}
|
||||
|
||||
/*fboBlurHalf.inAction(camera, batch) {
|
||||
blurtex2 = renderTarget.colorBufferTexture
|
||||
blurtex2.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex2.bind(0)
|
||||
shaderKawaseDown.bind()
|
||||
shaderKawaseDown.setUniformMatrix("u_projTrans", camera.combined)
|
||||
shaderKawaseDown.setUniformi("u_texture", 0)
|
||||
shaderKawaseDown.setUniformf("halfpixel", blurRadius / fboBlurHalf.width, blurRadius / fboBlurHalf.height)
|
||||
blurWriteQuad2.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
|
||||
}
|
||||
|
||||
fboBlur.inAction(camera, batch) {
|
||||
blurtex3 = fboBlurHalf.colorBufferTexture
|
||||
blurtex3.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||
blurtex3.bind(0)
|
||||
shaderKawaseUp.bind()
|
||||
shaderKawaseUp.setUniformMatrix("u_projTrans", camera.combined)
|
||||
shaderKawaseUp.setUniformi("u_texture", 0)
|
||||
shaderKawaseUp.setUniformf("halfpixel", blurRadius / fboBlurHalf.width, blurRadius / fboBlurHalf.height)
|
||||
blurWriteQuad.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
|
||||
}*/
|
||||
|
||||
|
||||
BlurMgr.makeBlur(renderTarget, fboBlur, blurRadius0)
|
||||
|
||||
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
|
||||
|
||||
@@ -344,33 +243,9 @@ object Toolkit : Disposable {
|
||||
init = true
|
||||
}
|
||||
else {
|
||||
blurWriteQuad.dispose()
|
||||
blurWriteQuad2.dispose()
|
||||
blurWriteQuad4.dispose()
|
||||
fboBlur.dispose()
|
||||
fboBlurHalf.dispose()
|
||||
fboBlurQuarter.dispose()
|
||||
}
|
||||
|
||||
blurWriteQuad = Mesh(
|
||||
true, 4, 4,
|
||||
VertexAttribute.Position(),
|
||||
VertexAttribute.ColorUnpacked(),
|
||||
VertexAttribute.TexCoords(0)
|
||||
)
|
||||
blurWriteQuad2 = Mesh(
|
||||
true, 4, 4,
|
||||
VertexAttribute.Position(),
|
||||
VertexAttribute.ColorUnpacked(),
|
||||
VertexAttribute.TexCoords(0)
|
||||
)
|
||||
blurWriteQuad4 = Mesh(
|
||||
true, 4, 4,
|
||||
VertexAttribute.Position(),
|
||||
VertexAttribute.ColorUnpacked(),
|
||||
VertexAttribute.TexCoords(0)
|
||||
)
|
||||
|
||||
val fw = App.scr.width//MathUtils.nextPowerOfTwo(App.scr.width)
|
||||
val fh = App.scr.height//MathUtils.nextPowerOfTwo(App.scr.height)
|
||||
|
||||
@@ -379,36 +254,5 @@ object Toolkit : Disposable {
|
||||
fh,
|
||||
false
|
||||
)
|
||||
fboBlurHalf = Float16FrameBuffer(
|
||||
fw / 2,
|
||||
fh / 2,
|
||||
false
|
||||
)
|
||||
fboBlurQuarter = Float16FrameBuffer(
|
||||
fw / 4,
|
||||
fh / 4,
|
||||
false
|
||||
)
|
||||
|
||||
blurWriteQuad.setVertices(floatArrayOf(
|
||||
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
|
||||
fw.toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
|
||||
fw.toFloat(), fh.toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
|
||||
0f, fh.toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
|
||||
blurWriteQuad.setIndices(shortArrayOf(0, 1, 2, 3))
|
||||
|
||||
blurWriteQuad2.setVertices(floatArrayOf(
|
||||
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
|
||||
fw.div(2).toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
|
||||
fw.div(2).toFloat(), fh.div(2).toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
|
||||
0f, fh.div(2).toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
|
||||
blurWriteQuad2.setIndices(shortArrayOf(0, 1, 2, 3))
|
||||
|
||||
blurWriteQuad4.setVertices(floatArrayOf(
|
||||
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
|
||||
fw.div(4).toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
|
||||
fw.div(4).toFloat(), fh.div(4).toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
|
||||
0f, fh.div(4).toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
|
||||
blurWriteQuad4.setIndices(shortArrayOf(0, 1, 2, 3))
|
||||
}
|
||||
}
|
||||
@@ -136,6 +136,7 @@ abstract class UICanvas(
|
||||
|
||||
/** A function that is run ONCE when the UI is requested to be opened; will work identical to [endOpening] if [openCloseTime] is zero */
|
||||
open fun show() {
|
||||
clearTooltip()
|
||||
openingClickLatched = true
|
||||
uiItems.forEach { it.show() }
|
||||
handler.subUIs.forEach { it.show() }
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package net.torvald.terrarum.utils
|
||||
|
||||
|
||||
import com.badlogic.gdx.utils.Json
|
||||
import com.badlogic.gdx.utils.JsonValue
|
||||
import net.torvald.terrarum.gameactors.ActorValue
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.BlockAddress
|
||||
|
||||
@@ -17,7 +17,9 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||
import net.torvald.terrarum.gameitems.ItemID
|
||||
import net.torvald.terrarum.gameworld.*
|
||||
import net.torvald.terrarum.gameworld.FLUID_MIN_MASS
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.fmod
|
||||
import net.torvald.terrarum.modulebasegame.worldgenerator.shake
|
||||
import net.torvald.terrarum.realestate.LandUtil
|
||||
import net.torvald.terrarum.serialise.toBig64
|
||||
@@ -41,7 +43,7 @@ import kotlin.math.roundToInt
|
||||
internal object BlocksDrawer {
|
||||
|
||||
/** World change is managed by IngameRenderer.setWorld() */
|
||||
internal var world: GameWorld = TheGameWorld.makeNullWorld()
|
||||
internal var world: GameWorld = GameWorld.makeNullWorld()
|
||||
|
||||
|
||||
/**
|
||||
@@ -276,7 +278,7 @@ internal object BlocksDrawer {
|
||||
fillInTileBuffer(TERRAIN) // regular tiles
|
||||
fillInTileBuffer(ORES)
|
||||
fillInTileBuffer(FLUID)
|
||||
fillInTileBuffer(OCCLUSION)
|
||||
// fillInTileBuffer(OCCLUSION)
|
||||
prepareDrawBuffers()
|
||||
}
|
||||
}
|
||||
@@ -287,7 +289,7 @@ internal object BlocksDrawer {
|
||||
renderUsingBuffer(WALL, projectionMatrix, drawGlow, drawEmissive)
|
||||
|
||||
gdxBlendMul()
|
||||
renderUsingBuffer(OCCLUSION, projectionMatrix, false, drawEmissive)
|
||||
// renderUsingBuffer(OCCLUSION, projectionMatrix, false, drawEmissive)
|
||||
}
|
||||
|
||||
|
||||
@@ -446,10 +448,6 @@ internal object BlocksDrawer {
|
||||
*/
|
||||
private fun fillInTileBuffer(mode: Int) {
|
||||
|
||||
// don't render fluid and ores for TitlescreenGameWorld (for now)
|
||||
if (world.layerFluids !is BlockLayerFluidI16F16) return
|
||||
if (world.layerOres !is BlockLayerOresI16I8) return
|
||||
|
||||
// TODO the real fluid rendering must use separate function, but its code should be similar to this.
|
||||
// shader's tileAtlas will be fluid.tga, pixels written to the buffer is in accordance with the new
|
||||
// atlas. IngameRenderer must be modified so that fluid-draw call is separated from drawing tiles.
|
||||
@@ -469,7 +467,7 @@ internal object BlocksDrawer {
|
||||
WALL -> world.layerWall.unsafeGetTile(wx, wy)
|
||||
TERRAIN -> world.layerTerrain.unsafeGetTile(wx, wy)
|
||||
ORES -> world.layerOres.unsafeGetTile(wx, wy)//.also { println(it) }
|
||||
FLUID -> world.layerFluids.unsafeGetTileI16F16(wx, wy).let { (number, fill) ->
|
||||
FLUID -> world.layerFluids.unsafeGetTile1(wx, wy).let { (number, fill) ->
|
||||
if (number == 65535 || fill < 1f/30f) 0
|
||||
else number
|
||||
}
|
||||
@@ -499,7 +497,7 @@ internal object BlocksDrawer {
|
||||
val nearbyFluidType = fluids.asSequence().filter { it.amount >= 0.5f / 16f }.map { it.type }.filter { it.startsWith("fluid@") }.sorted().firstOrNull()
|
||||
|
||||
val fillThis =
|
||||
world.layerFluids.unsafeGetTileI16F16(wx, wy).second.let { if (it.isNaN()) 0f else it.coerceAtMost(1f) }
|
||||
world.layerFluids.unsafeGetTile1(wx, wy).second.let { if (it.isNaN()) 0f else it.coerceAtMost(1f) }
|
||||
|
||||
val tile = world.getTileFromTerrain(wx, wy)
|
||||
|
||||
@@ -673,7 +671,7 @@ internal object BlocksDrawer {
|
||||
rawTileNum + nearbyTilesInfo
|
||||
// special case: ores
|
||||
else if (mode == ORES)
|
||||
rawTileNum + world.layerOres.unsafeGetTileI16I8(wx, wy).second
|
||||
rawTileNum + world.layerOres.unsafeGetTile1(wx, wy).second
|
||||
// rest of the cases: terrain and walls
|
||||
else rawTileNum + when (renderTag.maskType) {
|
||||
CreateTileAtlas.RenderTag.MASK_NA -> 0
|
||||
@@ -1190,7 +1188,7 @@ internal object BlocksDrawer {
|
||||
get() {
|
||||
val rate = (((Gdx.graphics.framesPerSecond / 50f) * TILE_SIZEF) / maxOf(WorldCamera.deltaX.abs(), WorldCamera.deltaY.abs()).coerceAtLeast(1)).roundToInt().coerceIn(1, 4)
|
||||
App.debugTimers.put("Renderer.tilemapUpdateDivider", rate.toLong())
|
||||
return (!world.layerTerrain.disposed && App.GLOBAL_RENDER_TIMER % rate == 0L)
|
||||
return (!world.layerTerrain.ptrDestroyed && App.GLOBAL_RENDER_TIMER % rate == 0L)
|
||||
}
|
||||
|
||||
private var camTransX = 0
|
||||
|
||||
@@ -260,7 +260,7 @@ class CreateTileAtlas {
|
||||
}
|
||||
|
||||
// test print
|
||||
PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas.tga"), atlas, false)
|
||||
// PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas.tga"), atlas, false)
|
||||
// PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasGlow.tga"), atlasGlow, false)
|
||||
|
||||
// PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas_0.tga"), atlasPrevernal, false)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package net.torvald.terrarum.worlddrawer
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.colourutil.ColourTemp
|
||||
import net.torvald.terrarum.*
|
||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
|
||||
import net.torvald.terrarum.blockproperties.Block
|
||||
import net.torvald.terrarum.blockstats.TileSurvey
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.ui.Toolkit
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@@ -15,7 +17,7 @@ import kotlin.math.roundToInt
|
||||
object FeaturesDrawer {
|
||||
|
||||
/** World change is managed by IngameRenderer.setWorld() */
|
||||
internal var world: GameWorld = TheGameWorld.makeNullWorld()
|
||||
internal var world: GameWorld = GameWorld.makeNullWorld()
|
||||
|
||||
//const val TILE_SIZE = TILE_SIZE
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import net.torvald.terrarum.gameitems.GameItem
|
||||
import net.torvald.terrarum.gameitems.isBlock
|
||||
import net.torvald.terrarum.gameworld.BlockAddress
|
||||
import net.torvald.terrarum.gameworld.GameWorld
|
||||
import net.torvald.terrarum.gameworld.TheGameWorld
|
||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||
import net.torvald.terrarum.modulebasegame.ui.abs
|
||||
@@ -44,7 +43,7 @@ import kotlin.math.*
|
||||
object LightmapRenderer {
|
||||
|
||||
/** World change is managed by IngameRenderer.setWorld() */
|
||||
private var world: GameWorld = TheGameWorld.makeNullWorld()
|
||||
private var world: GameWorld = GameWorld.makeNullWorld()
|
||||
|
||||
//private lateinit var lightCalcShader: ShaderProgram
|
||||
//private val SHADER_LIGHTING = AppLoader.getConfigBoolean("gpulightcalc")
|
||||
@@ -142,7 +141,7 @@ object LightmapRenderer {
|
||||
}
|
||||
|
||||
fun recalculate(actorContainer: List<ActorWithBody>) {
|
||||
if (!world.layerTerrain.disposed) _recalculate(actorContainer, lightmap)
|
||||
if (!world.layerTerrain.ptrDestroyed) _recalculate(actorContainer, lightmap)
|
||||
}
|
||||
|
||||
private fun _recalculate(actorContainer: List<ActorWithBody>, lightmap: UnsafeCvecArray) {
|
||||
@@ -154,7 +153,7 @@ object LightmapRenderer {
|
||||
}
|
||||
catch (e: NullPointerException) {
|
||||
System.err.println("[LightmapRendererNew.recalculate] Attempted to refer destroyed unsafe array " +
|
||||
"(${world.layerTerrain})")
|
||||
"(${world.layerTerrain.ptr})")
|
||||
e.printStackTrace()
|
||||
return // something's wrong but we'll ignore it like a trustful AK
|
||||
}
|
||||
@@ -657,7 +656,7 @@ object LightmapRenderer {
|
||||
|
||||
internal fun draw(): Texture {
|
||||
|
||||
if (!world.layerTerrain.disposed) {
|
||||
if (!world.layerTerrain.ptrDestroyed) {
|
||||
// when shader is not used: 0.5 ms on 6700K
|
||||
App.measureDebugTime("Renderer.LightToScreen") {
|
||||
|
||||
|
||||
20
src/shaders/shadowdeep.frag
Normal file
20
src/shaders/shadowdeep.frag
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
in vec4 v_color;
|
||||
in vec4 v_generic;
|
||||
in vec2 v_texCoords;
|
||||
uniform sampler2D u_texture;
|
||||
uniform sampler2D u_wall;
|
||||
out vec4 fragColor;
|
||||
|
||||
vec4 mult = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
void main() {
|
||||
vec4 backcol = texture(u_wall, v_texCoords);
|
||||
vec4 incol = texture(u_texture, v_texCoords);
|
||||
vec4 outcol = vec4(incol.rgb, backcol.a * pow(incol.a, 1.4142));
|
||||
fragColor = mult * outcol;
|
||||
}
|
||||
20
src/shaders/shadowshallow.frag
Normal file
20
src/shaders/shadowshallow.frag
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
in vec4 v_color;
|
||||
in vec4 v_generic;
|
||||
in vec2 v_texCoords;
|
||||
uniform sampler2D u_texture;
|
||||
uniform sampler2D u_wall;
|
||||
out vec4 fragColor;
|
||||
|
||||
vec4 mult = vec4(0.0, 0.0, 0.0, 1.4142);
|
||||
|
||||
void main() {
|
||||
vec4 backcol = texture(u_wall, v_texCoords);
|
||||
vec4 incol = texture(u_texture, v_texCoords);
|
||||
vec4 outcol = vec4(incol.rgb, backcol.a * pow(incol.a, 2.0));
|
||||
fragColor = mult * outcol;
|
||||
}
|
||||
Reference in New Issue
Block a user