diff --git a/.idea/artifacts/TerrarumBuild.xml b/.idea/artifacts/TerrarumBuild.xml index e5ea8e246..92f057a0f 100644 --- a/.idea/artifacts/TerrarumBuild.xml +++ b/.idea/artifacts/TerrarumBuild.xml @@ -46,7 +46,6 @@ - diff --git a/.idea/libraries/com_google_code_gson_gson_2_8_7.xml b/.idea/libraries/com_google_code_gson_gson_2_8_7.xml deleted file mode 100644 index ff204fce5..000000000 --- a/.idea/libraries/com_google_code_gson_gson_2_8_7.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build.gradle b/build.gradle index f25fbb93c..a8ad65539 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.3.72' + ext.kotlin_version = '1.5.21' repositories { mavenCentral() @@ -14,6 +14,9 @@ apply plugin: 'java' apply plugin: 'application' apply plugin: 'idea' apply plugin: 'kotlin' +plugins { + kotlin("plugin.serialization") version "1.5.21" +} sourceSets.main.java.srcDirs = ['src'] // because I'm not setting up proper /src/main/java/... @@ -31,6 +34,7 @@ dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib" compile fileTree(dir: 'lib', include: ['*.jar']) implementation 'org.junit:junit-bom:5.2.0' + implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0' } compileKotlin { diff --git a/ingamemodule_basegame/ingamemodule_basegame.iml b/ingamemodule_basegame/ingamemodule_basegame.iml index cd8dbc66b..4c0d19460 100644 --- a/ingamemodule_basegame/ingamemodule_basegame.iml +++ b/ingamemodule_basegame/ingamemodule_basegame.iml @@ -11,7 +11,6 @@ - @@ -20,7 +19,6 @@ - diff --git a/lib/gson-2.8.7-javadoc.jar b/lib/gson-2.8.7-javadoc.jar deleted file mode 100644 index 7b2ba6406..000000000 Binary files a/lib/gson-2.8.7-javadoc.jar and /dev/null differ diff --git a/lib/gson-2.8.7-sources.jar b/lib/gson-2.8.7-sources.jar deleted file mode 100644 index 116bf95b5..000000000 Binary files a/lib/gson-2.8.7-sources.jar and /dev/null differ diff --git a/lib/gson-2.8.7.jar b/lib/gson-2.8.7.jar deleted file mode 100644 index 215e82328..000000000 Binary files a/lib/gson-2.8.7.jar and /dev/null differ diff --git a/lib/kotlin-stdlib-sources.jar b/lib/kotlin-stdlib-sources.jar deleted file mode 100644 index acb8ff171..000000000 Binary files a/lib/kotlin-stdlib-sources.jar and /dev/null differ diff --git a/src/module-info.java.wtf b/src/module-info.java.wtf index b9d1df39e..f0af35259 100644 --- a/src/module-info.java.wtf +++ b/src/module-info.java.wtf @@ -5,7 +5,6 @@ module terrarum.terrarum { requires jdk.unsupported; // sun.misc.Unsafe // kotlin - requires kotlin.stdlib; requires kotlin.test; // gdx @@ -22,7 +21,9 @@ module terrarum.terrarum { // etc requires GetCpuName; - requires com.google.gson; + requires kotlinx.serialization.core.jvm; + requires kotlinx.serialization.json; + requires kotlinx.serialization.json.jvm; requires org.apache.commons.codec; requires commons.csv; requires jxinput; diff --git a/src/net/torvald/parametricsky/datasets/DatasetOp.kt b/src/net/torvald/parametricsky/datasets/DatasetOp.kt index 2be469357..eb9aa3e8e 100644 --- a/src/net/torvald/parametricsky/datasets/DatasetOp.kt +++ b/src/net/torvald/parametricsky/datasets/DatasetOp.kt @@ -21,4 +21,6 @@ object DatasetOp { fis.close() return ret } + + } \ No newline at end of file diff --git a/src/net/torvald/terrarum/AppLoader.java b/src/net/torvald/terrarum/AppLoader.java index efa46714b..ae2922b59 100644 --- a/src/net/torvald/terrarum/AppLoader.java +++ b/src/net/torvald/terrarum/AppLoader.java @@ -12,12 +12,9 @@ import com.badlogic.gdx.graphics.glutils.FrameBuffer; import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.utils.Disposable; -import com.badlogic.gdx.utils.GdxRuntimeException; +import com.badlogic.gdx.utils.JsonValue; import com.badlogic.gdx.utils.ScreenUtils; import com.github.strikerx3.jxinput.XInputDevice; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; import net.torvald.gdx.graphics.PixmapIO2; import net.torvald.getcpuname.GetCpuName; import net.torvald.terrarum.concurrent.ThreadExecutor; @@ -37,18 +34,10 @@ import net.torvald.terrarum.utils.JsonWriter; import net.torvald.terrarum.worlddrawer.CreateTileAtlas; import net.torvald.terrarumsansbitmap.gdx.GameFontBase; import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack; -import net.torvald.util.ArrayListMap; import net.torvald.util.DebugTimers; -import org.lwjgl.opengl.GL11; - import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Random; - -import static net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED; +import java.util.*; import static net.torvald.terrarum.TerrarumKt.gdxClearAndSetBlend; import static net.torvald.terrarum.TerrarumKt.printStackTrace; @@ -973,7 +962,7 @@ public class AppLoader implements ApplicationListener { File configFile = new File(configDir); if (!configFile.exists() || configFile.length() == 0L) { - JsonWriter.INSTANCE.writeToFile(DefaultConfig.INSTANCE.fetch(), configDir); + JsonWriter.INSTANCE.writeToFile(DefaultConfig.INSTANCE.getHashMap(), configDir); } } @@ -984,12 +973,18 @@ public class AppLoader implements ApplicationListener { private static Boolean readConfigJson() { try { // read from disk and build config from it - JsonObject jsonObject = JsonFetcher.INSTANCE.invoke(configDir); + JsonValue map = JsonFetcher.INSTANCE.invoke(configDir); // make config - jsonObject.entrySet().forEach((entry) -> - gameConfig.set(entry.getKey(), entry.getValue()) - ); + for (JsonValue entry = map.child; entry != null; entry = entry.next) { + gameConfig.set(entry.name, + entry.isArray() ? entry.asDoubleArray() : + entry.isDouble() ? entry.asDouble() : + entry.isBoolean() ? entry.asBoolean() : + entry.isLong() ? entry.asInt() : + entry.asString() + ); + } return true; } @@ -1018,10 +1013,7 @@ public class AppLoader implements ApplicationListener { */ public static int getConfigInt(String key) { Object cfg = getConfigMaster(key); - if (cfg instanceof JsonPrimitive) - return ((JsonPrimitive) cfg).getAsInt(); - else - return Integer.parseInt(((String) cfg)); + return ((int) cfg); } /** @@ -1034,10 +1026,7 @@ public class AppLoader implements ApplicationListener { */ public static String getConfigString(String key) { Object cfg = getConfigMaster(key); - if (cfg instanceof JsonPrimitive) - return ((JsonPrimitive) cfg).getAsString(); - else - return ((String) cfg); + return ((String) cfg); } /** @@ -1049,17 +1038,14 @@ public class AppLoader implements ApplicationListener { public static boolean getConfigBoolean(String key) { try { Object cfg = getConfigMaster(key); - if (cfg instanceof JsonPrimitive) - return ((JsonPrimitive) cfg).getAsBoolean(); - else - return ((boolean) cfg); + return ((boolean) cfg); } catch (NullPointerException keyNotFound) { return false; } } - public static int[] getConfigIntArray(String key) { + /*public static int[] getConfigIntArray(String key) { Object cfg = getConfigMaster(key); if (cfg instanceof JsonArray) { JsonArray jsonArray = ((JsonArray) cfg).getAsJsonArray(); @@ -1072,24 +1058,23 @@ public class AppLoader implements ApplicationListener { } else return ((int[]) cfg); - } + }*/ - public static float[] getConfigFloatArray(String key) { + public static double[] getConfigDoubleArray(String key) { Object cfg = getConfigMaster(key); - if (cfg instanceof JsonArray) { - JsonArray jsonArray = ((JsonArray) cfg).getAsJsonArray(); - //return IntArray(jsonArray.size(), { i -> jsonArray[i].asInt }) - float[] floatArray = new float[jsonArray.size()]; - for (int i = 0; i < jsonArray.size(); i++) { - floatArray[i] = jsonArray.get(i).getAsInt(); - } - return floatArray; - } - else - return ((float[]) cfg); + return ((double[]) cfg); } - public static String[] getConfigStringArray(String key) { + public static int[] getConfigIntArray(String key) { + double[] a = getConfigDoubleArray(key); + int[] r = new int[a.length]; + for (int i = 0; i < a.length; i++) { + r[i] = ((int) a[i]); + } + return r; + } + + /*public static String[] getConfigStringArray(String key) { Object cfg = getConfigMaster(key); if (cfg instanceof JsonArray) { JsonArray jsonArray = ((JsonArray) cfg).getAsJsonArray(); @@ -1102,13 +1087,13 @@ public class AppLoader implements ApplicationListener { } else return ((String[]) cfg); - } + }*/ /** * Get config from config file. If the entry does not exist, get from defaults; if the entry is not in the default, NullPointerException will be thrown */ - private static JsonObject getDefaultConfig() { - return DefaultConfig.INSTANCE.fetch(); + private static HashMap getDefaultConfig() { + return DefaultConfig.INSTANCE.getHashMap(); } private static Object getConfigMaster(String key1) { diff --git a/src/net/torvald/terrarum/DefaultConfig.kt b/src/net/torvald/terrarum/DefaultConfig.kt index 1cd0ad50a..d110c8c49 100644 --- a/src/net/torvald/terrarum/DefaultConfig.kt +++ b/src/net/torvald/terrarum/DefaultConfig.kt @@ -1,8 +1,7 @@ package net.torvald.terrarum import com.badlogic.gdx.Input -import com.google.gson.JsonArray -import com.google.gson.JsonObject +import com.badlogic.gdx.utils.Json import net.torvald.terrarum.blockproperties.Block /** @@ -11,126 +10,110 @@ import net.torvald.terrarum.blockproperties.Block * Created by minjaesong on 2016-03-12. */ object DefaultConfig { - fun fetch(): JsonObject { - val jsonObject = JsonObject() - jsonObject.addProperty("displayfps", 0) // 0: no limit, non-zero: limit - jsonObject.addProperty("usevsync", false) - jsonObject.addProperty("screenwidth", TerrarumScreenSize.defaultW) - jsonObject.addProperty("screenheight", TerrarumScreenSize.defaultH) - jsonObject.addProperty("atlastexsize", 2048) + val hashMap = hashMapOf( + "displayfps" to 0, // 0: no limit, non-zero: limit + "usevsync" to false, + "screenwidth" to TerrarumScreenSize.defaultW, + "screenheight" to TerrarumScreenSize.defaultH, + "atlastexsize" to 2048, + + "language" to AppLoader.getSysLang(), + "notificationshowuptime" to 4000, + "multithread" to true, + "multithreadedlight" to false, + + "showhealthmessageonstartup" to true, + + "usexinput" to true, // when FALSE, LT+RT input on xbox controller is impossible + + "config_gamepadkeyn" to 3, + "config_gamepadkeyw" to 2, + "config_gamepadkeys" to 0, + "config_gamepadkeye" to 1, // xbox indices + + "config_gamepadlup" to 4, + "config_gamepadrup" to 5, + "config_gamepadselect" to 6, + "config_gamepadstart" to 7, + + "config_gamepadltrigger" to 8, + "config_gamepadrtrigger" to 9, + "config_gamepadlthumb" to 10, + "config_gamepadrthumb" to 11, - //jsonObject.addProperty("imtooyoungtodie", false) // no perma-death - jsonObject.addProperty("language", AppLoader.getSysLang()) - jsonObject.addProperty("notificationshowuptime", 4000) - jsonObject.addProperty("multithread", true) // experimental! - jsonObject.addProperty("multithreadedlight", false) // experimental! + "config_gamepadaxislx" to 1, + "config_gamepadaxisly" to 0, + "config_gamepadaxisrx" to 3, + "config_gamepadaxisry" to 2, // 0-1-2-3 but sometimes 3-2-1-0 ?! what the actual fuck? + "config_gamepadtriggeraxis" to 4, // positive: LT, negative: RT (xbox pad) + "config_gamepadtriggeraxis2" to 5, // just in case... (RT) - jsonObject.addProperty("showhealthmessageonstartup", true) + // to accomodate shifted zero point of analog stick + "gamepadaxiszeropoints" to doubleArrayOf(-0.011, -0.022, -0.033, -0.044), - // control-gamepad + "gamepadlabelstyle" to "msxbone", // "nwii", "logitech", "sonyps", "msxb360", "msxbone" - // "config_key", "config_mouse", "config_gamepad" are keyword recognised by control setup UI + // control-keyboard (GDX key codes, + "config_keyup" to Input.Keys.E, + "config_keyleft" to Input.Keys.S, + "config_keydown" to Input.Keys.D, + "config_keyright" to Input.Keys.F, // ESDF Masterrace - jsonObject.addProperty("usexinput", true) // when FALSE, LT+RT input on xbox controller is impossible + "config_keymovementaux" to Input.Keys.A, // movement-auxiliary, or hookshot + "config_keyinventory" to Input.Keys.Q, + "config_keyinteract" to Input.Keys.R, + "config_keyclose" to Input.Keys.C, // this or hard-coded ESC + "config_keyzoom" to Input.Keys.Z, - jsonObject.addProperty("config_gamepadkeyn", 3) - jsonObject.addProperty("config_gamepadkeyw", 2) - jsonObject.addProperty("config_gamepadkeys", 0) - jsonObject.addProperty("config_gamepadkeye", 1) // xbox indices + "config_keygamemenu" to Input.Keys.TAB, + "config_keyquicksel" to Input.Keys.SHIFT_LEFT, // pie menu is now LShift because GDX does not read CapsLock + // Colemak, Workman and some typers use CapsLock as Backspace, Apple-JIS and HHKB has Control in place of CapsLock and often re-assigned to Command + // so these keys are treated as the same. + // FOR ~~FUCKS~~ERGONOMICS' SAKE DON'T USE CTRL AND ALT AS A KEY! + "config_keyquickselalt" to intArrayOf(Input.Keys.BACKSPACE, Input.Keys.CONTROL_LEFT, Input.Keys.BACKSLASH), + "config_mousequicksel" to Input.Buttons.MIDDLE, // middle click to open pie menu - jsonObject.addProperty("config_gamepadlup", 4) - jsonObject.addProperty("config_gamepadrup", 5) - jsonObject.addProperty("config_gamepadselect", 6) - jsonObject.addProperty("config_gamepadstart", 7) + "config_keyjump" to Input.Keys.SPACE, - jsonObject.addProperty("config_gamepadltrigger", 8) - jsonObject.addProperty("config_gamepadrtrigger", 9) - jsonObject.addProperty("config_gamepadlthumb", 10) - jsonObject.addProperty("config_gamepadrthumb", 11) + "config_keyquickslots" to (Input.Keys.NUM_0..Input.Keys.NUM_9).toList(), + + "config_mouseprimary" to Input.Buttons.LEFT, // left mouse + "config_mousesecondary" to Input.Buttons.RIGHT, // right mouse - jsonObject.addProperty("config_gamepadaxislx", 1) - jsonObject.addProperty("config_gamepadaxisly", 0) - jsonObject.addProperty("config_gamepadaxisrx", 3) - jsonObject.addProperty("config_gamepadaxisry", 2) // 0-1-2-3 but sometimes 3-2-1-0 ?! what the actual fuck? - jsonObject.addProperty("config_gamepadtriggeraxis", 4) // positive: LT, negative: RT (xbox pad) - jsonObject.addProperty("config_gamepadtriggeraxis2", 5) // just in case... (RT) + "pcgamepadenv" to "console", - val axesZeroPoints = JsonArray(); axesZeroPoints.add(-0.011f); axesZeroPoints.add(-0.022f); axesZeroPoints.add(-0.033f); axesZeroPoints.add(-0.044f) - jsonObject.add("gamepadaxiszeropoints", axesZeroPoints) // to accomodate shifted zero point of analog stick - - jsonObject.addProperty("gamepadlabelstyle", "msxbone") // "nwii", "logitech", "sonyps", "msxb360", "msxbone" - - // control-keyboard (GDX key codes) - jsonObject.addProperty("config_keyup", Input.Keys.E) - jsonObject.addProperty("config_keyleft", Input.Keys.S) - jsonObject.addProperty("config_keydown", Input.Keys.D) - jsonObject.addProperty("config_keyright", Input.Keys.F) // ESDF Masterrace - - jsonObject.addProperty("config_keymovementaux", Input.Keys.A) // movement-auxiliary, or hookshot - jsonObject.addProperty("config_keyinventory", Input.Keys.Q) - jsonObject.addProperty("config_keyinteract", Input.Keys.R) - jsonObject.addProperty("config_keyclose", Input.Keys.C) // this or hard-coded ESC - jsonObject.addProperty("config_keyzoom", Input.Keys.Z) - - jsonObject.addProperty("config_keygamemenu", Input.Keys.TAB) - jsonObject.addProperty("config_keyquicksel", Input.Keys.SHIFT_LEFT) // pie menu is now LShift because GDX does not read CapsLock - val keyquickselalt = JsonArray(); keyquickselalt.add(Input.Keys.BACKSPACE); keyquickselalt.add(Input.Keys.CONTROL_LEFT); keyquickselalt.add(Input.Keys.BACKSLASH) - // Colemak, Workman and some typers use CapsLock as Backspace, Apple-JIS and HHKB has Control in place of CapsLock and often re-assigned to Command - // so these keys are treated as the same. - // FOR ~~FUCKS~~ERGONOMICS' SAKE DON'T USE CTRL AND ALT AS A KEY! - jsonObject.add("config_keyquickselalt", keyquickselalt) - jsonObject.addProperty("config_mousequicksel", Input.Buttons.MIDDLE) // middle click to open pie menu - - jsonObject.addProperty("config_keyjump", Input.Keys.SPACE) - - val keyquickslots = JsonArray(); for (i in Input.Keys.NUM_1..Input.Keys.NUM_9) keyquickslots.add(i); keyquickslots.add(Input.Keys.NUM_0) // NUM_1 to NUM_0 - jsonObject.add("config_keyquickslots", keyquickslots) - - jsonObject.addProperty("config_mouseprimary", Input.Buttons.LEFT) // left mouse - jsonObject.addProperty("config_mousesecondary", Input.Buttons.RIGHT) // right mouse + //jsonObject.writeValue("safetywarning" to true, - jsonObject.addProperty("pcgamepadenv", "console") + "maxparticles" to 768, - //jsonObject.addProperty("safetywarning", true) + "temperatureunit" to 1, // -1: american, 0: kelvin, 1: celcius - jsonObject.addProperty("maxparticles", 768) - - jsonObject.addProperty("temperatureunit", 1) // -1: american, 0: kelvin, 1: celcius + // "fancy" graphics settings + "fxdither" to true, + "fxretro" to false, + //"fx3dlut" to false, - // "fancy" graphics settings - jsonObject.addProperty("fxdither", true) - jsonObject.addProperty("fxretro", false) - //jsonObject.addProperty("fx3dlut", false) + // settings regarding debugger + /*"buildingmakerfavs" to arrayOf( + Block.GLASS_CRUDE, + Block.PLANK_NORMAL, + Block.PLANK_BIRCH, + Block.STONE_QUARRIED, + Block.STONE_BRICKS, - - // settings regarding debugger - val buildingMakerFavs = JsonArray() - arrayOf( - Block.GLASS_CRUDE, - Block.PLANK_NORMAL, - Block.PLANK_BIRCH, - Block.STONE_QUARRIED, - Block.STONE_BRICKS, - - Block.STONE_TILE_WHITE, - Block.TORCH, - "wall@" + Block.PLANK_NORMAL, - "wall@" + Block.PLANK_BIRCH, - "wall@" + Block.GLASS_CRUDE - ).forEach { - buildingMakerFavs.add(it) - } - jsonObject.add("buildingmakerfavs", buildingMakerFavs) - - - return jsonObject - } + Block.STONE_TILE_WHITE, + Block.TORCH, + "wall@" + Block.PLANK_NORMAL, + "wall@" + Block.PLANK_BIRCH, + "wall@" + Block.GLASS_CRUDE + )*/ + ) } /* diff --git a/src/net/torvald/terrarum/GsonSerialisable.kt b/src/net/torvald/terrarum/GsonSerialisable.kt deleted file mode 100644 index f39a89eb5..000000000 --- a/src/net/torvald/terrarum/GsonSerialisable.kt +++ /dev/null @@ -1,15 +0,0 @@ -package net.torvald.terrarum - -import com.google.gson.JsonObject - -/** - * Created by minjaesong on 2018-05-18. - */ -interface GsonSerialisable { - - /** - * Will modify itself according to the input gson. Not sure it's even necessary so please test. - */ - fun read(gson: JsonObject) - -} \ No newline at end of file diff --git a/src/net/torvald/terrarum/IngameInstance.kt b/src/net/torvald/terrarum/IngameInstance.kt index 789751926..45abd3305 100644 --- a/src/net/torvald/terrarum/IngameInstance.kt +++ b/src/net/torvald/terrarum/IngameInstance.kt @@ -45,7 +45,8 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { field = value } /** how many different planets/stages/etc. are thenre. Whole stages must be manually managed by YOU. */ - var gameworldCount = 0 + var gameworldIndices = ArrayList() + /** The actor the game is currently allowing you to control. * * Most of the time it'd be the "player", but think about the case where you have possessed diff --git a/src/net/torvald/terrarum/KVHashMap.kt b/src/net/torvald/terrarum/KVHashMap.kt index f25e98a72..0900058ef 100644 --- a/src/net/torvald/terrarum/KVHashMap.kt +++ b/src/net/torvald/terrarum/KVHashMap.kt @@ -1,14 +1,11 @@ package net.torvald.terrarum -import com.google.gson.JsonObject -import com.google.gson.JsonPrimitive - typealias ItemValue = KVHashMap /** * Created by minjaesong on 2015-12-30. */ -open class KVHashMap : GsonSerialisable { +open class KVHashMap { constructor() { hashMap = HashMap() @@ -49,8 +46,7 @@ open class KVHashMap : GsonSerialisable { if (value == null) return null - if (value is JsonPrimitive) - return value.asInt +// if (value is JsonPrimitive) return value.asInt return value as Int } @@ -62,8 +58,7 @@ open class KVHashMap : GsonSerialisable { if (value is Int) return value.toDouble() - else if (value is JsonPrimitive) - return value.asDouble +// else if (value is JsonPrimitive) return value.asDouble return value as Double } @@ -77,8 +72,7 @@ open class KVHashMap : GsonSerialisable { if (value == null) return null - if (value is JsonPrimitive) - return value.asString +// if (value is JsonPrimitive) return value.asString return value as String } @@ -88,8 +82,7 @@ open class KVHashMap : GsonSerialisable { if (value == null) return null - if (value is JsonPrimitive) - return value.asBoolean +// if (value is JsonPrimitive) return value.asBoolean return value as Boolean } @@ -109,9 +102,4 @@ open class KVHashMap : GsonSerialisable { val cloneOfMap = hashMap.clone() as HashMap return KVHashMap(cloneOfMap) } - - override fun read(gson: JsonObject) { - TODO() - } - } \ No newline at end of file diff --git a/src/net/torvald/terrarum/ModMgr.kt b/src/net/torvald/terrarum/ModMgr.kt index 0d9735af2..22131642d 100644 --- a/src/net/torvald/terrarum/ModMgr.kt +++ b/src/net/torvald/terrarum/ModMgr.kt @@ -62,6 +62,8 @@ object ModMgr { val moduleInfo = HashMap() val entryPointClasses = ArrayList() + val loadOrder = ArrayList() + init { // load modules val loadOrderCSVparser = CSVParser.parse( @@ -75,6 +77,7 @@ object ModMgr { loadOrder.forEachIndexed { index, it -> val moduleName = it[0] + this.loadOrder.add(moduleName) printmsg(this, "Loading module $moduleName") try { diff --git a/src/net/torvald/terrarum/blockproperties/BlockCodex.kt b/src/net/torvald/terrarum/blockproperties/BlockCodex.kt index 20933ab61..3a340e69a 100644 --- a/src/net/torvald/terrarum/blockproperties/BlockCodex.kt +++ b/src/net/torvald/terrarum/blockproperties/BlockCodex.kt @@ -20,7 +20,7 @@ import java.io.IOException */ object BlockCodex { - private var blockProps = HashMap() + val blockProps = HashMap() val dynamicLights = SortedArrayList() // does not include virtual ones diff --git a/src/net/torvald/terrarum/blockproperties/BlockProp.kt b/src/net/torvald/terrarum/blockproperties/BlockProp.kt index 88e8b58fc..3af22f925 100644 --- a/src/net/torvald/terrarum/blockproperties/BlockProp.kt +++ b/src/net/torvald/terrarum/blockproperties/BlockProp.kt @@ -4,7 +4,6 @@ import net.torvald.gdx.graphics.Cvec import net.torvald.random.XXHash32 import net.torvald.terrarum.gameitem.ItemID import net.torvald.terrarum.gameworld.fmod -import net.torvald.terrarum.serialise.toLittle /** * Created by minjaesong on 2016-02-16. @@ -92,7 +91,7 @@ class BlockProp { var material: String = "" - var rngBase0 = Math.random().toFloat() // initial cycle phase (xxxxFuncX) - var rngBase1 = Math.random().toFloat() // flicker P0, etc - var rngBase2 = Math.random().toFloat() // flicker P1, etc + @Transient var rngBase0 = Math.random().toFloat() // initial cycle phase (xxxxFuncX) + @Transient var rngBase1 = Math.random().toFloat() // flicker P0, etc + @Transient var rngBase2 = Math.random().toFloat() // flicker P1, etc } \ No newline at end of file diff --git a/src/net/torvald/terrarum/blockproperties/WireCodex.kt b/src/net/torvald/terrarum/blockproperties/WireCodex.kt index 5a0ae7eb4..2a74a8f9b 100644 --- a/src/net/torvald/terrarum/blockproperties/WireCodex.kt +++ b/src/net/torvald/terrarum/blockproperties/WireCodex.kt @@ -17,7 +17,7 @@ import java.io.IOException */ object WireCodex { - private var wireProps = HashMap() + val wireProps = HashMap() private val nullProp = WireProp() diff --git a/src/net/torvald/terrarum/console/CommandDict.kt b/src/net/torvald/terrarum/console/CommandDict.kt index 7290d43d0..8a606ba27 100644 --- a/src/net/torvald/terrarum/console/CommandDict.kt +++ b/src/net/torvald/terrarum/console/CommandDict.kt @@ -48,7 +48,6 @@ object CommandDict { // Test codes "bulletintest" to SetBulletin, - "gsontest" to GsonTest, "tips" to PrintRandomTips, "langtest" to LangTest, "spawnball" to SpawnPhysTestBall, diff --git a/src/net/torvald/terrarum/controller/TerrarumController.kt b/src/net/torvald/terrarum/controller/TerrarumController.kt index aced53db5..3aee97ea7 100644 --- a/src/net/torvald/terrarum/controller/TerrarumController.kt +++ b/src/net/torvald/terrarum/controller/TerrarumController.kt @@ -1,7 +1,7 @@ package net.torvald.terrarum.controller import net.torvald.terrarum.AppLoader.gamepadDeadzone -import net.torvald.terrarum.AppLoader.getConfigFloatArray +import net.torvald.terrarum.AppLoader.getConfigDoubleArray /** * Created by minjaesong on 2019-02-09. @@ -49,7 +49,7 @@ interface TerrarumController { */ fun getAxis(index:Int): Float { val raw = getAxisRaw(index) - val zero = if (index < 4) getConfigFloatArray("gamepadaxiszeropoints")[index] else 0f + val zero = if (index < 4) getConfigDoubleArray("gamepadaxiszeropoints")[index] else 0.0 val compensatedRaw = raw - zero val inDeadzone = Math.abs(compensatedRaw) < gamepadDeadzone @@ -58,7 +58,7 @@ interface TerrarumController { fun inDeadzone(axis: Int): Boolean { val ax = getAxisRaw(axis) - val zero = if (axis < 4) getConfigFloatArray("gamepadaxiszeropoints")[axis] else 0f + val zero = if (axis < 4) getConfigDoubleArray("gamepadaxiszeropoints")[axis] else 0.0 return Math.abs(ax - zero) < gamepadDeadzone } diff --git a/src/net/torvald/terrarum/gameactors/faction/FactionFactory.kt b/src/net/torvald/terrarum/gameactors/faction/FactionFactory.kt index d3ed1fcee..4c5d56a45 100644 --- a/src/net/torvald/terrarum/gameactors/faction/FactionFactory.kt +++ b/src/net/torvald/terrarum/gameactors/faction/FactionFactory.kt @@ -16,12 +16,12 @@ object FactionFactory { @Throws(IOException::class) fun create(module: String, path: String): Faction { val jsonObj = JsonFetcher(ModMgr.getFile(module, path)) - val factionObj = Faction(jsonObj.get("factionname").asString) + val factionObj = Faction(jsonObj.getString("factionname")) - jsonObj.get("factionamicable").asJsonArray.forEach { factionObj.addFactionAmicable(it.asString) } - jsonObj.get("factionneutral").asJsonArray.forEach { factionObj.addFactionNeutral(it.asString) } - jsonObj.get("factionhostile").asJsonArray.forEach { factionObj.addFactionHostile(it.asString) } - jsonObj.get("factionfearful").asJsonArray.forEach { factionObj.addFactionFearful(it.asString) } + jsonObj.get("factionamicable").asStringArray().forEach { factionObj.addFactionAmicable(it) } + jsonObj.get("factionneutral").asStringArray().forEach { factionObj.addFactionNeutral(it) } + jsonObj.get("factionhostile").asStringArray().forEach { factionObj.addFactionHostile(it) } + jsonObj.get("factionfearful").asStringArray().forEach { factionObj.addFactionFearful(it) } return factionObj } diff --git a/src/net/torvald/terrarum/gamecontroller/KeyLayout.kt b/src/net/torvald/terrarum/gamecontroller/KeyLayout.kt index 5119cd2a4..dffedf719 100644 --- a/src/net/torvald/terrarum/gamecontroller/KeyLayout.kt +++ b/src/net/torvald/terrarum/gamecontroller/KeyLayout.kt @@ -1,8 +1,12 @@ package net.torvald.terrarum.gamecontroller +import com.badlogic.gdx.utils.JsonValue import net.torvald.terrarum.utils.JsonFetcher import java.util.* + + + /** * Created by minjaesong on 2016-07-28. */ @@ -16,17 +20,18 @@ object KeyLayout { init { layouts = HashMap() - val json = JsonFetcher("./res/keylayout.json") - json.entrySet().forEach { it -> + val map = net.torvald.terrarum.utils.JsonFetcher("./res/keylayout.json") + JsonFetcher.forEach(map) { name, entry -> layouts.put( - it.key, + name, KeyLayoutClass( - it.value.asJsonObject.get("layout").asString, - it.value.asJsonObject.get("name").asString, - it.value.asJsonObject.get("capslock").asString + entry.getString("layout"), + entry.getString("name"), + entry.getString("capslock") ) ) } + } } diff --git a/src/net/torvald/terrarum/gameworld/GameWorld.kt b/src/net/torvald/terrarum/gameworld/GameWorld.kt index 597d4c087..dd865fcde 100644 --- a/src/net/torvald/terrarum/gameworld/GameWorld.kt +++ b/src/net/torvald/terrarum/gameworld/GameWorld.kt @@ -11,7 +11,6 @@ import net.torvald.terrarum.blockproperties.Fluid import net.torvald.terrarum.gameactors.WireActor import net.torvald.terrarum.gameitem.ItemID import net.torvald.terrarum.realestate.LandUtil -import net.torvald.terrarum.serialise.ReadLayerDataZip import net.torvald.util.SortedArrayList import org.dyn4j.geometry.Vector2 import kotlin.experimental.and @@ -165,31 +164,10 @@ open class GameWorld : Disposable { /** * Load existing world */ - internal constructor(worldIndex: Int, layerData: ReadLayerDataZip.LayerData, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) { + /*internal constructor(worldIndex: Int, json: JsonObject) { this.worldIndex = worldIndex - layerTerrain = layerData.layerTerrain - layerWall = layerData.layerWall - //layerWire = layerData.layerWire - - wallDamages = layerData.wallDamages - terrainDamages = layerData.terrainDamages - fluidTypes = layerData.fluidTypes - fluidFills = layerData.fluidFills - - //wiringBlocks = HashMap() - wirings = HashMap() - - spawnX = layerData.spawnX - spawnY = layerData.spawnY - - width = layerTerrain.width - height = layerTerrain.height - - - creationTime = creationTIME_T - lastPlayTime = lastPlayTIME_T - this.totalPlayTime = totalPlayTime + // TODO setup layerTerrain, layerWall, etc. from the json // before the renaming, update the name maps tileNumberToNameMap = HashMap() @@ -200,7 +178,7 @@ open class GameWorld : Disposable { } // perform renaming of tile layers - val oldTileNumberToNameMap = layerData.tileNumberToNameMap + val oldTileNumberToNameMap = /* todo */ for (y in 0 until layerTerrain.height) { for (x in 0 until layerTerrain.width) { layerTerrain.unsafeSetTile(x, y, tileNameToNumberMap[oldTileNumberToNameMap[layerTerrain.unsafeGetTile(x, y)]]!!) @@ -212,7 +190,7 @@ open class GameWorld : Disposable { // AN EXCEPTIONAL TERM: tilenum 0 is always redirected to Air tile, even if the tilenum for actual Air tile is not zero tileNumberToNameMap[0] = Block.AIR - } + }*/ /** * Get 2d array data of wire diff --git a/src/net/torvald/terrarum/itemproperties/ItemCodex.kt b/src/net/torvald/terrarum/itemproperties/ItemCodex.kt index df0d7593e..df4147a7b 100644 --- a/src/net/torvald/terrarum/itemproperties/ItemCodex.kt +++ b/src/net/torvald/terrarum/itemproperties/ItemCodex.kt @@ -26,7 +26,7 @@ object ItemCodex { * * Will return corresponding Actor if ID >= ACTORID_MIN */ - private val itemCodex = HashMap() + val itemCodex = HashMap() val dynamicItemDescription = HashMap() val dynamicToStaticTable = HashMap() @@ -119,5 +119,5 @@ object ItemCodex { } - fun hasItem(itemID: Int): Boolean = dynamicItemDescription.containsKey(itemID) + fun hasItem(itemID: ItemID): Boolean = dynamicItemDescription.containsKey(itemID) } \ No newline at end of file diff --git a/src/net/torvald/terrarum/itemproperties/Material.kt b/src/net/torvald/terrarum/itemproperties/Material.kt index 76526681e..47b15d8d1 100644 --- a/src/net/torvald/terrarum/itemproperties/Material.kt +++ b/src/net/torvald/terrarum/itemproperties/Material.kt @@ -28,7 +28,7 @@ class Material { object MaterialCodex { - private var materialProps = HashMap() + val materialProps = HashMap() private val nullMaterial = Material() operator fun invoke(module: String, path: String) { diff --git a/src/net/torvald/terrarum/langpack/Lang.kt b/src/net/torvald/terrarum/langpack/Lang.kt index 3aad4c796..a2b8b3a66 100644 --- a/src/net/torvald/terrarum/langpack/Lang.kt +++ b/src/net/torvald/terrarum/langpack/Lang.kt @@ -82,9 +82,10 @@ object Lang { * "<>" = "<>" */ //println(json.entrySet()) - json.entrySet().forEach { - langpack.put("${it.key}_$lang", it.value.asString) + JsonFetcher.forEach(json) { key, value -> + langpack.put("${key}_$lang", value.asString()) } + } private fun processPolyglotLangFile(file: File, lang: String) { @@ -106,12 +107,13 @@ object Lang { * (the array continues) * */ - json.getAsJsonObject("resources").getAsJsonArray("data").forEach { + JsonFetcher.forEach(json.get("resources").get("data")) { _, entry -> langpack.put( - "${it.asJsonObject["n"].asString}_$lang", - it.asJsonObject["s"].asString + "${entry.getString("n")}_$lang", + entry.getString("s") ) } + } operator fun get(key: String): String { diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index d9e781ed7..394ce0fce 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -303,7 +303,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { // init map as chosen size val timeNow = System.currentTimeMillis() / 1000 gameworld = GameWorldExtension(1, worldParams.width, worldParams.height, timeNow, timeNow, 0) // new game, so the creation time is right now - gameworldCount++ + gameworldIndices.add(gameworld.worldIndex) world = gameworld // generate terrain for the map diff --git a/src/net/torvald/terrarum/modulebasegame/console/ExportAV.kt b/src/net/torvald/terrarum/modulebasegame/console/ExportAV.kt index 49d2adde6..ed1de7c98 100644 --- a/src/net/torvald/terrarum/modulebasegame/console/ExportAV.kt +++ b/src/net/torvald/terrarum/modulebasegame/console/ExportAV.kt @@ -20,7 +20,7 @@ internal object ExportAV : ConsoleCommand { if (player == null) return JsonWriter.writeToFile( - player.actorValue, + player, AppLoader.defaultDir + "/Exports/" + args[1] + ".json") Echo("ExportAV: exported to " + args[1] + ".json") diff --git a/src/net/torvald/terrarum/modulebasegame/console/ExportLayerData.kt b/src/net/torvald/terrarum/modulebasegame/console/ExportLayerData.kt index b1535d0f0..5767dcb50 100644 --- a/src/net/torvald/terrarum/modulebasegame/console/ExportLayerData.kt +++ b/src/net/torvald/terrarum/modulebasegame/console/ExportLayerData.kt @@ -1,22 +1,31 @@ package net.torvald.terrarum.modulebasegame.console +import com.badlogic.gdx.utils.Json +import net.torvald.terrarum.AppLoader +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.WriteMeta +import net.torvald.terrarum.utils.JsonWriter +import java.io.IOException /** * Created by minjaesong on 2017-07-18. */ object ExportLayerData : ConsoleCommand { override fun execute(args: Array) { - /*try { - val outfile = WriteLayerDataZip() - WriteWorldInfo() - Echo("Layer data exported to ${outfile!!.canonicalPath}") + try { + val str = WriteMeta(Terrarum.ingame!! as TerrarumIngame).invoke() + val writer = java.io.FileWriter(AppLoader.defaultDir + "/Exports/savegame.json", false) + writer.write(str) + writer.close() + Echo("Exportlayer: exported to savegame.json") } - catch (e: Exception) { + catch (e: IOException) { + Echo("Exportlayer: IOException raised.") e.printStackTrace() - EchoError("Layer data export failed; see console for error traces.") - }*/ + } } override fun printUsage() { diff --git a/src/net/torvald/terrarum/modulebasegame/console/GsonTest.kt b/src/net/torvald/terrarum/modulebasegame/console/GsonTest.kt index 04c1c10e9..8ad88d89e 100644 --- a/src/net/torvald/terrarum/modulebasegame/console/GsonTest.kt +++ b/src/net/torvald/terrarum/modulebasegame/console/GsonTest.kt @@ -13,7 +13,7 @@ import java.io.IOException /** * Created by minjaesong on 2016-02-10. */ -internal object GsonTest : ConsoleCommand { +/*internal object GsonTest : ConsoleCommand { override fun execute(args: Array) { if (args.size == 2) { @@ -51,4 +51,4 @@ internal object GsonTest : ConsoleCommand { Echo("Usage: gsontest filename-without-extension") } -} +}*/ diff --git a/src/net/torvald/terrarum/modulebasegame/console/ImportLayerData.kt b/src/net/torvald/terrarum/modulebasegame/console/ImportLayerData.kt index 35cee4852..685273891 100644 --- a/src/net/torvald/terrarum/modulebasegame/console/ImportLayerData.kt +++ b/src/net/torvald/terrarum/modulebasegame/console/ImportLayerData.kt @@ -5,7 +5,6 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.console.ConsoleCommand import net.torvald.terrarum.console.Echo import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension -import net.torvald.terrarum.serialise.ReadLayerDataZip import java.io.File /** @@ -13,7 +12,7 @@ import java.io.File */ object ImportLayerData : ConsoleCommand { override fun execute(args: Array) { - if (args.size < 2) { + /*if (args.size < 2) { ExportLayerData.printUsage() return } @@ -28,7 +27,7 @@ object ImportLayerData : ConsoleCommand { (Terrarum.ingame!!.world).spawnX * TILE_SIZED ) - Echo("Successfully loaded ${args[1]}") + Echo("Successfully loaded ${args[1]}")*/ } override fun printUsage() { diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/InjectCreatureRaw.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/InjectCreatureRaw.kt index f27d36271..173aff676 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/InjectCreatureRaw.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/InjectCreatureRaw.kt @@ -2,13 +2,12 @@ package net.torvald.terrarum.modulebasegame.gameactors import net.torvald.terrarum.utils.JsonFetcher import net.torvald.random.Fudge3 -import net.torvald.terrarum.langpack.Lang -import com.google.gson.JsonObject import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.ModMgr import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.ActorValue import java.security.SecureRandom +import kotlin.collections.ArrayList /** * Created by minjaesong on 2016-03-25. @@ -27,46 +26,44 @@ object InjectCreatureRaw { operator fun invoke(actorValueRef: ActorValue, module: String, jsonFileName: String) { val jsonObj = JsonFetcher(ModMgr.getPath(module, "creatures/$jsonFileName")) - jsonObj.keySet().filter { !it.startsWith("_") }.forEach { key -> + JsonFetcher.forEach(jsonObj) { key, value -> if (!key.startsWith("_")) { val diceRollers = ArrayList() - jsonObj[key].let { - if (it.isJsonPrimitive) { - val raw = it.asString - val lowraw = raw.toLowerCase() - // can the value be cast to Boolean? - if (lowraw == "true") actorValueRef[key] = true - else if (lowraw == "false") actorValueRef[key] = false - else { - try { - actorValueRef[key] = - if (raw.contains('.')) it.asDouble - else it.asInt - } - catch (e: NumberFormatException) { - actorValueRef[key] = raw - } + if (!value.isArray && !value.isObject) { + val raw = value.asString() + val lowraw = raw.lowercase() + // can the value be cast to Boolean? + if (lowraw == "true") actorValueRef[key] = true + else if (lowraw == "false") actorValueRef[key] = false + else { + try { + actorValueRef[key] = + if (raw.contains('.')) value.asDouble() + else value.asLong().toInt() + } + catch (e: NumberFormatException) { + actorValueRef[key] = raw } } - else if (key.endsWith(JSONMULT) && it.isJsonArray) { - diceRollers.add(key) - } - else { - printdbg(this, "Unknown Creature Raw key: $key") - } + } + else if (key.endsWith(JSONMULT) && value.isArray) { + diceRollers.add(key) + } + else { + printdbg(this, "Unknown Creature Raw key: $key") } diceRollers.forEach { keymult -> val keybase = keymult.substring(0, keymult.length - 4) - val baseValue = jsonObj[keybase].asDouble + val baseValue = jsonObj[keybase].asDouble() val selected = Fudge3(SecureRandom()).rollForArray() - val mult = jsonObj[keymult].asJsonArray.get(selected).asInt + val mult = jsonObj[keymult].asIntArray()[selected] val realValue = baseValue * mult / 100.0 actorValueRef[keybase] = realValue actorValueRef[keybase + BUFF] = 1.0 } - } + } } } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/gameworld/GameWorldExtension.kt b/src/net/torvald/terrarum/modulebasegame/gameworld/GameWorldExtension.kt index 5b45fe4ce..7b2280eb5 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameworld/GameWorldExtension.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameworld/GameWorldExtension.kt @@ -2,7 +2,6 @@ package net.torvald.terrarum.modulebasegame.gameworld import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.WorldTime -import net.torvald.terrarum.serialise.ReadLayerDataZip /** * Created by minjaesong on 2018-07-03. @@ -10,7 +9,7 @@ import net.torvald.terrarum.serialise.ReadLayerDataZip class GameWorldExtension : GameWorld { constructor(worldIndex: Int, width: Int, height: Int, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) : super(worldIndex, width, height, creationTIME_T, lastPlayTIME_T, totalPlayTime) - internal constructor(worldIndex: Int, layerData: ReadLayerDataZip.LayerData, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) : super(worldIndex, layerData, creationTIME_T, lastPlayTIME_T, totalPlayTime) + //internal constructor(worldIndex: Int, layerData: ReadLayerDataZip.LayerData, creationTIME_T: Long, lastPlayTIME_T: Long, totalPlayTime: Int) : super(worldIndex, layerData, creationTIME_T, lastPlayTIME_T, totalPlayTime) val economy = GameEconomy() diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIBuildingMakerPenMenu.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIBuildingMakerPenMenu.kt index 639f47fee..09a4ef855 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIBuildingMakerPenMenu.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIBuildingMakerPenMenu.kt @@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.Camera import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.terrarum.* +import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.modulebasegame.BuildingMaker import net.torvald.terrarum.ui.UICanvas @@ -153,7 +154,19 @@ class UIBuildingMakerPenMenu(val parent: BuildingMaker): UICanvas() { // draw blocks slot batch.color = blockCellCol - val slotConfig = AppLoader.getConfigStringArray("buildingmakerfavs") + val slotConfig = arrayOf( + Block.GLASS_CRUDE, + Block.PLANK_NORMAL, + Block.PLANK_BIRCH, + Block.STONE_QUARRIED, + Block.STONE_BRICKS, + + Block.STONE_TILE_WHITE, + Block.TORCH, + "wall@" + Block.PLANK_NORMAL, + "wall@" + Block.PLANK_BIRCH, + "wall@" + Block.GLASS_CRUDE + )//AppLoader.getConfigStringArray("buildingmakerfavs") for (i in 0 until PALETTE_SIZE) { val x = blockCellPos[i].x.roundToInt().toFloat() val y = blockCellPos[i].y.roundToInt().toFloat() diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIItemPlayerInfoCell.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIItemPlayerInfoCell.kt index 0daf29dc7..d3518d181 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIItemPlayerInfoCell.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIItemPlayerInfoCell.kt @@ -2,10 +2,10 @@ package net.torvald.terrarum.modulebasegame.ui import com.badlogic.gdx.graphics.Camera import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.badlogic.gdx.utils.JsonValue import net.torvald.terrarum.* import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer -import net.torvald.terrarum.serialise.ReadWorldInfo import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UIItem import java.util.* @@ -17,7 +17,7 @@ import java.util.* */ class UIItemPlayerInfoCell( parent: UICanvas, - val saveInfo: ReadWorldInfo.SaveMetaData, + val saveInfo: JsonValue, override val width: Int, initialX: Int, initialY: Int, @@ -50,18 +50,18 @@ class UIItemPlayerInfoCell( init { val cal = Calendar.getInstance() - cal.timeInMillis = saveInfo.creationTime * 1000 + cal.timeInMillis = saveInfo.getLong("creation_t") * 1000 creationTimeStr = "${cal[Calendar.YEAR]}-" + "${cal[Calendar.MONTH].toString().padStart(2,'0')}-" + "${cal[Calendar.DATE].toString().padStart(2,'0')}" - cal.timeInMillis = saveInfo.lastPlayTime * 1000 + cal.timeInMillis = saveInfo.getLong("lastplay_t") * 1000 modificationTimeStr = "${cal[Calendar.YEAR]}-" + "${cal[Calendar.MONTH].toString().padStart(2,'0')}-" + "${cal[Calendar.DATE].toString().padStart(2,'0')}" - worldCountStr = Lang["CONTEXT_WORLD_COUNT"] + saveInfo.worldCount + worldCountStr = Lang["CONTEXT_WORLD_COUNT"] + saveInfo.get("worlds").asIntArray().size worldCountStrWidth = AppLoader.fontGame.getWidth(worldCountStr) } diff --git a/src/net/torvald/terrarum/serialise/PayloadUtil.kt b/src/net/torvald/terrarum/serialise/PayloadUtil.kt deleted file mode 100644 index 523e7374e..000000000 --- a/src/net/torvald/terrarum/serialise/PayloadUtil.kt +++ /dev/null @@ -1,114 +0,0 @@ -package net.torvald.terrarum.serialise - -import net.torvald.terrarum.AppLoader -import net.torvald.terrarum.serialise.WriteLayerDataZip.FILE_FOOTER -import net.torvald.terrarum.serialise.WriteLayerDataZip.PAYLOAD_FOOTER -import net.torvald.terrarum.toHex -import java.nio.charset.Charset -import java.util.* - -/** - * Created by minjaesong on 2019-02-20. - */ - -object PayloadUtil { - /** - * InputStream must be located manually at the payload begin - * - * For the actual use case, take a look at the source of the [ReadLayerDataZip]. - */ - fun readAll(inputStream: MarkableFileInputStream, footer: ByteArray = FILE_FOOTER): HashMap { - val pldBuffer4 = ByteArray(4) - val pldBuffer6 = ByteArray(6) - val pldBuffer8 = ByteArray(8) - - val payloads = HashMap() - - var pldCnt = 1 - - while (true) { - // read header and get payload's name - inputStream.read(pldBuffer8) - - // check if end of payload reached - if (pldBuffer8.contentEquals(footer)) { - break - } - - val payloadName = pldBuffer8.copyOfRange(4, 8).toString(Charset.forName("US-ASCII")) - - AppLoader.printdbg(this, "Payload $pldCnt name: $payloadName") // maybe maybe related with buffer things? - - // get uncompressed size - inputStream.read(pldBuffer6) - val uncompressedSize = pldBuffer6.toLittleInt48() - - // get deflated size - inputStream.mark(2147483647) // FIXME deflated stream cannot be larger than 2 GB - // creep forward until we hit the PAYLOAD_FOOTER - var compressedSize: Int = 0 // FIXME deflated stream cannot be larger than 2 GB - // loop init - inputStream.read(pldBuffer8) - // loop main - while (!pldBuffer8.contentEquals(PAYLOAD_FOOTER)) { - val aByte = inputStream.read(); compressedSize += 1 - if (aByte == -1) throw InternalError("Unexpected end-of-file at payload $pldCnt") - pldBuffer8.shiftLeftBy(1, aByte.toByte()) - } - - // at this point, we should have correct size of deflated bytestream - - AppLoader.printdbg(this, "Payload $pldCnt compressed size: $compressedSize") - - val compressedBytes = ByteArray(compressedSize) // FIXME deflated stream cannot be larger than 2 GB - inputStream.reset() // go back to marked spot - inputStream.read(compressedBytes) - - // PRO Debug tip: every deflated bytes must begin with 0x789C or 0x78DA - // Thus, \0pLd + [10] must be either of these. - - // put constructed payload into a container - payloads.put(payloadName, TEMzPayload(uncompressedSize, compressedBytes)) - - // skip over to be aligned with the next payload - inputStream.skip(8) - - pldCnt += 1 - } - - return payloads - } - - private fun ByteArray.shiftLeftBy(size: Int, fill: Byte = 0.toByte()) { - if (size == 0) { - return - } - else if (size < 0) { - throw IllegalArgumentException("This won't shift to right (size = $size)") - } - else if (size >= this.size) { - Arrays.fill(this, 0.toByte()) - } - else { - for (c in size..this.lastIndex) { - this[c - size] = this[c] - } - for (c in (this.size - size)..this.lastIndex) { - this[c] = fill - } - } - } - - private fun ByteArray.toByteString(): String { - val sb = StringBuilder() - this.forEach { - sb.append(it.toUint().toHex().takeLast(2)) - sb.append(' ') - } - sb.deleteCharAt(sb.lastIndex) - return sb.toString() - } - - data class TEMzPayload(val uncompressedSize: Long, val bytes: ByteArray) // FIXME deflated stream cannot be larger than 2 GB - -} \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/ReadLayerData.kt b/src/net/torvald/terrarum/serialise/ReadLayerData.kt deleted file mode 100644 index fd475c2e4..000000000 --- a/src/net/torvald/terrarum/serialise/ReadLayerData.kt +++ /dev/null @@ -1,188 +0,0 @@ -package net.torvald.terrarum.serialise - -/** - * Only being used by the title screen and the demoworld. This object may get deleted at any update - * - * Created by minjaesong on 2016-08-24. - */ -// internal for everything: prevent malicious module from messing up the savedata -@Deprecated("TEMD is deprecated format; use TEMz which does compression") -internal object ReadLayerData { - - init { - throw Error("TEMD is old and removed format; use TEMz which does compression") - } - - /*internal operator fun invoke(inputStream: InputStream, inWorld: GameWorldExtension? = null): GameWorldExtension { - val magicBytes = ByteArray(4) - val layerSizeBytes = ByteArray(1) - val layerCountBytes = ByteArray(1) - val worldWidthBytes = ByteArray(4) - val worldHeightBytes = ByteArray(4) - val spawnCoordXBytes = ByteArray(4) - val spawnCoordYBytes = ByteArray(4) - - // read header first - inputStream.read(magicBytes) - if (!Arrays.equals(magicBytes, WriteLayerData.MAGIC)) { - throw IllegalArgumentException("File not a Layer Data") - } - - inputStream.read(layerSizeBytes) - inputStream.read(layerCountBytes) - inputStream.skip(2) // reserved bytes - inputStream.read(worldWidthBytes) - inputStream.read(worldHeightBytes) - inputStream.read(spawnCoordXBytes) - inputStream.read(spawnCoordYBytes) - - val worldWidth = worldWidthBytes.toLittleInt() - val worldHeight = worldHeightBytes.toLittleInt() - val bytesPerTile = layerSizeBytes[0].toUint() - val layerCount = layerCountBytes[0].toUint() - val layerSize = worldWidth * worldHeight * bytesPerTile - - val terrainLayerMSB = ByteArray(layerSize) - val wallLayerMSB = ByteArray(layerSize) - val terrainLayerLSB = ByteArray(layerSize / 2) - val wallLayerLSB = ByteArray(layerSize / 2) - var wireLayer: ByteArray? = null - - inputStream.read(terrainLayerMSB) - inputStream.read(wallLayerMSB) - inputStream.read(terrainLayerLSB) - inputStream.read(wallLayerLSB) - - if (layerCount == 4) { - wireLayer = ByteArray(layerSize) - inputStream.read(wireLayer) - } - - - - // create world out of tiles data - - val retWorld = inWorld ?: GameWorldExtension(1, worldWidth, worldHeight, 0, 0, 0) // FIXME null TIME_T for the (partial) test to pass - - retWorld.layerTerrain.data = terrainLayerMSB - retWorld.layerWall.data = wallLayerMSB - retWorld.layerTerrainLowBits.data = terrainLayerLSB - retWorld.layerWallLowBits.data = wallLayerLSB - - - retWorld.spawnX = spawnCoordXBytes.toLittleInt() - retWorld.spawnY = spawnCoordYBytes.toLittleInt() - - - return retWorld - } - - - internal fun InputStream.readRelative(b: ByteArray, off: Int, len: Int): Int { - if (b == null) { - throw NullPointerException() - } else if (off < 0 || len < 0 || len > b.size) { - throw IndexOutOfBoundsException() - } else if (len == 0) { - return 0 - } - - var c = read() - if (c == -1) { - return -1 - } - b[0] = c.toByte() - - var i = 1 - try { - while (i < len) { - c = read() - if (c == -1) { - break - } - b[i] = c.toByte() - i++ - } - } catch (ee: IOException) { - } - - return i - }*/ -} - -fun Int.toLittle() = byteArrayOf( - this.and(0xFF).toByte(), - this.ushr(8).and(0xFF).toByte(), - this.ushr(16).and(0xFF).toByte(), - this.ushr(24).and(0xFF).toByte() -) -/** Converts int as 2-byte array, discarding the sign.*/ -fun Int.toULittleShort() = byteArrayOf( - this.and(0xFF).toByte(), - this.ushr(8).and(0xFF).toByte() -) -/** Converts int as 2-byte array, preserving the sign. In other words, it converts int to short. */ -fun Int.toLittleShort() = byteArrayOf( - this.and(0xFF).toByte(), - this.shr(8).and(0xFF).toByte() -) -fun Long.toLittle() = byteArrayOf( - this.and(0xFF).toByte(), - this.ushr(8).and(0xFF).toByte(), - this.ushr(16).and(0xFF).toByte(), - this.ushr(24).and(0xFF).toByte(), - this.ushr(32).and(0xFF).toByte(), - this.ushr(40).and(0xFF).toByte(), - this.ushr(48).and(0xFF).toByte(), - this.ushr(56).and(0xFF).toByte() -) -/** Converts long as 6-byte array, discarding the sign. */ -fun Long.toULittle48() = byteArrayOf( - this.and(0xFF).toByte(), - this.ushr(8).and(0xFF).toByte(), - this.ushr(16).and(0xFF).toByte(), - this.ushr(24).and(0xFF).toByte(), - this.ushr(32).and(0xFF).toByte(), - this.ushr(40).and(0xFF).toByte() -) -fun Double.toLittle() = java.lang.Double.doubleToRawLongBits(this).toLittle() -fun Boolean.toLittle() = byteArrayOf(if (this) 0xFF.toByte() else 0.toByte()) - -fun ByteArray.toLittleInt() = - if (this.size != 4) throw Error("Array not in size of 4") - else this[0].toUint() or - this[1].toUint().shl(8) or - this[2].toUint().shl(16) or - this[3].toUint().shl(24) -fun ByteArray.toULittleShort() = - if (this.size != 4) throw Error("Array not in size of 2") - else this[0].toUint() or - this[1].toUint().shl(8) -fun ByteArray.toLittleShort() = - if (this.size != 4) throw Error("Array not in size of 2") - else this[0].toUint() or - this[1].toInt().shl(8) -fun ByteArray.toLittleLong() = - if (this.size != 8) throw Error("Array not in size of 8") - else this[0].toUlong() or - this[1].toUlong().shl(8) or - this[2].toUlong().shl(16) or - this[3].toUlong().shl(24) or - this[4].toUlong().shl(32) or - this[5].toUlong().shl(40) or - this[6].toUlong().shl(48) or - this[7].toUlong().shl(56) -fun ByteArray.toLittleInt48() = - if (this.size != 6) throw Error("Array not in size of 6") - else this[0].toUlong() or - this[1].toUlong().shl(8) or - this[2].toUlong().shl(16) or - this[3].toUlong().shl(24) or - this[4].toUlong().shl(32) or - this[5].toUlong().shl(40) -fun ByteArray.toLittleFloat() = java.lang.Float.intBitsToFloat(this.toLittleInt()) - -fun Byte.toUlong() = java.lang.Byte.toUnsignedLong(this) -fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this) - -const val WORLD_GENERATOR_VERSION = 1 diff --git a/src/net/torvald/terrarum/serialise/ReadLayerDataLzma.kt b/src/net/torvald/terrarum/serialise/ReadLayerDataLzma.kt deleted file mode 100644 index d5cd4a57e..000000000 --- a/src/net/torvald/terrarum/serialise/ReadLayerDataLzma.kt +++ /dev/null @@ -1,224 +0,0 @@ -package net.torvald.terrarum.serialise - -import com.badlogic.gdx.utils.compression.Lzma -import net.torvald.terrarum.AppLoader.printdbg -import net.torvald.terrarum.gameitem.ItemID -import net.torvald.terrarum.gameworld.BlockAddress -import net.torvald.terrarum.gameworld.BlockLayer -import net.torvald.terrarum.gameworld.FluidType -import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read -import net.torvald.terrarum.realestate.LandUtil -import java.io.* -import java.util.* -import kotlin.collections.HashMap - -/** - * Created by minjaesong on 2016-08-24. - */ -// internal for everything: prevent malicious module from messing up the savedata -internal object ReadLayerDataLzma { - - // FIXME TERRAIN DAMAGE UNTESTED - - internal operator fun invoke(file: File): ReadLayerDataZip.LayerData { - val inputStream = MarkableFileInputStream(FileInputStream(file)) - - - val magicBytes = ByteArray(4) - - - ////////////////// - // FILE READING // - ////////////////// - - - // read header first - inputStream.read(magicBytes) - if (!Arrays.equals(magicBytes, WriteLayerDataZip.MAGIC)) { - throw IllegalArgumentException("File not a Layer Data") - } - - val versionNumber = inputStream.read(1)[0].toUint() - val layerCount = inputStream.read(1)[0].toUint() - val payloadCount = inputStream.read(1)[0].toUint() - val compression = inputStream.read(1)[0].toUint() - val generatorVer = inputStream.read(2).toULittleShort() - val width = inputStream.read(4).toLittleInt() - val height = inputStream.read(4).toLittleInt() - val spawnAddress = inputStream.read(6).toLittleInt48() - - if (compression != 2) throw IllegalArgumentException("Input file is not compressed as LZMA; it's using algorithm $compression") - - printdbg(this, "Version number: $versionNumber") - printdbg(this, "Layers count: $layerCount") - printdbg(this, "Payloads count: $payloadCount") - printdbg(this, "Compression: $compression") - printdbg(this, "World generator version: $generatorVer") - printdbg(this, "Dimension: ${width}x$height") - - // read payloads - - val payloads = PayloadUtil.readAll(inputStream) - /*val pldBuffer4 = ByteArray(4) - val pldBuffer6 = ByteArray(6) - val pldBuffer8 = ByteArray(8) - - val payloads = HashMap() - - - // TODO please test the read; write has been fixed up - - for (pldCnt in 0 until payloadCount) { - inputStream.read(pldBuffer4) - - // check payload header - if (!pldBuffer4.contentEquals(WriteLayerDataZip.PAYLOAD_HEADER)) - throw InternalError("Payload $pldCnt not found -- expected ${WriteLayerDataZip.PAYLOAD_HEADER.toByteString()}, got ${pldBuffer4.toByteString()}") - - // get payload's name - inputStream.read(pldBuffer4) - val payloadName = pldBuffer4.toString(Charset.forName("US-ASCII")) - - printdbg(this, "Payload $pldCnt name: $payloadName") // maybe maybe related with buffer things? - - // get uncompressed size - inputStream.read(pldBuffer6) - val uncompressedSize = pldBuffer6.toLittleInt48() - - // get deflated size - inputStream.mark(2147483647) // FIXME deflated stream cannot be larger than 2 GB - // creep forward until we hit the PAYLOAD_FOOTER - var deflatedSize: Int = 0 // FIXME deflated stream cannot be larger than 2 GB - // loop init - inputStream.read(pldBuffer8) - // loop main - while (!pldBuffer8.contentEquals(WriteLayerDataZip.PAYLOAD_FOOTER)) { - val aByte = inputStream.read(); deflatedSize += 1 - if (aByte == -1) throw InternalError("Unexpected end-of-file at payload $pldCnt") - pldBuffer8.shiftLeftBy(1, aByte.toByte()) - } - - // at this point, we should have correct size of deflated bytestream - - printdbg(this, "Payload $pldCnt compressed size: $deflatedSize") - - val deflatedBytes = ByteArray(deflatedSize) // FIXME deflated stream cannot be larger than 2 GB - inputStream.reset() // go back to marked spot - inputStream.read(deflatedBytes) - - // PRO Debug tip: every deflated bytes must begin with 0x789C or 0x78DA - // Thus, \0pLd + [10] must be either of these. - - // put constructed payload into a container - payloads.put(payloadName, TEMzPayload(uncompressedSize, deflatedBytes)) - - // skip over to be aligned with the next payload - inputStream.skip(8) - } - - - // test for EOF - inputStream.read(pldBuffer8) - if (!pldBuffer8.contentEquals(WriteLayerDataZip.FILE_FOOTER)) - throw InternalError("Expected end-of-file, got not-so-end-of-file")*/ - - - ////////////////////// - // END OF FILE READ // - ////////////////////// - - val worldSize = width.toLong() * height - - val payloadBytes = HashMap() - - payloads.forEach { t, u -> - val inflatedOS = ByteArrayOutputStream(u.uncompressedSize.toInt()) // FIXME deflated stream cannot be larger than 2 GB - - try { - Lzma.decompress(ByteArrayInputStream(u.bytes), inflatedOS) - } - catch (e: RuntimeException) { - // keep it empty (zero-sized file was compressed) - } - - val inflatedFile = inflatedOS.toByteArray() - - payloadBytes[t] = inflatedFile - } - - val spawnPoint = LandUtil.resolveBlockAddr(width, spawnAddress) - - val terrainDamages = HashMap() - val wallDamages = HashMap() - val fluidTypes = HashMap() - val fluidFills = HashMap() - val tileNumToName = HashMap() - - // parse terrain damages - for (c in payloadBytes["TdMG"]!!.indices step 10) { - val bytes = payloadBytes["TdMG"]!! - - val tileAddr = bytes.sliceArray(c..c+5) - val value = bytes.sliceArray(c+6..c+9) - - terrainDamages[tileAddr.toLittleInt48()] = value.toLittleFloat() - } - - - // parse wall damages - for (c in payloadBytes["WdMG"]!!.indices step 10) { - val bytes = payloadBytes["WdMG"]!! - - val tileAddr = bytes.sliceArray(c..c+5) - val value = bytes.sliceArray(c+6..c+9) - - wallDamages[tileAddr.toLittleInt48()] = value.toLittleFloat() - } - - - // TODO parse fluid(Types|Fills) - - // TODO parse tileNumToName - - - return ReadLayerDataZip.LayerData( - BlockLayer(width, height, payloadBytes["WALL"]!!), - BlockLayer(width, height, payloadBytes["TERR"]!!), - - spawnPoint.first, spawnPoint.second, - - wallDamages, terrainDamages, fluidTypes, fluidFills, tileNumToName - ) - } - - internal fun InputStream.readRelative(b: ByteArray, off: Int, len: Int): Int { - if (b == null) { - throw NullPointerException() - } else if (off < 0 || len < 0 || len > b.size) { - throw IndexOutOfBoundsException() - } else if (len == 0) { - return 0 - } - - var c = read() - if (c == -1) { - return -1 - } - b[0] = c.toByte() - - var i = 1 - try { - while (i < len) { - c = read() - if (c == -1) { - break - } - b[i] = c.toByte() - i++ - } - } catch (ee: IOException) { - } - - return i - } -} \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/ReadLayerDataZip.kt b/src/net/torvald/terrarum/serialise/ReadLayerDataZip.kt deleted file mode 100644 index b145aa682..000000000 --- a/src/net/torvald/terrarum/serialise/ReadLayerDataZip.kt +++ /dev/null @@ -1,243 +0,0 @@ -package net.torvald.terrarum.serialise - -import net.torvald.terrarum.AppLoader.printdbg -import net.torvald.terrarum.gameitem.ItemID -import net.torvald.terrarum.gameworld.BlockAddress -import net.torvald.terrarum.gameworld.BlockLayer -import net.torvald.terrarum.gameworld.FluidType -import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read -import net.torvald.terrarum.realestate.LandUtil -import java.io.File -import java.io.FileInputStream -import java.io.IOException -import java.io.InputStream -import java.util.* -import java.util.zip.Inflater -import kotlin.collections.HashMap - -/** - * Created by minjaesong on 2016-08-24. - */ -// internal for everything: prevent malicious module from messing up the savedata -internal object ReadLayerDataZip { - - // FIXME TERRAIN DAMAGE UNTESTED - - internal operator fun invoke(file: File): LayerData { - val inputStream = MarkableFileInputStream(FileInputStream(file)) - - - val magicBytes = ByteArray(4) - - - ////////////////// - // FILE READING // - ////////////////// - - - // read header first - inputStream.read(magicBytes) - if (!Arrays.equals(magicBytes, WriteLayerDataZip.MAGIC)) { - throw IllegalArgumentException("File not a Layer Data") - } - - val versionNumber = inputStream.read(1)[0].toUint() - val layerCount = inputStream.read(1)[0].toUint() - val payloadCount = inputStream.read(1)[0].toUint() - val compression = inputStream.read(1)[0].toUint() - val generatorVer = inputStream.read(2).toULittleShort() - val width = inputStream.read(4).toLittleInt() - val height = inputStream.read(4).toLittleInt() - val spawnAddress = inputStream.read(6).toLittleInt48() - - if (compression != 1) throw IllegalArgumentException("Input file is not compressed as DEFLATE; it's using algorithm $compression") - - printdbg(this, "Version number: $versionNumber") - printdbg(this, "Layers count: $layerCount") - printdbg(this, "Payloads count: $payloadCount") - printdbg(this, "Compression: $compression") - printdbg(this, "World generator version: $generatorVer") - printdbg(this, "Dimension: ${width}x$height") - - // read payloads - - val payloads = PayloadUtil.readAll(inputStream) - /*val pldBuffer4 = ByteArray(4) - val pldBuffer6 = ByteArray(6) - val pldBuffer8 = ByteArray(8) - - val payloads = HashMap() - - - // TODO please test the read; write has been fixed up - - for (pldCnt in 0 until payloadCount) { - inputStream.read(pldBuffer4) - - // check payload header - if (!pldBuffer4.contentEquals(WriteLayerDataZip.PAYLOAD_HEADER)) - throw InternalError("Payload $pldCnt not found -- expected ${WriteLayerDataZip.PAYLOAD_HEADER.toByteString()}, got ${pldBuffer4.toByteString()}") - - // get payload's name - inputStream.read(pldBuffer4) - val payloadName = pldBuffer4.toString(Charset.forName("US-ASCII")) - - printdbg(this, "Payload $pldCnt name: $payloadName") // maybe maybe related with buffer things? - - // get uncompressed size - inputStream.read(pldBuffer6) - val uncompressedSize = pldBuffer6.toLittleInt48() - - // get deflated size - inputStream.mark(2147483647) // FIXME deflated stream cannot be larger than 2 GB - // creep forward until we hit the PAYLOAD_FOOTER - var deflatedSize: Int = 0 // FIXME deflated stream cannot be larger than 2 GB - // loop init - inputStream.read(pldBuffer8) - // loop main - while (!pldBuffer8.contentEquals(WriteLayerDataZip.PAYLOAD_FOOTER)) { - val aByte = inputStream.read(); deflatedSize += 1 - if (aByte == -1) throw InternalError("Unexpected end-of-file at payload $pldCnt") - pldBuffer8.shiftLeftBy(1, aByte.toByte()) - } - - // at this point, we should have correct size of deflated bytestream - - printdbg(this, "Payload $pldCnt compressed size: $deflatedSize") - - val deflatedBytes = ByteArray(deflatedSize) // FIXME deflated stream cannot be larger than 2 GB - inputStream.reset() // go back to marked spot - inputStream.read(deflatedBytes) - - // PRO Debug tip: every deflated bytes must begin with 0x789C or 0x78DA - // Thus, \0pLd + [10] must be either of these. - - // put constructed payload into a container - payloads.put(payloadName, TEMzPayload(uncompressedSize, deflatedBytes)) - - // skip over to be aligned with the next payload - inputStream.skip(8) - } - - - // test for EOF - inputStream.read(pldBuffer8) - if (!pldBuffer8.contentEquals(WriteLayerDataZip.FILE_FOOTER)) - throw InternalError("Expected end-of-file, got not-so-end-of-file")*/ - - - ////////////////////// - // END OF FILE READ // - ////////////////////// - - val worldSize = width.toLong() * height - - val payloadBytes = HashMap() - - payloads.forEach { t, u -> - val inflatedFile = ByteArray(u.uncompressedSize.toInt()) // FIXME deflated stream cannot be larger than 2 GB - val inflater = Inflater() - inflater.setInput(u.bytes, 0, u.bytes.size) - val uncompLen = inflater.inflate(inflatedFile) - - // just in case - if (uncompLen.toLong() != u.uncompressedSize) - throw InternalError("Payload $t DEFLATE size mismatch -- expected ${u.uncompressedSize}, got $uncompLen") - - payloadBytes[t] = inflatedFile - } - - val spawnPoint = LandUtil.resolveBlockAddr(width, spawnAddress) - - val terrainDamages = HashMap() - val wallDamages = HashMap() - val fluidTypes = HashMap() - val fluidFills = HashMap() - val tileNumberToNameMap = HashMap() - - // parse terrain damages - for (c in payloadBytes["TdMG"]!!.indices step 10) { - val bytes = payloadBytes["TdMG"]!! - - val tileAddr = bytes.sliceArray(c..c+5) - val value = bytes.sliceArray(c+6..c+9) - - terrainDamages[tileAddr.toLittleInt48()] = value.toLittleFloat() - } - - - // parse wall damages - for (c in payloadBytes["WdMG"]!!.indices step 10) { - val bytes = payloadBytes["WdMG"]!! - - val tileAddr = bytes.sliceArray(c..c+5) - val value = bytes.sliceArray(c+6..c+9) - - wallDamages[tileAddr.toLittleInt48()] = value.toLittleFloat() - } - - - // TODO parse fluid(Types|Fills) - - - return LayerData( - BlockLayer(width, height, payloadBytes["WALL"]!!), - BlockLayer(width, height, payloadBytes["TERR"]!!), - - spawnPoint.first, spawnPoint.second, - - wallDamages, terrainDamages, fluidTypes, fluidFills, tileNumberToNameMap - ) - } - - /** - * Immediately deployable, a part of the gameworld - */ - internal data class LayerData( - val layerWall: BlockLayer, - val layerTerrain: BlockLayer, - //val layerThermal: MapLayerHalfFloat, // in Kelvins - //val layerAirPressure: MapLayerHalfFloat, // (milibar - 1000) - - val spawnX: Int, - val spawnY: Int, - - //val wirings: HashMap>, - val wallDamages: HashMap, - val terrainDamages: HashMap, - val fluidTypes: HashMap, - val fluidFills: HashMap, - val tileNumberToNameMap: HashMap - ) - - internal fun InputStream.readRelative(b: ByteArray, off: Int, len: Int): Int { - if (b == null) { - throw NullPointerException() - } else if (off < 0 || len < 0 || len > b.size) { - throw IndexOutOfBoundsException() - } else if (len == 0) { - return 0 - } - - var c = read() - if (c == -1) { - return -1 - } - b[0] = c.toByte() - - var i = 1 - try { - while (i < len) { - c = read() - if (c == -1) { - break - } - b[i] = c.toByte() - i++ - } - } catch (ee: IOException) { - } - - return i - } -} diff --git a/src/net/torvald/terrarum/serialise/ReadWorldInfo.kt b/src/net/torvald/terrarum/serialise/ReadWorldInfo.kt deleted file mode 100644 index 0614a4445..000000000 --- a/src/net/torvald/terrarum/serialise/ReadWorldInfo.kt +++ /dev/null @@ -1,84 +0,0 @@ -package net.torvald.terrarum.serialise - -import com.badlogic.gdx.graphics.Pixmap -import com.badlogic.gdx.graphics.Texture -import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.DiskSkimmer.Companion.read -import java.io.File -import java.io.FileInputStream -import java.util.* - - -object ReadWorldInfo { - - // FIXME UNTESTED - - internal operator fun invoke(file: File): SaveMetaData { - - val magic = ByteArray(4) - val worldNameUTF8 = ArrayList() - - val fis = FileInputStream(file) - - fis.read(magic) - if (!Arrays.equals(magic, WriteWorldInfo.META_MAGIC)) { - throw IllegalArgumentException("File not a Save Meta") - } - - - val descVersion = fis.read(1) // 0-127 - val numberOfHashes = fis.read() // 0-127 - - - var byteRead = fis.read() - while (byteRead != 0) { - if (byteRead == -1) - throw InternalError("Unexpected EOF") - - worldNameUTF8.add(byteRead.toByte()) - byteRead = fis.read() - } - - return SaveMetaData( - String(worldNameUTF8.toByteArray(), Charsets.UTF_8), - fis.read(8).toLittleLong(), // terrain seed - fis.read(8).toLittleLong(), // rng s0 - fis.read(8).toLittleLong(), // rng s1 - fis.read(8).toLittleLong(), // weather s0 - fis.read(8).toLittleLong(), // weather s1 - fis.read(4).toLittleInt(), // player id - fis.read(8).toLittleLong(), // world TIME_T - fis.read(6).toLittleLong(), // creation time - fis.read(6).toLittleLong(), // last play time - fis.read(4).toLittleInt(), // total time wasted - fis.read(32), // sha256sum worldinfo1 - fis.read(32), // sha256sum worldinfo2 - fis.read(32) // sha256sum worldinfo3 - ) - } - - - data class SaveMetaData( - val worldName: String, - val terrainSeed: Long, - val rngS0: Long, - val rngS1: Long, - val weatherS0: Long, - val weatherS1: Long, - val playerID: Int, - val timeNow: Long, - val creationTime: Long, - val lastPlayTime: Long, - val totalPlayTime: Int, - val worldinfo1Hash: ByteArray, - val worldInfo2Hash: ByteArray, - val worldInfo3Hash: ByteArray, - - // gzipped TGA in meta - val thumbnail: Texture = Texture(2, 2, Pixmap.Format.RGBA8888), - // skim through the virtualdisk entries - val worldCount: Int = 1, - // read from the entry file - val playerName: String = "Savegame", - val playerWallet: Int = 0 - ) -} \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/SavegameLoader.kt b/src/net/torvald/terrarum/serialise/SavegameReader.kt similarity index 84% rename from src/net/torvald/terrarum/serialise/SavegameLoader.kt rename to src/net/torvald/terrarum/serialise/SavegameReader.kt index 857766afd..39753f169 100644 --- a/src/net/torvald/terrarum/serialise/SavegameLoader.kt +++ b/src/net/torvald/terrarum/serialise/SavegameReader.kt @@ -3,7 +3,7 @@ package net.torvald.terrarum.serialise /** * Created by minjaesong on 2018-10-03. */ -object SavegameLoader { +object SavegameReader { // TODO read TEVd, load necessary shits diff --git a/src/net/torvald/terrarum/serialise/SavegameWriter.kt b/src/net/torvald/terrarum/serialise/SavegameWriter.kt index 58776daf4..122a06533 100644 --- a/src/net/torvald/terrarum/serialise/SavegameWriter.kt +++ b/src/net/torvald/terrarum/serialise/SavegameWriter.kt @@ -9,7 +9,6 @@ import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameitem.GameItem import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.* -import net.torvald.terrarum.utils.JsonWriter.getJsonBuilder import net.torvald.util.SortedArrayList import java.io.File import java.nio.charset.Charset @@ -77,76 +76,17 @@ object SavegameWriter { // serialise current world (stage) - val worldBytes = WriteLayerDataZip(gameworld) // filename can be anything that is "world[n]" where [n] is any number - if (worldBytes == null) { - throw Error("Serialising world failed") - } - if (!worldBytes.sliceArray(0..3).contentEquals(WriteLayerDataZip.MAGIC)) { - worldBytes.forEach { - print(it.toUInt().and(255u).toString(16).toUpperCase().padStart(2, '0')) - print(' ') - }; println() - throw Error() - } - - // add current world (stage) to the disk - VDUtil.registerFile(disk, DiskEntry( - gameworld.worldIndex, ROOT, - "world${gameworld.worldIndex}".toByteArray(charset), - creationDate, creationDate, - EntryFile(worldBytes) - )) - - - - // TODO world[n] is done, needs whole other things - - - // worldinfo0..3 - val worldinfoBytes = WriteWorldInfo(ingame) - worldinfoBytes?.forEachIndexed { index, bytes -> - VDUtil.registerFile(disk, DiskEntry( - 32766 - index, ROOT, "worldinfo$index".toByteArray(charset), - creationDate, creationDate, - EntryFile(bytes) - )) - } ?: throw Error("Serialising worldinfo failed") - - // loadorder.txt - VDUtil.registerFile(disk, DiskEntry( - 32767, ROOT, "load_order.txt".toByteArray(charset), - creationDate, creationDate, - EntryFile(ByteArray64.fromByteArray(Gdx.files.internal("./assets/mods/LoadOrder.csv").readBytes())) - )) - - // actors - ingame.actorContainerActive.forEach { - VDUtil.registerFile(disk, DiskEntry( - rngPool.next(), ROOT, - it.referenceID.toString(16).toUpperCase().toByteArray(charset), - creationDate, creationDate, - EntryFile(serialiseActor(it)) - )) - } - ingame.actorContainerInactive.forEach { - VDUtil.registerFile(disk, DiskEntry( - rngPool.next(), ROOT, - it.referenceID.toString(16).toUpperCase().toByteArray(charset), - creationDate, creationDate, - EntryFile(serialiseActor(it)) - )) - } // items - ItemCodex.dynamicItemDescription.forEach { dynamicID, item -> + /*ItemCodex.dynamicItemDescription.forEach { dynamicID, item -> VDUtil.registerFile(disk, DiskEntry( rngPool.next(), ROOT, dynamicID.toByteArray(charset), creationDate, creationDate, EntryFile(serialiseItem(item)) )) - } + }*/ System.gc() @@ -156,14 +96,79 @@ object SavegameWriter { fun modifyExistingSave(savefile: File): VirtualDisk { TODO() } +} - private fun serialiseActor(a: Actor): ByteArray64 { - val gson = getJsonBuilder().toJson(a).toByteArray(charset) - return ByteArray64.fromByteArray(gson) - } +fun Int.toLittle() = byteArrayOf( + this.and(0xFF).toByte(), + this.ushr(8).and(0xFF).toByte(), + this.ushr(16).and(0xFF).toByte(), + this.ushr(24).and(0xFF).toByte() +) +/** Converts int as 2-byte array, discarding the sign.*/ +fun Int.toULittleShort() = byteArrayOf( + this.and(0xFF).toByte(), + this.ushr(8).and(0xFF).toByte() +) +/** Converts int as 2-byte array, preserving the sign. In other words, it converts int to short. */ +fun Int.toLittleShort() = byteArrayOf( + this.and(0xFF).toByte(), + this.shr(8).and(0xFF).toByte() +) +fun Long.toLittle() = byteArrayOf( + this.and(0xFF).toByte(), + this.ushr(8).and(0xFF).toByte(), + this.ushr(16).and(0xFF).toByte(), + this.ushr(24).and(0xFF).toByte(), + this.ushr(32).and(0xFF).toByte(), + this.ushr(40).and(0xFF).toByte(), + this.ushr(48).and(0xFF).toByte(), + this.ushr(56).and(0xFF).toByte() +) +/** Converts long as 6-byte array, discarding the sign. */ +fun Long.toULittle48() = byteArrayOf( + this.and(0xFF).toByte(), + this.ushr(8).and(0xFF).toByte(), + this.ushr(16).and(0xFF).toByte(), + this.ushr(24).and(0xFF).toByte(), + this.ushr(32).and(0xFF).toByte(), + this.ushr(40).and(0xFF).toByte() +) +fun Double.toLittle() = java.lang.Double.doubleToRawLongBits(this).toLittle() +fun Boolean.toLittle() = byteArrayOf(if (this) 0xFF.toByte() else 0.toByte()) - private fun serialiseItem(i: GameItem): ByteArray64 { - val gson = getJsonBuilder().toJson(i).toByteArray(charset) - return ByteArray64.fromByteArray(gson) - } -} \ No newline at end of file +fun ByteArray.toLittleInt() = + if (this.size != 4) throw Error("Array not in size of 4") + else this[0].toUint() or + this[1].toUint().shl(8) or + this[2].toUint().shl(16) or + this[3].toUint().shl(24) +fun ByteArray.toULittleShort() = + if (this.size != 4) throw Error("Array not in size of 2") + else this[0].toUint() or + this[1].toUint().shl(8) +fun ByteArray.toLittleShort() = + if (this.size != 4) throw Error("Array not in size of 2") + else this[0].toUint() or + this[1].toInt().shl(8) +fun ByteArray.toLittleLong() = + if (this.size != 8) throw Error("Array not in size of 8") + else this[0].toUlong() or + this[1].toUlong().shl(8) or + this[2].toUlong().shl(16) or + this[3].toUlong().shl(24) or + this[4].toUlong().shl(32) or + this[5].toUlong().shl(40) or + this[6].toUlong().shl(48) or + this[7].toUlong().shl(56) +fun ByteArray.toLittleInt48() = + if (this.size != 6) throw Error("Array not in size of 6") + else this[0].toUlong() or + this[1].toUlong().shl(8) or + this[2].toUlong().shl(16) or + this[3].toUlong().shl(24) or + this[4].toUlong().shl(32) or + this[5].toUlong().shl(40) +fun ByteArray.toLittleFloat() = java.lang.Float.intBitsToFloat(this.toLittleInt()) + +fun Byte.toUlong() = java.lang.Byte.toUnsignedLong(this) +fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this) \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/WriteCSV.kt b/src/net/torvald/terrarum/serialise/WriteCSV.kt deleted file mode 100644 index f88c7d30e..000000000 --- a/src/net/torvald/terrarum/serialise/WriteCSV.kt +++ /dev/null @@ -1,61 +0,0 @@ -package net.torvald.terrarum.serialise - -import net.torvald.terrarum.AppLoader -import java.io.IOException -import java.nio.file.Files -import java.nio.file.Paths -import java.nio.file.StandardCopyOption - -/** - * Created by minjaesong on 2016-03-18. - */ -// internal for everything: prevent malicious module from messing up the savedata -internal object WriteCSV { - val META_FILENAME_TILE = "worldinfo2" - val META_FILENAME_ITEM = "worldinfo3" - val META_FILENAME_MAT = "worldinfo4" - - internal fun write(saveDirectoryName: String): Boolean { - //val tileCSV = CSVFetcher.readCSVasString(BlockCodex.CSV_PATH) - //val itemCSV = CSVFetcher.readCSVasString(ItemCodex.CSV_PATH) - //val matCSV = CSVFetcher.readCSVasString(MaterialCodex.CSV_PATH) - - val pathTile = Paths.get("${AppLoader.defaultSaveDir}" + - "/$saveDirectoryName/${META_FILENAME_TILE}") - val pathItem = Paths.get("${AppLoader.defaultSaveDir}" + - "/$saveDirectoryName/${META_FILENAME_ITEM}") - val pathMat = Paths.get("${AppLoader.defaultSaveDir}" + - "/$saveDirectoryName/${META_FILENAME_MAT}") - val tempPathTile = Files.createTempFile(pathTile.toString(), "_temp") - val tempPathItem = Files.createTempFile(pathItem.toString(), "_temp") - val tempPathMat = Files.createTempFile(pathMat.toString(), "_temp") - - // TODO gzip - - // write CSV to path - //Files.write(tempPathTile, tileCSV.toByteArray(Charsets.UTF_8)) - //Files.write(tempPathItem, itemCSV.toByteArray(Charsets.UTF_8)) - //Files.write(tempPathMat, matCSV.toByteArray(Charsets.UTF_8)) - - // replace savemeta with tempfile - try { - Files.copy(tempPathTile, pathTile, StandardCopyOption.REPLACE_EXISTING) - Files.deleteIfExists(tempPathTile) - - Files.copy(tempPathItem, pathItem, StandardCopyOption.REPLACE_EXISTING) - Files.deleteIfExists(tempPathItem) - - Files.copy(tempPathMat, pathMat, StandardCopyOption.REPLACE_EXISTING) - Files.deleteIfExists(tempPathMat) - - println("Saved map data '${WriteLayerData.LAYERS_FILENAME}' to $saveDirectoryName.") - - return true - } - catch (e: IOException) { - e.printStackTrace() - } - return false - } - -} \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/WriteLayerData.kt b/src/net/torvald/terrarum/serialise/WriteLayerData.kt deleted file mode 100644 index 5bbfd8863..000000000 --- a/src/net/torvald/terrarum/serialise/WriteLayerData.kt +++ /dev/null @@ -1,85 +0,0 @@ -package net.torvald.terrarum.serialise - -/** - * TODO this one does not use TerranVirtualDisk - * - * Created by minjaesong on 2016-03-18. - */ -// internal for everything: prevent malicious module from messing up the savedata -@Deprecated("TEMD is old and removed format; use TEMz which does compression") -internal object WriteLayerData { - - init { - throw Error("TEMD is old and removed format; use TEMz which does compression") - } - - val LAYERS_FILENAME = "worldinfo1" - - /*val MAGIC = "TEMD".toByteArray(charset = Charset.forName("US-ASCII")) - - val BYTE_NULL: Byte = 0 - - - internal operator fun invoke(saveDirectoryName: String): Boolean { - val path = "${AppLoader.defaultSaveDir}/$saveDirectoryName/${LAYERS_FILENAME}" - val tempPath = "${path}_bak" - val map = (Terrarum.ingame!!.world) - - val parentDir = File("${AppLoader.defaultSaveDir}/$saveDirectoryName") - if (!parentDir.exists()) { - parentDir.mkdir() - } - else if (!parentDir.isDirectory) { - EchoError("Savegame directory is not actually a directory, aborting...") - return false - } - - val tempFile = File(tempPath) - val outFile = File(path) - tempFile.createNewFile() - - val outputStream = GZIPOutputStream(FileOutputStream(tempFile)) - - - // write binary - outputStream.write(MAGIC) - outputStream.write(byteArrayOf(GameWorld.SIZEOF)) - outputStream.write(byteArrayOf(GameWorld.LAYERS)) - outputStream.write(byteArrayOf(BYTE_NULL)) - outputStream.write(byteArrayOf(BYTE_NULL)) - outputStream.write(map.width.toLittle()) - outputStream.write(map.height.toLittle()) - outputStream.write(map.spawnX.toLittle()) - outputStream.write(map.spawnY.toLittle()) - // write one row (byteArray) at a time - outputStream.write(map.layerTerrain.data) - outputStream.write(map.layerWall.data) - outputStream.write(map.layerTerrainLowBits.data) - outputStream.write(map.layerWallLowBits.data) - - // replace savemeta with tempfile - try { - outputStream.flush() - outputStream.close() - - outFile.delete() - tempFile.copyTo(outFile, overwrite = true) - tempFile.delete() - println("Saved map data '$LAYERS_FILENAME' to $saveDirectoryName.") - - return true - } - catch (e: IOException) { - e.printStackTrace() - } - finally { - outputStream.close() - } - - return false - }*/ - - -} - -const val WORLD_WRITER_FORMAT_VERSION = 3 \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/WriteLayerDataLzma.kt b/src/net/torvald/terrarum/serialise/WriteLayerDataLzma.kt deleted file mode 100644 index 3f99b9b63..000000000 --- a/src/net/torvald/terrarum/serialise/WriteLayerDataLzma.kt +++ /dev/null @@ -1,208 +0,0 @@ -package net.torvald.terrarum.serialise - -import com.badlogic.gdx.utils.compression.Lzma -import net.torvald.terrarum.AppLoader -import net.torvald.terrarum.Terrarum -import net.torvald.terrarum.realestate.LandUtil -import net.torvald.terrarum.serialise.WriteLayerDataZip.FILE_FOOTER -import net.torvald.terrarum.serialise.WriteLayerDataZip.PAYLOAD_FOOTER -import net.torvald.terrarum.serialise.WriteLayerDataZip.PAYLOAD_HEADER -import java.io.* -import java.util.zip.DeflaterOutputStream - -/** - * This object only writes a file named 'worldinfo1'. - * - * The intended operation is as follows: - * 1. This and others write - * - * TODO temporarily dump on the disk THEN pack? Or put all the files (in ByteArray64) in the RAM THEN pack? - * - * Created by minjaesong on 2016-03-18. - */ -// internal for everything: prevent malicious module from messing up the savedata -internal object WriteLayerDataLzma { - - // FIXME TERRAIN DAMAGE UNTESTED - - - // 2400x800 world size: about .. kB - // 8192x2048 world size: about 470 kB but writes much slower than DEFLATE - - - val LAYERS_FILENAME = "world" - - val MAGIC = byteArrayOf(0x54, 0x45, 0x4D, 0x7A) - val VERSION_NUMBER = WORLD_WRITER_FORMAT_VERSION.toByte() - val NUMBER_OF_LAYERS = 3.toByte() - val NUMBER_OF_PAYLOADS = 5.toByte() - val COMPRESSION_ALGORITHM = 2.toByte() - val GENERATOR_VERSION = WORLD_GENERATOR_VERSION.toULittleShort() - - //val NULL: Byte = 0 - - - /** - * TODO currently it'll dump the temporary file (tmp_worldinfo1) onto the disk and will return the temp file. - * - * @return File on success; `null` on failure - */ - internal operator fun invoke(): File? { - val world = (Terrarum.ingame!!.world) - - val path = "${AppLoader.defaultSaveDir}/tmp_$LAYERS_FILENAME${world.worldIndex}" - - // TODO let's try dump-on-the-disk-then-pack method... - - /*val parentDir = File("${AppLoader.defaultSaveDir}/$saveDirectoryName") - if (!parentDir.exists()) { - parentDir.mkdir() - } - else if (!parentDir.isDirectory) { - EchoError("Savegame directory is not actually a directory, aborting...") - return false - }*/ - - - val outFile = File(path) - if (outFile.exists()) outFile.delete() - outFile.createNewFile() - - val outputStream = BufferedOutputStream(FileOutputStream(outFile), 8192) - var deflater: DeflaterOutputStream // couldn't really use one outputstream for all the files. - - fun wb(byteArray: ByteArray) { outputStream.write(byteArray) } - fun wb(byte: Byte) { outputStream.write(byte.toInt()) } - //fun wb(byte: Int) { outputStream.write(byte) } - fun wi32(int: Int) { wb(int.toLittle()) } - fun wi48(long: Long) { wb(long.toULittle48()) } - fun wi64(long: Long) { wb(long.toLittle()) } - fun wf32(float: Float) { wi32(float.toRawBits()) } - - - //////////////////// - // WRITE BINARIES // - //////////////////// - - - // all the necessary headers - wb(MAGIC); wb(VERSION_NUMBER); wb(NUMBER_OF_LAYERS); wb(NUMBER_OF_PAYLOADS); wb(COMPRESSION_ALGORITHM); wb(GENERATOR_VERSION) - - // world width, height, and spawn point - wi32(world.width); wi32(world.height) - wi48(LandUtil.getBlockAddr(world, world.spawnX, world.spawnY)) - - // write payloads // - outputStream.flush() - - // TERR payload - // PRO Debug tip: every deflated bytes must begin with 0x789C or 0x78DA - // Thus, \0pLd + [10] must be either of these. - - wb(PAYLOAD_HEADER); wb("TERR".toByteArray()) - wi48(world.width * world.height * 3L / 2) - world.layerTerrain.bytesIterator().forEach { - val tempByteArray = ByteArray(1) - tempByteArray[0] = it - val tempByteArrayStream = ByteArrayInputStream(tempByteArray) - Lzma.compress(tempByteArrayStream, outputStream) - } - wb(PAYLOAD_FOOTER) - - // WALL payload - wb(PAYLOAD_HEADER); wb("WALL".toByteArray()) - wi48(world.width * world.height * 3L / 2) - world.layerWall.bytesIterator().forEach { - val tempByteArray = ByteArray(1) - tempByteArray[0] = it - val tempByteArrayStream = ByteArrayInputStream(tempByteArray) - Lzma.compress(tempByteArrayStream, outputStream) - } - wb(PAYLOAD_FOOTER) - - // WIRE payload - /*wb(PAYLOAD_HEADER); wb("WIRE".toByteArray()) - wi48(world.width * world.height.toLong()) - Lzma.compress(ByteArrayInputStream(world.wireArray), outputStream) - wb(PAYLOAD_FOOTER)*/ - - // TdMG payload - wb(PAYLOAD_HEADER); wb("TdMG".toByteArray()) - wi48(world.terrainDamages.size * 10L) - - - world.terrainDamages.forEach { t, u -> - Lzma.compress(ByteArrayInputStream(t.toULittle48()), outputStream) - Lzma.compress(ByteArrayInputStream(u.toRawBits().toLittle()), outputStream) - } - - wb(PAYLOAD_FOOTER) - - // WdMG payload - wb(PAYLOAD_HEADER); wb("WdMG".toByteArray()) - wi48(world.wallDamages.size * 10L) - - - world.wallDamages.forEach { t, u -> - Lzma.compress(ByteArrayInputStream(t.toULittle48()), outputStream) - Lzma.compress(ByteArrayInputStream(u.toRawBits().toLittle()), outputStream) - } - - wb(PAYLOAD_FOOTER) - - // FlTP payload - wb(PAYLOAD_HEADER); wb("FlTP".toByteArray()) - wi48(world.fluidTypes.size * 8L) - - - world.fluidTypes.forEach { t, u -> - Lzma.compress(ByteArrayInputStream(t.toULittle48()), outputStream) - Lzma.compress(ByteArrayInputStream(u.value.toLittleShort()), outputStream) - } - - wb(PAYLOAD_FOOTER) - - // FlFL payload - wb(PAYLOAD_HEADER); wb("FlFL".toByteArray()) - wi48(world.fluidFills.size * 10L) - - - world.fluidFills.forEach { t, u -> - Lzma.compress(ByteArrayInputStream(t.toULittle48()), outputStream) - Lzma.compress(ByteArrayInputStream(u.toRawBits().toLittle()), outputStream) - } - - wb(PAYLOAD_FOOTER) - - - - // write footer - wb(FILE_FOOTER) - - - ////////////////// - // END OF WRITE // - ////////////////// - - - - // replace savemeta with tempfile - try { - outputStream.flush() - outputStream.close() - - - return outFile - } - catch (e: IOException) { - e.printStackTrace() - } - finally { - outputStream.close() - } - - return null - } - - -} diff --git a/src/net/torvald/terrarum/serialise/WriteLayerDataZip.kt b/src/net/torvald/terrarum/serialise/WriteLayerDataZip.kt deleted file mode 100644 index 04e57a2a9..000000000 --- a/src/net/torvald/terrarum/serialise/WriteLayerDataZip.kt +++ /dev/null @@ -1,208 +0,0 @@ -package net.torvald.terrarum.serialise - -import net.torvald.terrarum.AppLoader.printdbg -import net.torvald.terrarum.gameworld.GameWorld -import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64 -import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64GrowableOutputStream -import net.torvald.terrarum.realestate.LandUtil -import java.util.zip.Deflater -import java.util.zip.DeflaterOutputStream - -/** - * This object only writes a file named 'worldinfo1'. - * - * The intended operation is as follows: - * 1. This and others write - * - * TODO temporarily dump on the disk THEN pack? Or put all the files (in ByteArray64) in the RAM THEN pack? - * - * Created by minjaesong on 2016-03-18. - */ -// internal for everything: prevent malicious module from messing up the savedata -internal object WriteLayerDataZip { - - // FIXME TERRAIN DAMAGE UNTESTED - - - // 2400x800 world size, default comp level: about 90 kB - // 8192x2048 world size, default comp level: about 670 kB - - // 2400x800 world size, best comp level: about 75 kB - // 8192x2048 world size, best comp level: about 555 kB - - val LAYERS_FILENAME = "world" - - val MAGIC = byteArrayOf(0x54, 0x45, 0x4D, 0x7A) - val VERSION_NUMBER = WORLD_WRITER_FORMAT_VERSION.toByte() - val NUMBER_OF_LAYERS = 3.toByte() - val NUMBER_OF_PAYLOADS = 5.toByte() - val COMPRESSION_ALGORITHM = 1.toByte() - val GENERATOR_VERSION = WORLD_GENERATOR_VERSION.toULittleShort() - val PAYLOAD_HEADER = byteArrayOf(0, 0x70, 0x4C, 0x64) // \0pLd - val PAYLOAD_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x50, 0x59, 0x4C, 0x64, -1) // EndPYLd\xFF - val FILE_FOOTER = byteArrayOf(0x45, 0x6E, 0x64, 0x54, 0x45, 0x4D, -1, -2) // EndTEM with BOM - - //val NULL: Byte = 0 - - - /** - * @param world The world to serialise - * @param path The directory where the temporary file goes, in relative to the AppLoader.defaultSaveDir. Should NOT start with slashed - * - * @return File on success; `null` on failure - */ - internal operator fun invoke(world: GameWorld): ByteArray64? { - //val sanitisedPath = path.replace('\\', '/').removePrefix("/").replace("../", "") - - //val path = "${AppLoader.defaultSaveDir}/$sanitisedPath/tmp_$LAYERS_FILENAME${world.worldIndex}" - //val path = "${AppLoader.defaultSaveDir}/tmp_$LAYERS_FILENAME${world.worldIndex}" - - // TODO let's try dump-on-the-disk-then-pack method... - - /*val parentDir = File("${AppLoader.defaultSaveDir}/$saveDirectoryName") - if (!parentDir.exists()) { - parentDir.mkdir() - } - else if (!parentDir.isDirectory) { - EchoError("Savegame directory is not actually a directory, aborting...") - return false - }*/ - - - //val outFile = File(path) - //if (outFile.exists()) outFile.delete() - //outFile.createNewFile() - - //val outputStream = BufferedOutputStream(FileOutputStream(outFile), 8192) - val outputStream = ByteArray64GrowableOutputStream() - var deflater: DeflaterOutputStream // couldn't really use one outputstream for all the files. - - fun wb(byteArray: ByteArray) { outputStream.write(byteArray) } - fun wb(byte: Byte) { outputStream.write(byte.toInt()) } - //fun wb(byte: Int) { outputStream.write(byte) } - fun wi32(int: Int) { wb(int.toLittle()) } - fun wi48(long: Long) { wb(long.toULittle48()) } - fun wi64(long: Long) { wb(long.toLittle()) } - fun wf32(float: Float) { wi32(float.toRawBits()) } - - - //////////////////// - // WRITE BINARIES // - //////////////////// - - - // all the necessary headers - wb(MAGIC); wb(VERSION_NUMBER); wb(NUMBER_OF_LAYERS); wb(NUMBER_OF_PAYLOADS); wb(COMPRESSION_ALGORITHM); wb(GENERATOR_VERSION) - - // world width, height, and spawn point - wi32(world.width); wi32(world.height) - wi48(LandUtil.getBlockAddr(world, world.spawnX, world.spawnY)) - - // write payloads // - - // TERR payload - // PRO Debug tip: every deflated bytes must begin with 0x789C or 0x78DA - // Thus, \0pLd + [10] must be either of these. - - // TODO serialised payloads have bit too much zeros, should I be worried? - - val savePayloads = world.javaClass.superclass.declaredFields//.filter { it.isAnnotationPresent(TEMzPayload::class.java) } - printdbg(this, "") - savePayloads.forEach { printdbg(this, "${it.name}: ${it.type} @${it.declaredAnnotations.size}") } - - wb(PAYLOAD_HEADER); wb("TERR".toByteArray()) - wi48(world.width * world.height * 3L / 2) - deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false) - world.layerTerrain.bytesIterator().forEach { deflater.write(it.toInt()) } - deflater.flush(); deflater.finish() - wb(PAYLOAD_FOOTER) - - // WALL payload - wb(PAYLOAD_HEADER); wb("WALL".toByteArray()) - wi48(world.width * world.height * 3L / 2) - deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false) - world.layerWall.bytesIterator().forEach { deflater.write(it.toInt()) } - deflater.flush(); deflater.finish() - wb(PAYLOAD_FOOTER) - - // WIRE payload - /*wb(PAYLOAD_HEADER); wb("WIRE".toByteArray()) - wi48(world.width * world.height.toLong()) - deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false) - deflater.write(world.wireArray) - deflater.flush(); deflater.finish() - wb(PAYLOAD_FOOTER)*/ - - // TdMG payload - wb(PAYLOAD_HEADER); wb("TdMG".toByteArray()) - wi48(world.terrainDamages.size * 10L) - - deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false) - - world.terrainDamages.forEach { t, u -> - deflater.write(t.toULittle48()) - deflater.write(u.toRawBits().toLittle()) - } - - deflater.flush(); deflater.finish() - wb(PAYLOAD_FOOTER) - - // WdMG payload - wb(PAYLOAD_HEADER); wb("WdMG".toByteArray()) - wi48(world.wallDamages.size * 10L) - - deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false) - - world.wallDamages.forEach { t, u -> - deflater.write(t.toULittle48()) - deflater.write(u.toRawBits().toLittle()) - } - - deflater.flush(); deflater.finish() - wb(PAYLOAD_FOOTER) - - // FlTP payload - wb(PAYLOAD_HEADER); wb("FlTP".toByteArray()) - wi48(world.fluidTypes.size * 8L) - - deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false) - - world.fluidTypes.forEach { t, u -> - deflater.write(t.toULittle48()) - deflater.write(u.value.toLittleShort()) - } - - deflater.flush(); deflater.finish() - wb(PAYLOAD_FOOTER) - - // FlFL payload - wb(PAYLOAD_HEADER); wb("FlFL".toByteArray()) - wi48(world.fluidFills.size * 10L) - - deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION, true), false) - - world.fluidFills.forEach { t, u -> - deflater.write(t.toULittle48()) - deflater.write(u.toRawBits().toLittle()) - } - - deflater.flush(); deflater.finish() - wb(PAYLOAD_FOOTER) - - - // write footer - wb(FILE_FOOTER) - - - ////////////////// - // END OF WRITE // - ////////////////// - - outputStream.flush() - outputStream.close() - - return outputStream.toByteArray64() - } - - -} diff --git a/src/net/torvald/terrarum/serialise/WriteMeta.kt b/src/net/torvald/terrarum/serialise/WriteMeta.kt index ba0c61191..7dedfb506 100644 --- a/src/net/torvald/terrarum/serialise/WriteMeta.kt +++ b/src/net/torvald/terrarum/serialise/WriteMeta.kt @@ -1,70 +1,73 @@ package net.torvald.terrarum.serialise -import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen -import java.nio.charset.Charset +import com.badlogic.gdx.utils.Json +import com.badlogic.gdx.utils.JsonWriter +import net.torvald.terrarum.ModMgr +import net.torvald.terrarum.blockproperties.BlockCodex +import net.torvald.terrarum.blockproperties.WireCodex +import net.torvald.terrarum.itemproperties.ItemCodex +import net.torvald.terrarum.itemproperties.MaterialCodex +import net.torvald.terrarum.modulebasegame.TerrarumIngame +import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser +import net.torvald.terrarum.weather.WeatherMixer -/** - * Created by minjaesong on 2016-03-15. - */ -// internal for everything: prevent malicious module from messing up the savedata -internal object WriteMeta { +open class WriteMeta(val ingame: TerrarumIngame) { - val META_FILENAME = "worldinfo0" + open fun invoke(): String { + val world = ingame.world + + val props = hashMapOf( + "genver" to 4, + "savename" to world.worldName, + "terrseed" to world.generatorSeed, + "randseed0" to RoguelikeRandomiser.RNG.state0, + "randseed1" to RoguelikeRandomiser.RNG.state1, + "weatseed0" to WeatherMixer.RNG.state0, + "weatseed1" to WeatherMixer.RNG.state1, + "playerid" to ingame.theRealGamer.referenceID, + "creation_t" to world.creationTime, + "lastplay_t" to world.lastPlayTime, + "playtime_t" to world.totalPlayTime, - val MAGIC = "TESV".toByteArray(charset = Charset.forName("US-ASCII")) + // CSVs + "blocks" to StringBuilder().let { + ModMgr.getFilesFromEveryMod("blocks/blocks.csv").forEach { (modname, file) -> + it.append("\n\n## module: $modname ##\n\n") + it.append(file.readText()) + } + it.toString() + }, + "items" to StringBuilder().let { + ModMgr.getFilesFromEveryMod("items/itemid.csv").forEach { (modname, file) -> + it.append("\n\n## module: $modname ##\n\n") + it.append(file.readText()) + } + it.toString() + }, - val BYTE_NULL: Byte = 0 + "wires" to StringBuilder().let { + ModMgr.getFilesFromEveryMod("wires/wires.csv").forEach { (modname, file) -> + it.append("\n\n## module: $modname ##\n\n") + it.append(file.readText()) + } + it.toString() + }, - val terraseed: Long = Worldgen.params.seed + // TODO fluids + "materials" to StringBuilder().let { + ModMgr.getFilesFromEveryMod("materials/materials.csv").forEach { (modname, file) -> + it.append("\n\n## module: $modname ##\n\n") + it.append(file.readText()) + } + it.toString() + }, - - /** - * Write save meta to specified directory. Returns false if something went wrong. - * @param saveDirectoryName - * @param savegameName -- Nullable. If the value is not specified, saveDirectoryName will be used instead. - */ - internal fun write(saveDirectoryName: String, savegameName: String?): Boolean { - /*val hashArray: ArrayList = ArrayList() - val savenameAsByteArray: ByteArray = - (savegameName ?: saveDirectoryName).toByteArray(Charsets.UTF_8) - - // define Strings to be hashed - val props = arrayOf( - TilePropCSV() - //, (item, mat, ...) + "loadorder" to ModMgr.loadOrder, + "worlds" to ingame.gameworldIndices ) - - // get and store hash from the list - props.map { hashArray.add(DigestUtils.sha256(it)) } - - // open file and delete it - val metaPath = Paths.get("$AppLoader.defaultSaveDir" + - "/$saveDirectoryName/$META_FILENAME") - val metaTempPath = Files.createTempFile(metaPath.toString(), "_temp") - - // TODO gzip - - // write bytes in tempfile - Files.write(metaTempPath, MAGIC) - Files.write(metaTempPath, savenameAsByteArray) - Files.write(metaTempPath, byteArrayOf(BYTE_NULL)) - Files.write(metaTempPath, toByteArray(terraseed)) - Files.write(metaTempPath, toByteArray(rogueseed)) - for (hash in hashArray) - Files.write(metaTempPath, hash) - - // replace savemeta with tempfile - try { - Files.copy(metaTempPath, metaPath, StandardCopyOption.REPLACE_EXISTING) - Files.deleteIfExists(metaTempPath) - println("Saved metadata to $saveDirectoryName.") - - return true - } - catch (e: IOException) { - e.printStackTrace() - }*/ - return false + + return Json(JsonWriter.OutputType.json).toJson(props) } + } \ No newline at end of file diff --git a/src/net/torvald/terrarum/serialise/WriteWorldInfo.kt b/src/net/torvald/terrarum/serialise/WriteWorldInfo.kt deleted file mode 100644 index d2925c876..000000000 --- a/src/net/torvald/terrarum/serialise/WriteWorldInfo.kt +++ /dev/null @@ -1,185 +0,0 @@ -package net.torvald.terrarum.serialise - -import com.badlogic.gdx.Gdx -import com.badlogic.gdx.graphics.GL30 -import com.badlogic.gdx.graphics.OrthographicCamera -import com.badlogic.gdx.graphics.Pixmap -import com.badlogic.gdx.graphics.g2d.SpriteBatch -import com.badlogic.gdx.graphics.glutils.FrameBuffer -import com.badlogic.gdx.utils.ScreenUtils -import net.torvald.gdx.graphics.PixmapIO2 -import net.torvald.terrarum.* -import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension -import net.torvald.terrarum.weather.WeatherMixer -import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser -import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64 -import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64GrowableOutputStream -import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64InputStream -import org.apache.commons.codec.digest.DigestUtils -import java.io.ByteArrayOutputStream -import java.util.zip.Deflater -import java.util.zip.DeflaterOutputStream - -object WriteWorldInfo { - - val META_MAGIC = "TESV".toByteArray(Charsets.UTF_8) - val NULL = 0.toByte() - - val VERSION = 1 - val HASHED_FILES_COUNT = 3 - - /** - * TODO currently it'll dump the temporary file (tmp_worldinfo1) onto the disk and will return the temp file. - * - * @return List of ByteArray64, worldinfo0..worldinfo3; `null` on failure - */ - internal operator fun invoke(ingame: IngameInstance): List? { - - //val path = "${AppLoader.defaultSaveDir}/tmp_worldinfo" - - val infileList = arrayOf( - ModMgr.getGdxFilesFromEveryMod("blocks/blocks.csv"), - ModMgr.getGdxFilesFromEveryMod("items/items.csv"), - ModMgr.getGdxFilesFromEveryMod("materials/materials.csv") - ) - - val outFiles = ArrayList() // for worldinfo1-3 only - val worldInfoHash = ArrayList() // hash of worldinfo1-3 - // try to write worldinfo1-3 - - for (filenum in 1..HASHED_FILES_COUNT) { - val outputStream = ByteArray64GrowableOutputStream() - val infile = infileList[filenum - 1] - - infile.forEach { - outputStream.write("## from file: ${it.second.nameWithoutExtension()} ##############################\n".toByteArray()) - val readBytes = it.second.readBytes() - outputStream.write(readBytes) - outputStream.write("\n".toByteArray()) - } - - outputStream.flush() - outputStream.close() - - - outFiles.add(outputStream.toByteArray64()) - - - worldInfoHash.add(DigestUtils.sha256(ByteArray64InputStream(outputStream.toByteArray64()))) - } - - - // compose save meta (actual writing part) - val metaOut = ByteArray64GrowableOutputStream() - - - metaOut.write(META_MAGIC) - metaOut.write(VERSION) - metaOut.write(HASHED_FILES_COUNT) - - // world name - val world = ingame.world - val worldNameBytes = world.worldName.toByteArray(Charsets.UTF_8) - //metaOut.write(worldNameBytes) - worldNameBytes.forEach { - if (it != 0.toByte()) metaOut.write(it.toInt()) - } - metaOut.write(NULL.toInt()) - - // terrain seed - metaOut.write(world.generatorSeed.toLittle()) - - // randomiser seed - metaOut.write(RoguelikeRandomiser.RNG.state0.toLittle()) - metaOut.write(RoguelikeRandomiser.RNG.state1.toLittle()) - - // weather seed - metaOut.write(WeatherMixer.RNG.state0.toLittle()) - metaOut.write(WeatherMixer.RNG.state1.toLittle()) - - // reference ID of the player - metaOut.write(Terrarum.PLAYER_REF_ID.toLittle()) - - // ingame time_t - metaOut.write((world as GameWorldExtension).worldTime.TIME_T.toLittle()) - - // creation time (real world time) - metaOut.write(world.creationTime.toULittle48()) - - // time at save (real world time) - val timeNow = System.currentTimeMillis() / 1000L - metaOut.write(timeNow.toULittle48()) - - // get playtime and save it - val timeToAdd = (timeNow - world.loadTime).toInt() - metaOut.write((world.totalPlayTime + timeToAdd).toLittle()) - world.lastPlayTime = timeNow - world.totalPlayTime += timeToAdd - - // SHA256SUM of worldinfo1-3 - worldInfoHash.forEach { - metaOut.write(it) - } - - // thumbnail - val texreg = ingame.actorGamer.sprite?.textureRegion - if (texreg != null) { - val batch = SpriteBatch() - val camera = OrthographicCamera(texreg.tileW.toFloat(), texreg.tileH.toFloat()) - val fbo = FrameBuffer(Pixmap.Format.RGBA8888, texreg.tileW, texreg.tileH, false) - - fbo.inAction(camera, batch) { - batch.inUse { - batch.draw(texreg.get(0, 0), 0f, 0f) - } - } - - // bind and unbind the fbo so that I can get the damned Pixmap using ScreenUtils - // NullPointerException if not appconfig.useGL30 - Gdx.gl30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, fbo.framebufferHandle) - Gdx.gl30.glReadBuffer(GL30.GL_COLOR_ATTACHMENT0) - - val outpixmap = ScreenUtils.getFrameBufferPixmap(0, 0, fbo.width, fbo.height) - - Gdx.gl30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, 0) - Gdx.gl30.glReadBuffer(GL30.GL_BACK) - - - val tgaSize = PixmapIO2.HEADER_FOOTER_SIZE + outpixmap.width * outpixmap.height * 4 - val byteArrayOS = ByteArrayOutputStream(tgaSize) - PixmapIO2._writeTGA(byteArrayOS, outpixmap, true, true) - byteArrayOS.flush() - byteArrayOS.close() - - - //PixmapIO2.writeTGA(Gdx.files.absolute(AppLoader.defaultDir+"/tmp_writeworldinfo+outpixmap.tga"), outpixmap, true) - - - outpixmap.dispose() - batch.dispose() - fbo.dispose() - - - - // write uncompressed size - metaOut.write(tgaSize.toULittleShort()) - // write compressed tga - val deflater = DeflaterOutputStream(metaOut, Deflater(Deflater.BEST_COMPRESSION, true), false) - deflater.write(byteArrayOS.toByteArray()) - deflater.flush(); deflater.finish() - // write footer - metaOut.write(-1); metaOut.write(-2) - } - - // more data goes here // - - - metaOut.flush() - metaOut.close() - - - - return listOf(metaOut.toByteArray64()) + outFiles.toList() - } - -} \ No newline at end of file diff --git a/src/net/torvald/terrarum/tests/Addnewcolumn.kt b/src/net/torvald/terrarum/tests/Addnewcolumn.kt index 4e5a90737..fc5ba00da 100644 --- a/src/net/torvald/terrarum/tests/Addnewcolumn.kt +++ b/src/net/torvald/terrarum/tests/Addnewcolumn.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.tests +import com.badlogic.gdx.utils.JsonValue import net.torvald.terrarum.utils.JsonFetcher import net.torvald.terrarum.utils.JsonWriter import java.io.File @@ -63,7 +64,7 @@ fun main() { val key = record[0] val value = record[index + 2] if (value.isNotBlank()) { - jsonObject.addProperty(key, value) + jsonObject.addChild(key, JsonValue(value)) } } diff --git a/src/net/torvald/terrarum/tests/ByteArray64Test.kt b/src/net/torvald/terrarum/tests/ByteArray64Test.kt index cac49f47d..d84f3525b 100644 --- a/src/net/torvald/terrarum/tests/ByteArray64Test.kt +++ b/src/net/torvald/terrarum/tests/ByteArray64Test.kt @@ -1,7 +1,6 @@ package net.torvald.terrarum.tests import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.ByteArray64GrowableOutputStream -import net.torvald.terrarum.serialise.WriteLayerDataZip import net.torvald.terrarum.serialise.toLittle import net.torvald.terrarum.serialise.toULittle48 import java.util.zip.Deflater @@ -33,7 +32,7 @@ Ooh, black and yellow! Let's shake it up a little.""".trimIndent().toByteArray() - wb(WriteLayerDataZip.MAGIC); wb(WriteLayerDataZip.VERSION_NUMBER); wb(WriteLayerDataZip.NUMBER_OF_LAYERS); wb(WriteLayerDataZip.NUMBER_OF_PAYLOADS); wb(WriteLayerDataZip.COMPRESSION_ALGORITHM); wb(WriteLayerDataZip.GENERATOR_VERSION) + //wb(WriteLayerDataZip.MAGIC); wb(WriteLayerDataZip.VERSION_NUMBER); wb(WriteLayerDataZip.NUMBER_OF_LAYERS); wb(WriteLayerDataZip.NUMBER_OF_PAYLOADS); wb(WriteLayerDataZip.COMPRESSION_ALGORITHM); wb(WriteLayerDataZip.GENERATOR_VERSION) val deflater = DeflaterOutputStream(outputStream, Deflater(Deflater.BEST_COMPRESSION), true) repeat(20001) { deflater.write(Math.random().times(256).toInt().and(255)) diff --git a/src/net/torvald/terrarum/tests/GsonTest.kt b/src/net/torvald/terrarum/tests/GsonTest.kt index d48684087..075e5303a 100644 --- a/src/net/torvald/terrarum/tests/GsonTest.kt +++ b/src/net/torvald/terrarum/tests/GsonTest.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.tests +import com.badlogic.gdx.utils.Json import net.torvald.terrarum.utils.JsonWriter import org.dyn4j.geometry.Vector2 @@ -22,13 +23,12 @@ object GsonTest { operator fun invoke() { - val gson = JsonWriter.getJsonBuilder() - val jsonString = gson.toJson(testClass) + val jsonString = Json(com.badlogic.gdx.utils.JsonWriter.OutputType.json).toJson(testClass) println(jsonString) + val deserialised = Json().fromJson(GsonTestSuper::class.java, jsonString) - val deserialised = gson.fromJson(jsonString, GsonTestSuper::class.java) println(deserialised) println(deserialised as GsonTestClass) // ClassCastException } diff --git a/src/net/torvald/terrarum/ui/UINSMenu.kt b/src/net/torvald/terrarum/ui/UINSMenu.kt index 302031315..6d74a309d 100644 --- a/src/net/torvald/terrarum/ui/UINSMenu.kt +++ b/src/net/torvald/terrarum/ui/UINSMenu.kt @@ -92,7 +92,7 @@ class UINSMenu( val listWidth = maxOf( AppLoader.fontGame.getWidth(menuTitle), minimumWidth, - stringsFromTree.map { AppLoader.fontGame.getWidth(it) }.max() ?: 0 + stringsFromTree.map { AppLoader.fontGame.getWidth(it) }.maxOrNull() ?: 0 ) val uiWidth = listWidth + (2 * TEXT_OFFSETX.toInt()) val listHeight = stringsFromTree.size * LINE_HEIGHT diff --git a/src/net/torvald/terrarum/utils/JsonFetcher.kt b/src/net/torvald/terrarum/utils/JsonFetcher.kt index 395b38c73..1f39b00d9 100644 --- a/src/net/torvald/terrarum/utils/JsonFetcher.kt +++ b/src/net/torvald/terrarum/utils/JsonFetcher.kt @@ -1,5 +1,7 @@ package net.torvald.terrarum.utils +import com.badlogic.gdx.utils.JsonReader +import com.badlogic.gdx.utils.JsonValue import net.torvald.terrarum.AppLoader.printdbg /** @@ -10,7 +12,7 @@ object JsonFetcher { private var jsonString: StringBuffer? = null @Throws(java.nio.file.NoSuchFileException::class) - operator fun invoke(jsonFilePath: String): com.google.gson.JsonObject { + operator fun invoke(jsonFilePath: String): JsonValue { jsonString = StringBuffer() // reset buffer every time it called readJsonFileAsString(jsonFilePath) @@ -20,14 +22,11 @@ object JsonFetcher { throw Error("[JsonFetcher] jsonString is null!") } - val jsonParser = com.google.gson.JsonParser() - val jsonObj = jsonParser.parse(jsonString.toString()).asJsonObject - - return jsonObj + return JsonReader().parse(jsonString.toString()) } @Throws(java.nio.file.NoSuchFileException::class) - operator fun invoke(jsonFile: java.io.File): com.google.gson.JsonObject { + operator fun invoke(jsonFile: java.io.File): JsonValue { jsonString = StringBuffer() // reset buffer every time it called readJsonFileAsString(jsonFile.canonicalPath) @@ -37,10 +36,7 @@ object JsonFetcher { throw Error("[JsonFetcher] jsonString is null!") } - val jsonParser = com.google.gson.JsonParser() - val jsonObj = jsonParser.parse(jsonString.toString()).asJsonObject - - return jsonObj + return JsonReader().parse(jsonString.toString()) } @Throws(java.nio.file.NoSuchFileException::class) @@ -50,4 +46,14 @@ object JsonFetcher { ) // JSON does not require line break } + + fun forEach(map: JsonValue, action: (String, JsonValue) -> Unit) { + var counter = 0 + var entry = map.child + while (entry != null) { + action(entry.name ?: "(arrayindex $counter)", entry) + entry = entry.next + counter += 1 + } + } } diff --git a/src/net/torvald/terrarum/utils/JsonWriter.kt b/src/net/torvald/terrarum/utils/JsonWriter.kt index 21e26de0b..48f78a7f4 100644 --- a/src/net/torvald/terrarum/utils/JsonWriter.kt +++ b/src/net/torvald/terrarum/utils/JsonWriter.kt @@ -1,7 +1,7 @@ package net.torvald.terrarum.utils -import com.google.gson.GsonBuilder -import net.torvald.terrarum.AppLoader +import com.badlogic.gdx.utils.Json +import com.badlogic.gdx.utils.JsonWriter /** * Created by minjaesong on 2016-03-04. @@ -10,25 +10,6 @@ object JsonWriter { private val formattingRegex = Regex("""(?<=[\{,\[])|(?=[\]}])""") - fun getJsonBuilder() = if (AppLoader.IS_DEVELOPMENT_BUILD) { - getPrettyBuilder() - } - else { - GsonBuilder() - .serializeNulls() - .disableHtmlEscaping() - .enableComplexMapKeySerialization() - .create() - } - - fun getPrettyBuilder() = GsonBuilder() - .setPrettyPrinting() - - .serializeNulls() - .disableHtmlEscaping() - .enableComplexMapKeySerialization() - .create() - /** * serialise a class to the file as JSON, using Google GSON. * @@ -37,10 +18,8 @@ object JsonWriter { */ @Throws(java.io.IOException::class) fun writeToFile(c: Any, path: String) { - val jsonString = getJsonBuilder().toJson(c) - val writer = java.io.FileWriter(path, false) - writer.write(jsonString.replace(formattingRegex, "\n")) + writer.write(Json(JsonWriter.OutputType.json).toJson(c).replace(formattingRegex, "\n")) writer.close() } @@ -50,13 +29,13 @@ object JsonWriter { * @param jsonObject * @param path: path to write a file */ - @Throws(java.io.IOException::class) - fun writeToFile(jsonObject: com.google.gson.JsonObject, path: String) { + /*@Throws(java.io.IOException::class) + fun writeToFile(jsonObject: Json, path: String) { val writer = java.io.FileWriter(path, false) - writer.write(getPrettyBuilder().toJson(jsonObject)) + writer.write(jsonObject.) //writer.write(jsonObject.toString().replace(formattingRegex, "\n")) writer.close() - } + }*/ } diff --git a/src/net/torvald/terrarum/weather/WeatherMixer.kt b/src/net/torvald/terrarum/weather/WeatherMixer.kt index 416bd4970..b4f33a550 100644 --- a/src/net/torvald/terrarum/weather/WeatherMixer.kt +++ b/src/net/torvald/terrarum/weather/WeatherMixer.kt @@ -275,37 +275,31 @@ internal object WeatherMixer : RNGConsumer { val JSON = JsonFetcher(path) - val skyboxInJson = JSON.get("skyboxGradColourMap").asJsonPrimitive - val extraImagesPath = JSON.getAsJsonArray("extraImages") + val skyboxInJson = JSON.getString("skyboxGradColourMap") + val extraImagesPath = JSON.get("extraImages").asStringArray() - - - val skybox = if (skyboxInJson.isString) - GdxColorMap(ModMgr.getGdxFile("basegame", "$pathToImage/${skyboxInJson.asString}")) - else - throw IllegalStateException("In weather descriptor $path -- skyboxGradColourMap seems malformed.") + val skybox = GdxColorMap(ModMgr.getGdxFile("basegame", "$pathToImage/${skyboxInJson}")) val extraImages = ArrayList() for (i in extraImagesPath) - extraImages.add(Texture(ModMgr.getGdxFile("basegame", "$pathToImage/${i.asString}"))) + extraImages.add(Texture(ModMgr.getGdxFile("basegame", "$pathToImage/${i}"))) - - val classification = JSON.get("classification").asJsonPrimitive.asString + val classification = JSON.getString("classification") var mixFrom: String? - try { mixFrom = JSON.get("mixFrom").asJsonPrimitive.asString } - catch (e: NullPointerException) { mixFrom = null } + try { mixFrom = JSON.getString("mixFrom") } + catch (e: IllegalArgumentException) { mixFrom = null } var mixPercentage: Double? - try { mixPercentage = JSON.get("mixPercentage").asJsonPrimitive.asDouble } - catch (e: NullPointerException) { mixPercentage = null } + try { mixPercentage = JSON.getDouble("mixPercentage") } + catch (e: IllegalArgumentException) { mixPercentage = null } diff --git a/terrarum.terrarum.iml b/terrarum.terrarum.iml index b34d17a36..1b2112522 100644 --- a/terrarum.terrarum.iml +++ b/terrarum.terrarum.iml @@ -12,7 +12,6 @@ - @@ -22,7 +21,6 @@ - diff --git a/work_files/DataFormats/just-json-it-saveformat.md b/work_files/DataFormats/just-json-it-saveformat.md index db1be0c5c..87133ea0a 100644 --- a/work_files/DataFormats/just-json-it-saveformat.md +++ b/work_files/DataFormats/just-json-it-saveformat.md @@ -10,8 +10,8 @@ Following code is an example savegame JSON files. weatseed: "e5e72beb4e3c6926d3dc9e3e2ef7833b", playerid: 9545698, creation_t: , - lastplay_t: , - creation_t: , + lastplay_t: , + playtime_t: , thumb: , blocks: ,