diff --git a/README.md b/README.md index f19b49adc..9c3145865 100644 --- a/README.md +++ b/README.md @@ -21,24 +21,7 @@ Any contribution in this project must be made sorely in English, Korean part is ## The Engine ## -The Engine is custom built to suit the needs most. Following list is our aims: - -* Reasonable performance on vast world, on JVM - - At least better than Notch's codes... - -* Thread scalability - - Multithreaded environments are commonplace in this era; even in the Intel Pentium G. We aim to introduce performance boost by supporting multithreads, without the limitation of threads count (hopefully). - -* Lightweight physics solver, as light as we need - - This game is not exactly a physics toy, albeit some could add the fun. - - Currently implemented: gravity (NOT artificial), friction, buoyancy (WIP), air/fluid density and termination velocity - - Planned: artificial gravitation, wind, joints - -* Cellular Automata fluid simulation - - It should be enough — period. - - -Because of this, we just couldn't use solutions out there. For example, Tiled is too slow[citation needed] and has large memory footprint[citation needed] for our vast world; we can't use JBox2d nor Dyn4j as we don't need any sophisticated physics simulation, and can't use them anyway as we have literally _millions_ of rigid bodies (tiles) and actors. (Trivia: we _do_ use Dyn4j's Vector2 class) +Please refer to [```THE_ENGINE.md```](THE_ENGINE.md). ## Contribution guidelines ## diff --git a/THE_ENGINE.md b/THE_ENGINE.md new file mode 100644 index 000000000..503a08417 --- /dev/null +++ b/THE_ENGINE.md @@ -0,0 +1,58 @@ +DISCLAIMER: this is marketing-team stuffs. Features are still in-development and may not be available. + +### TODO: cleanup + +The Engine is custom built to suit the needs most. Following list is our aims: + +* Reasonable performance on vast world, on JVM + - At least better than Notch's codes... + +* Thread scalability + - Multithreaded environments are commonplace in this era; even in the Intel Pentium G. We aim to introduce performance boost by supporting multithreads, without the limitation of threads count (hopefully). + +* Lightweight physics solver, as light as we need + - This game is not exactly a physics toy, albeit some could add the fun. + - Currently implemented: gravity (NOT artificial), friction, buoyancy (WIP), air/fluid density and termination velocity + - Planned: artificial gravitation, wind, joints + +* Cellular Automata fluid simulation + - It should be enough — period. + + +Because of this, we just couldn't use solutions out there. For example, Tiled is too slow[citation needed] and has large memory footprint[citation needed] for our vast world; we can't use JBox2d nor Dyn4j as we don't need any sophisticated physics simulation, and can't use them anyway as we have literally _millions_ of rigid bodies (tiles) and actors. (Trivia: we _do_ use Dyn4j's Vector2 class) + + + +## General-Purpose Side-Scroller Game Maker + +The Engines is specialised in side-scrolling platformers with controls specific to + +The Engine is designed with modularity in mind — every game runs upon the Engine is individual module(s), and you can write your own module to alter the original game (module), essentially a game "mod" (put intended). + + +### Actors + +The Engine allows Actors (NPCs) to have AIs + + +### Sprites + +The Engine allows up to 64 sprite layers that are either software- or hardware-blended + + +### Multilingual Support + +The Engine can support any arbitrary language, as long as there is fonts for them. A default font is shipped with the Engine, and it already supports 20+ languages. + + + +### Utilities + +The Engine also comes with various utilities to help the game making bit easier. They include: + +- Savegame generator/loader +- Password system (old games used password system to load/save the gameplay) +- CSV loader (e.g. Item properties) +- Json loader/saver +- Text cipher + diff --git a/Terrarum_renewed.iml b/Terrarum_renewed.iml index ed975cde6..369566090 100644 --- a/Terrarum_renewed.iml +++ b/Terrarum_renewed.iml @@ -1,21 +1,5 @@ - - - - - - - - - - - - diff --git a/src/net/torvald/JsonFetcher.kt b/src/net/torvald/JsonFetcher.kt deleted file mode 100644 index abfd54774..000000000 --- a/src/net/torvald/JsonFetcher.kt +++ /dev/null @@ -1,52 +0,0 @@ -package net.torvald - -import com.google.gson.JsonObject -import com.google.gson.JsonParser -import java.io.File - -import java.io.IOException -import java.nio.file.FileSystems -import java.nio.file.Files -import java.util.ArrayList -import java.util.function.Consumer - -/** - * Created by minjaesong on 16-02-15. - */ -object JsonFetcher { - - private var jsonString: StringBuffer? = null - - @Throws(IOException::class) - operator fun invoke(jsonFilePath: String): JsonObject { - jsonString = StringBuffer() // reset buffer every time it called - readJsonFileAsString(jsonFilePath) - - println("[JsonFetcher] Reading JSON $jsonFilePath") - - val jsonParser = JsonParser() - val jsonObj = jsonParser.parse(jsonString!!.toString()).asJsonObject - - return jsonObj - } - - @Throws(IOException::class) - operator fun invoke(jsonFile: File): JsonObject { - jsonString = StringBuffer() // reset buffer every time it called - readJsonFileAsString(jsonFile.canonicalPath) - - println("[JsonFetcher] Reading JSON ${jsonFile.path}") - - val jsonParser = JsonParser() - val jsonObj = jsonParser.parse(jsonString!!.toString()).asJsonObject - - return jsonObj - } - - @Throws(IOException::class) - private fun readJsonFileAsString(path: String) { - Files.lines(FileSystems.getDefault().getPath(path)).forEach( - { jsonString!!.append(it) } - ) // JSON does not require line break - } -} diff --git a/src/net/torvald/RasterWriter.kt b/src/net/torvald/RasterWriter.kt deleted file mode 100644 index 65b375485..000000000 --- a/src/net/torvald/RasterWriter.kt +++ /dev/null @@ -1,49 +0,0 @@ -package net.torvald - -import javax.imageio.ImageIO -import java.awt.* -import java.awt.color.ColorSpace -import java.awt.image.* -import java.io.File -import java.io.IOException - -/** - * Created by minjaesong on 16-03-04. - */ -object RasterWriter { - - val BANDOFFSET_RGB = intArrayOf(0, 1, 2) - val BANDOFFSET_RGBA = intArrayOf(0, 1, 2, 3) - val BANDOFFSET_ARGB = intArrayOf(3, 0, 1, 2) - val BANDOFFSET_MONO = intArrayOf(0) - - val COLORSPACE_SRGB = ColorSpace.CS_sRGB - val COLORSPACE_GRAY = ColorSpace.CS_GRAY - val COLORSPACE_GREY = COLORSPACE_GRAY - val COLORSPACE_CIEXYZ = ColorSpace.CS_CIEXYZ - val COLORSPACE_RGB_LINEAR_GAMMA = ColorSpace.CS_LINEAR_RGB - - @Throws(IOException::class) - fun writePNG_RGB(w: Int, h: Int, rasterData: ByteArray, path: String) { - writePNG(w, h, rasterData, BANDOFFSET_RGB, COLORSPACE_SRGB, path) - } - - @Throws(IOException::class) - fun writePNG_Mono(w: Int, h: Int, rasterData: ByteArray, path: String) { - writePNG(w, h, rasterData, BANDOFFSET_MONO, COLORSPACE_GREY, path) - } - - @Throws(IOException::class) - fun writePNG(w: Int, h: Int, rasterData: ByteArray, bandOffsets: IntArray, awt_colorspace: Int, path: String) { - val buffer = DataBufferByte(rasterData, rasterData.size) - val raster = Raster.createInterleavedRaster( - buffer, w, h, bandOffsets.size * w, bandOffsets.size, bandOffsets, null) - - val colorModel = ComponentColorModel(ColorSpace.getInstance(awt_colorspace), false, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE) - - val image = BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied, null) - - ImageIO.write(image, "PNG", File(path)) - } - -} diff --git a/src/net/torvald/terrarum/ModMgr.kt b/src/net/torvald/terrarum/ModMgr.kt index 59171eec4..793dceb76 100644 --- a/src/net/torvald/terrarum/ModMgr.kt +++ b/src/net/torvald/terrarum/ModMgr.kt @@ -1,6 +1,6 @@ package net.torvald.terrarum -import net.torvald.CSVFetcher +import net.torvald.terrarum.utils.CSVFetcher import net.torvald.terrarum.itemproperties.GameItem import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.blockproperties.BlockCodex @@ -99,12 +99,6 @@ object ModMgr { println("extension:" + f.extensions) println("-----------------------------------------------") }*/ - - - /*val engine = ScriptEngineManager().getEngineByExtension("groovy")!! - engine.eval(FileReader(getFile("basegame", "/items/testpick.groovy"))) - val newPick = (engine as Invocable).invokeFunction("invoke", 8449) as GameItem - ItemCodex[8449] = newPick*/ } private fun checkExistence(module: String) { diff --git a/src/net/torvald/terrarum/StateUITest.kt b/src/net/torvald/terrarum/StateUITest.kt index 13816faf0..6be124572 100644 --- a/src/net/torvald/terrarum/StateUITest.kt +++ b/src/net/torvald/terrarum/StateUITest.kt @@ -27,7 +27,7 @@ class StateUITest : BasicGameState() { TODO("not implemented") } - override fun actorValueChanged(key: String, value: Any?) { + override fun onActorValueChange(key: String, value: Any?) { } override var inventory: ActorInventory = ActorInventory(this, 100, ActorInventory.CAPACITY_MODE_WEIGHT) diff --git a/src/net/torvald/terrarum/Terrarum.kt b/src/net/torvald/terrarum/Terrarum.kt index 639582b9e..d829bed23 100644 --- a/src/net/torvald/terrarum/Terrarum.kt +++ b/src/net/torvald/terrarum/Terrarum.kt @@ -1,11 +1,10 @@ package net.torvald.terrarum import com.google.gson.JsonArray -import com.google.gson.JsonObject import com.google.gson.JsonPrimitive import net.torvald.imagefont.GameFontImpl -import net.torvald.JsonFetcher -import net.torvald.JsonWriter +import net.torvald.terrarum.utils.JsonFetcher +import net.torvald.terrarum.utils.JsonWriter import net.torvald.imagefont.TinyAlphNum import net.torvald.terrarum.gamecontroller.mouseTileX import net.torvald.terrarum.gamecontroller.mouseTileY @@ -18,7 +17,6 @@ import org.newdawn.slick.opengl.Texture import org.newdawn.slick.state.StateBasedGame import java.io.File import java.io.IOException -import java.lang.management.ManagementFactory import java.nio.ByteOrder import java.text.SimpleDateFormat import java.util.* @@ -351,23 +349,23 @@ object Terrarum : StateBasedGame(GAME_NAME) { val OS = System.getProperty("os.name").toUpperCase() if (OS.contains("WIN")) { OperationSystem = "WINDOWS" - defaultDir = System.getenv("APPDATA") + "/terrarum" + defaultDir = System.getenv("APPDATA") + "/Terrarum" } else if (OS.contains("OS X")) { OperationSystem = "OSX" - defaultDir = System.getProperty("user.home") + "/Library/Application Support/terrarum" + defaultDir = System.getProperty("user.home") + "/Library/Application Support/Terrarum" } else if (OS.contains("NUX") || OS.contains("NIX")) { OperationSystem = "LINUX" - defaultDir = System.getProperty("user.home") + "/.terrarum" + defaultDir = System.getProperty("user.home") + "/.Terrarum" } else if (OS.contains("SUNOS")) { OperationSystem = "SOLARIS" - defaultDir = System.getProperty("user.home") + "/.terrarum" + defaultDir = System.getProperty("user.home") + "/.Terrarum" } else { OperationSystem = "UNKNOWN" - defaultDir = System.getProperty("user.home") + "/.terrarum" + defaultDir = System.getProperty("user.home") + "/.Terrarum" } defaultSaveDir = defaultDir + "/Saves" diff --git a/src/net/torvald/terrarum/blockproperties/BlockCodex.kt b/src/net/torvald/terrarum/blockproperties/BlockCodex.kt index dc223ad63..b9848fc5e 100644 --- a/src/net/torvald/terrarum/blockproperties/BlockCodex.kt +++ b/src/net/torvald/terrarum/blockproperties/BlockCodex.kt @@ -1,6 +1,6 @@ package net.torvald.terrarum.blockproperties -import net.torvald.CSVFetcher +import net.torvald.terrarum.utils.CSVFetcher import net.torvald.terrarum.gameworld.MapLayer import net.torvald.terrarum.gameworld.PairedMapLayer import org.apache.commons.csv.CSVRecord diff --git a/src/net/torvald/terrarum/console/ExportAV.kt b/src/net/torvald/terrarum/console/ExportAV.kt index 351afb6fb..995d822ec 100644 --- a/src/net/torvald/terrarum/console/ExportAV.kt +++ b/src/net/torvald/terrarum/console/ExportAV.kt @@ -1,6 +1,6 @@ package net.torvald.terrarum.console -import net.torvald.JsonWriter +import net.torvald.terrarum.utils.JsonWriter import net.torvald.terrarum.Terrarum import java.io.IOException diff --git a/src/net/torvald/terrarum/console/ExportMap.kt b/src/net/torvald/terrarum/console/ExportMap.kt index 763d1fdc3..9d0577d22 100644 --- a/src/net/torvald/terrarum/console/ExportMap.kt +++ b/src/net/torvald/terrarum/console/ExportMap.kt @@ -1,7 +1,7 @@ package net.torvald.terrarum.console import net.torvald.colourutil.Col4096 -import net.torvald.RasterWriter +import net.torvald.terrarum.utils.RasterWriter import net.torvald.terrarum.Terrarum import net.torvald.terrarum.blockproperties.Block diff --git a/src/net/torvald/terrarum/gameactors/Actor.kt b/src/net/torvald/terrarum/gameactors/Actor.kt index 032763bdd..f7d37f3c1 100644 --- a/src/net/torvald/terrarum/gameactors/Actor.kt +++ b/src/net/torvald/terrarum/gameactors/Actor.kt @@ -84,5 +84,7 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable, Runnable * * @param value null if the key is deleted */ - abstract fun actorValueChanged(key: String, value: Any?) -} \ No newline at end of file + abstract @Event fun onActorValueChange(key: String, value: Any?) +} + +annotation class Event diff --git a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt index 6489a3a93..4dad3bf27 100644 --- a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt +++ b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt @@ -335,8 +335,10 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) } override fun keyPressed(key: Int, c: Char) { - if (key in Key.NUM_1..Key.NUM_0) { - actorValue[AVKey.__PLAYER_QUICKSLOTSEL] = key - Key.NUM_1 + // quickslot (quickbar) + val quickbarKeys = Terrarum.getConfigIntArray("keyquickbars") + if (key in quickbarKeys) { + actorValue[AVKey.__PLAYER_QUICKSLOTSEL] = quickbarKeys.indexOf(key) } } @@ -474,7 +476,7 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) } } - override fun actorValueChanged(key: String, value: Any?) { + override fun onActorValueChange(key: String, value: Any?) { // quickslot implementation if (key == AVKey.__PLAYER_QUICKSLOTSEL && value != null) { // ONLY FOR HAND_GRIPs!! diff --git a/src/net/torvald/terrarum/gameactors/ActorValue.kt b/src/net/torvald/terrarum/gameactors/ActorValue.kt index 36b1f11fb..ada9da23e 100644 --- a/src/net/torvald/terrarum/gameactors/ActorValue.kt +++ b/src/net/torvald/terrarum/gameactors/ActorValue.kt @@ -13,13 +13,13 @@ class ActorValue(val actor: Actor) : KVHashMap() { override fun set(key: String, value: Any) { super.set(key, value) - actor.actorValueChanged(key, value) // fire the event handler + actor.onActorValueChange(key, value) // fire the event handler } override fun remove(key: String) { if (hashMap[key] != null) { hashMap.remove(key, hashMap[key]!!) - actor.actorValueChanged(key, null) + actor.onActorValueChange(key, null) } } diff --git a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt index 8b8ec4a77..3136b1ce6 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt @@ -1135,7 +1135,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean } } - override fun actorValueChanged(key: String, value: Any?) { + override fun onActorValueChange(key: String, value: Any?) { // do nothing } diff --git a/src/net/torvald/terrarum/gameactors/CreatureBuilder.kt b/src/net/torvald/terrarum/gameactors/CreatureBuilder.kt index 4e27d0d1a..a67eaf19e 100644 --- a/src/net/torvald/terrarum/gameactors/CreatureBuilder.kt +++ b/src/net/torvald/terrarum/gameactors/CreatureBuilder.kt @@ -1,10 +1,5 @@ package net.torvald.terrarum.gameactors -import net.torvald.JsonFetcher -import net.torvald.random.Fudge3 -import net.torvald.random.HQRNG -import net.torvald.terrarum.langpack.Lang -import com.google.gson.JsonObject import org.newdawn.slick.SlickException import java.io.IOException diff --git a/src/net/torvald/terrarum/gameactors/InjectCreatureRaw.kt b/src/net/torvald/terrarum/gameactors/InjectCreatureRaw.kt index 719025125..b060fc7b6 100644 --- a/src/net/torvald/terrarum/gameactors/InjectCreatureRaw.kt +++ b/src/net/torvald/terrarum/gameactors/InjectCreatureRaw.kt @@ -1,14 +1,10 @@ package net.torvald.terrarum.gameactors -import net.torvald.JsonFetcher +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.gameactors.ActorValue import net.torvald.terrarum.ModMgr -import net.torvald.terrarum.gameactors.ActorHumanoid -import org.newdawn.slick.SlickException -import java.io.IOException import java.security.SecureRandom /** diff --git a/src/net/torvald/terrarum/gameactors/faction/FactionFactory.kt b/src/net/torvald/terrarum/gameactors/faction/FactionFactory.kt index ddf4805a2..51c366a64 100644 --- a/src/net/torvald/terrarum/gameactors/faction/FactionFactory.kt +++ b/src/net/torvald/terrarum/gameactors/faction/FactionFactory.kt @@ -1,7 +1,6 @@ package net.torvald.terrarum.gameactors.faction -import net.torvald.JsonFetcher -import com.google.gson.JsonObject +import net.torvald.terrarum.utils.JsonFetcher import net.torvald.terrarum.ModMgr import java.io.IOException diff --git a/src/net/torvald/terrarum/gamecontroller/KeyLayout.kt b/src/net/torvald/terrarum/gamecontroller/KeyLayout.kt index e13875c85..4a4c78bd4 100644 --- a/src/net/torvald/terrarum/gamecontroller/KeyLayout.kt +++ b/src/net/torvald/terrarum/gamecontroller/KeyLayout.kt @@ -1,6 +1,6 @@ package net.torvald.terrarum.gamecontroller -import net.torvald.JsonFetcher +import net.torvald.terrarum.utils.JsonFetcher import java.util.* /** diff --git a/src/net/torvald/terrarum/langpack/Lang.kt b/src/net/torvald/terrarum/langpack/Lang.kt index feaf43029..016c6abab 100644 --- a/src/net/torvald/terrarum/langpack/Lang.kt +++ b/src/net/torvald/terrarum/langpack/Lang.kt @@ -1,6 +1,6 @@ package net.torvald.terrarum.langpack -import net.torvald.JsonFetcher +import net.torvald.terrarum.utils.JsonFetcher import net.torvald.terrarum.Terrarum import java.io.* import java.util.* diff --git a/src/net/torvald/CSVFetcher.kt b/src/net/torvald/terrarum/utils/CSVFetcher.kt similarity index 51% rename from src/net/torvald/CSVFetcher.kt rename to src/net/torvald/terrarum/utils/CSVFetcher.kt index 9da24802e..0ebe5de55 100644 --- a/src/net/torvald/CSVFetcher.kt +++ b/src/net/torvald/terrarum/utils/CSVFetcher.kt @@ -1,4 +1,4 @@ -package net.torvald +package net.torvald.terrarum.utils import net.torvald.terrarum.ModMgr import org.apache.commons.csv.CSVFormat @@ -17,15 +17,15 @@ object CSVFetcher { private var csvString: StringBuffer? = null - fun readFromFile(csvFilePath: String): List { - csvString = StringBuffer() // reset buffer every time it called - readCSVasString(csvFilePath) + fun readFromFile(csvFilePath: String): List { + net.torvald.terrarum.utils.CSVFetcher.csvString = StringBuffer() // reset buffer every time it called + net.torvald.terrarum.utils.CSVFetcher.readCSVasString(csvFilePath) println("[CSVFetcher] Reading CSV $csvFilePath") - val csvParser = CSVParser.parse( - csvString!!.toString(), - CSVFormat.DEFAULT.withIgnoreSurroundingSpaces() + val csvParser = org.apache.commons.csv.CSVParser.parse( + net.torvald.terrarum.utils.CSVFetcher.csvString!!.toString(), + org.apache.commons.csv.CSVFormat.DEFAULT.withIgnoreSurroundingSpaces() .withHeader() .withIgnoreEmptyLines() .withDelimiter(';') @@ -40,12 +40,12 @@ object CSVFetcher { return csvRecordList } - fun readFromModule(module: String, path: String) = readFromFile(ModMgr.getPath(module, path)) + fun readFromModule(module: String, path: String) = net.torvald.terrarum.utils.CSVFetcher.readFromFile(ModMgr.getPath(module, path)) - fun readFromString(csv: String): List { - val csvParser = CSVParser.parse( + fun readFromString(csv: String): List { + val csvParser = org.apache.commons.csv.CSVParser.parse( csv, - CSVFormat.DEFAULT.withIgnoreSurroundingSpaces() + org.apache.commons.csv.CSVFormat.DEFAULT.withIgnoreSurroundingSpaces() .withHeader() .withIgnoreEmptyLines() .withDelimiter(';') @@ -60,12 +60,12 @@ object CSVFetcher { return csvRecordList } - @Throws(IOException::class) + @Throws(java.io.IOException::class) fun readCSVasString(path: String): String { - csvString = StringBuffer() - Files.lines(FileSystems.getDefault().getPath(path)).forEach( - { s -> csvString!!.append("$s\n") } + net.torvald.terrarum.utils.CSVFetcher.csvString = StringBuffer() + java.nio.file.Files.lines(java.nio.file.FileSystems.getDefault().getPath(path)).forEach( + { s -> net.torvald.terrarum.utils.CSVFetcher.csvString!!.append("$s\n") } ) - return csvString!!.toString() + return net.torvald.terrarum.utils.CSVFetcher.csvString!!.toString() } } diff --git a/src/net/torvald/simplecipher/ROTUtil.kt b/src/net/torvald/terrarum/utils/CipherROT.kt similarity index 76% rename from src/net/torvald/simplecipher/ROTUtil.kt rename to src/net/torvald/terrarum/utils/CipherROT.kt index 429995afb..49444eb52 100644 --- a/src/net/torvald/simplecipher/ROTUtil.kt +++ b/src/net/torvald/terrarum/utils/CipherROT.kt @@ -1,9 +1,9 @@ -package net.torvald.simplecipher +package net.torvald.terrarum.utils /** * Created by minjaesong on 16-03-20. */ -object ROTUtil { +object CipherROT { const val CODE_CAP_A = 'A'.toInt() const val CODE_LOW_A = 'a'.toInt() @@ -14,18 +14,6 @@ object ROTUtil { * * Latin alph: removes diacritics and do ROT13, string reverse, capitalised. * Ligatures are disassembled. Even if the target language does not have * certain alphabet (e.g. C in Icelandic), such alphabet will be printed anyway. - * - * * Cyrillic: removes diacritics and do ROTnn, string reverse, capitalised. - * - * * Kana: raise Sutegana, ROT3 on vowels (a i u e o -> e o a i u), string reverse - * (Wa Wo -> Wo Wa), Nn will remain untouched, forced Katakana. - * - * * Hangul: ROT3 on initials\*, lower double initials to single - * (ㄱ ㄲ ㄴ ㄷ ㄸ ㄹ ㅁ ㅂ ㅃ ㅅ ㅆ ㅇ ㅈ ㅉ ㅊ ㅋ ㅌ ㅍ ㅎ -> ㄹ ㄹ ㅁ ㅂ ㅂ ㅅ ㅇ ㅇ ㅈ ㅈ ㅊ ㅋ ㅋ ㅌ ㅍ ㅎ ㄱ ㄴ ㄷ), - * string reverse - * - * * Chinese: NOT SUPPORTED - * * * Numeric: no encrypt */ fun encrypt(plaintext: String): String { diff --git a/src/net/torvald/Clipboard.kt b/src/net/torvald/terrarum/utils/Clipboard.kt similarity index 93% rename from src/net/torvald/Clipboard.kt rename to src/net/torvald/terrarum/utils/Clipboard.kt index 1e82ea209..aff3c4ef3 100644 --- a/src/net/torvald/Clipboard.kt +++ b/src/net/torvald/terrarum/utils/Clipboard.kt @@ -1,4 +1,4 @@ -package net.torvald +package net.torvald.terrarum.utils import java.awt.Toolkit import java.awt.datatransfer.DataFlavor diff --git a/src/net/torvald/terrarum/utils/JsonFetcher.kt b/src/net/torvald/terrarum/utils/JsonFetcher.kt new file mode 100644 index 000000000..8ad531148 --- /dev/null +++ b/src/net/torvald/terrarum/utils/JsonFetcher.kt @@ -0,0 +1,52 @@ +package net.torvald.terrarum.utils + +import com.google.gson.JsonObject +import com.google.gson.JsonParser +import java.io.File + +import java.io.IOException +import java.nio.file.FileSystems +import java.nio.file.Files +import java.util.ArrayList +import java.util.function.Consumer + +/** + * Created by minjaesong on 16-02-15. + */ +object JsonFetcher { + + private var jsonString: StringBuffer? = null + + @Throws(java.io.IOException::class) + operator fun invoke(jsonFilePath: String): com.google.gson.JsonObject { + net.torvald.terrarum.utils.JsonFetcher.jsonString = StringBuffer() // reset buffer every time it called + net.torvald.terrarum.utils.JsonFetcher.readJsonFileAsString(jsonFilePath) + + println("[JsonFetcher] Reading JSON $jsonFilePath") + + val jsonParser = com.google.gson.JsonParser() + val jsonObj = jsonParser.parse(net.torvald.terrarum.utils.JsonFetcher.jsonString!!.toString()).asJsonObject + + return jsonObj + } + + @Throws(java.io.IOException::class) + operator fun invoke(jsonFile: java.io.File): com.google.gson.JsonObject { + net.torvald.terrarum.utils.JsonFetcher.jsonString = StringBuffer() // reset buffer every time it called + net.torvald.terrarum.utils.JsonFetcher.readJsonFileAsString(jsonFile.canonicalPath) + + println("[JsonFetcher] Reading JSON ${jsonFile.path}") + + val jsonParser = com.google.gson.JsonParser() + val jsonObj = jsonParser.parse(net.torvald.terrarum.utils.JsonFetcher.jsonString!!.toString()).asJsonObject + + return jsonObj + } + + @Throws(java.io.IOException::class) + private fun readJsonFileAsString(path: String) { + java.nio.file.Files.lines(java.nio.file.FileSystems.getDefault().getPath(path)).forEach( + { net.torvald.terrarum.utils.JsonFetcher.jsonString!!.append(it) } + ) // JSON does not require line break + } +} diff --git a/src/net/torvald/JsonWriter.kt b/src/net/torvald/terrarum/utils/JsonWriter.kt similarity index 68% rename from src/net/torvald/JsonWriter.kt rename to src/net/torvald/terrarum/utils/JsonWriter.kt index 51bfe8dc5..c874f2926 100644 --- a/src/net/torvald/JsonWriter.kt +++ b/src/net/torvald/terrarum/utils/JsonWriter.kt @@ -1,4 +1,4 @@ -package net.torvald +package net.torvald.terrarum.utils import com.google.gson.Gson import com.google.gson.JsonElement @@ -18,11 +18,11 @@ object JsonWriter { * @param c: a class * @param path: path to write a file */ - @Throws(IOException::class) + @Throws(java.io.IOException::class) fun writeToFile(c: Any, path: String) { - val classElem = Gson().toJsonTree(c) + val classElem = com.google.gson.Gson().toJsonTree(c) val jsonString = classElem.toString() - val writer = FileWriter(path) + val writer = java.io.FileWriter(path) writer.write(jsonString) writer.close() } @@ -33,9 +33,9 @@ object JsonWriter { * @param jsonObject * @param path: path to write a file */ - @Throws(IOException::class) - fun writeToFile(jsonObject: JsonObject, path: String) { - val writer = FileWriter(path) + @Throws(java.io.IOException::class) + fun writeToFile(jsonObject: com.google.gson.JsonObject, path: String) { + val writer = java.io.FileWriter(path) writer.write(jsonObject.toString()) writer.close() } diff --git a/src/net/torvald/terrarum/utils/PasswordBase32.kt b/src/net/torvald/terrarum/utils/PasswordBase32.kt new file mode 100644 index 000000000..004247d2f --- /dev/null +++ b/src/net/torvald/terrarum/utils/PasswordBase32.kt @@ -0,0 +1,150 @@ +package net.torvald.terrarum.utils + +import kotlin.experimental.xor + + +/** + * Old-school passworld system using Base32 + * + * Created by minjaesong on 2017-05-02. + */ +object PasswordBase32 { + + private val stringSet = "YBNDRFG8EJKMCPQXOT+VWIS2A345H769=" + + private val substituteSet = hashMapOf( + Pair('0', 'O'), + Pair('1', 'I'), + Pair('Z', '2') + ) + + /* + 0 x + 1 6 + 2 4 + 3 3 + 4 1 + */ + val padLen = arrayOf(0, 6, 4, 3, 1) + private val nullPw = byteArrayOf(0.toByte()) + + + private fun encodeToLetters(byteArray: ByteArray, password: ByteArray): IntArray { + val out = ArrayList() + + fun get(i: Int) = byteArray[i] xor (password[i % password.size]) + + + /* + 5 Bytes -> 8 Letters + + 0000 0000 | 1111 1111 | 2222 2222 | 3333 3333 | 4444 4444 + AAAA ABBB | BBCC CCCD | DDDD EEEE | EFFF FFGG | GGGH HHHH + */ + + // non-pads + (0..byteArray.lastIndex - 5 step 5).forEach { + /* A */ out.add(get(it).toInt().and(0xF8).ushr(3)) + /* B */ out.add(get(it).toInt().and(7).shl(2) or get(it+1).toInt().and(0xC0).ushr(6)) + /* C */ out.add(get(it+1).toInt().and(0x3E).ushr(1)) + /* D */ out.add(get(it+1).toInt().and(1).shl(4) or get(it+2).toInt().and(0xF0).ushr(4)) + /* E */ out.add(get(it+2).toInt().and(0xF).shl(1) or get(it+3).toInt().and(0x80).ushr(7)) + /* F */ out.add(get(it+3).toInt().and(0x7C).ushr(2)) + /* G */ out.add(get(it+3).toInt().and(3).shl(3) or get(it+4).toInt().and(0xE0).ushr(5)) + /* H */ out.add(get(it+4).toInt().and(0x1F)) + } + // pads + val residue = byteArray.size % 5 + if (residue != 0){ + + val it = (byteArray.size / 5) * 5 // dark magic of integer division, let's hope the compiler won't "optimise" this... + + when (residue) { + 1 -> { + /* A */ out.add(get(it).toInt().and(0xF8).ushr(3)) + /* B */ out.add(get(it).toInt().and(7).shl(2)) + } + 2 -> { + /* A */ out.add(get(it).toInt().and(0xF8).ushr(3)) + /* B */ out.add(get(it).toInt().and(7).shl(2) or get(it+1).toInt().and(0xC0).ushr(6)) + /* C */ out.add(get(it+1).toInt().and(0x3E).ushr(1)) + /* D */ out.add(get(it+1).toInt().and(1).shl(4)) + } + 3 -> { + /* A */ out.add(get(it).toInt().and(0xF8).ushr(3)) + /* B */ out.add(get(it).toInt().and(7).shl(2) or get(it+1).toInt().and(0xC0).ushr(6)) + /* C */ out.add(get(it+1).toInt().and(0x3E).ushr(1)) + /* D */ out.add(get(it+1).toInt().and(1).shl(4) or get(it+2).toInt().and(0xF0).ushr(4)) + /* E */ out.add(get(it+2).toInt().and(0xF).shl(1)) + } + 4 -> { + /* A */ out.add(get(it).toInt().and(0xF8).ushr(3)) + /* B */ out.add(get(it).toInt().and(7).shl(2) or get(it+1).toInt().and(0xC0).ushr(6)) + /* C */ out.add(get(it+1).toInt().and(0x3E).ushr(1)) + /* D */ out.add(get(it+1).toInt().and(1).shl(4) or get(it+2).toInt().and(0xF0).ushr(4)) + /* E */ out.add(get(it+2).toInt().and(0xF).shl(1) or get(it+3).toInt().and(0x80).ushr(7)) + /* F */ out.add(get(it+3).toInt().and(0x7C).ushr(2)) + /* G */ out.add(get(it+3).toInt().and(3).shl(3)) + } + } + + // append padding + kotlin.repeat(padLen[residue], { out.add(32) }) + } + + return out.toIntArray() + } + + /** + * + * @param bytes size of multiple of five (5, 10, 15, 20, ...) is highly recommended to prevent + * lengthy padding + * @param password to encode resulting string using XOR Cipher to prevent unexperienced kids + * from doing naughty things. Longer, the better. + */ + fun encode(bytes: ByteArray, password: ByteArray = nullPw): String { + val plaintext = encodeToLetters(bytes, password) + val sb = StringBuilder() + plaintext.forEach { sb.append(stringSet[it]) } + + return sb.toString() + } + + /** + * @param outByteLength expected length of your decoded password. It is always a good idea to + * suspect user inputs and sanitise them. + */ + fun decode(input: String, outByteLength: Int, password: ByteArray = nullPw): ByteArray { + val buffer = ByteArray(outByteLength) + var appendCount = 0 + var input = input.toUpperCase() + substituteSet.forEach { from, to -> + input = input.replace(from, to) + } + + fun append(byte: Int) { + buffer[appendCount] = byte.toByte() xor (password[appendCount % password.size]) + appendCount++ + } + fun sbyteOf(i: Int) = stringSet.indexOf(input[i]).and(0x1F) + + try { + /* + 8 Letters -> 5 Bytes + + 0000 0000 | 1111 1111 | 2222 2222 | 3333 3333 | 4444 4444 + AAAA ABBB | BBCC CCCD | DDDD EEEE | EFFF FFGG | GGGH HHHH + */ + (0..input.lastIndex.plus(8) step 8).forEach { + /* 0 */ append(sbyteOf(it+0).shl(3) or sbyteOf(it+1).ushr(2)) + /* 1 */ append(sbyteOf(it+1).shl(6) or sbyteOf(it+2).shl(1) or sbyteOf(it+3).ushr(4)) + /* 2 */ append(sbyteOf(it+3).shl(4) or sbyteOf(it+4).ushr(1)) + /* 3 */ append(sbyteOf(it+4).shl(7) or sbyteOf(it+5).shl(2) or sbyteOf(it+6).ushr(3)) + /* 4 */ append(sbyteOf(it+6).shl(5) or sbyteOf(it+7)) + } + } + catch (endOfStream: ArrayIndexOutOfBoundsException) { } + + return buffer + } +} diff --git a/src/net/torvald/terrarum/utils/RasterWriter.kt b/src/net/torvald/terrarum/utils/RasterWriter.kt new file mode 100644 index 000000000..7d60ec339 --- /dev/null +++ b/src/net/torvald/terrarum/utils/RasterWriter.kt @@ -0,0 +1,49 @@ +package net.torvald.terrarum.utils + +import javax.imageio.ImageIO +import java.awt.* +import java.awt.color.ColorSpace +import java.awt.image.* +import java.io.File +import java.io.IOException + +/** + * Created by minjaesong on 16-03-04. + */ +object RasterWriter { + + val BANDOFFSET_RGB = intArrayOf(0, 1, 2) + val BANDOFFSET_RGBA = intArrayOf(0, 1, 2, 3) + val BANDOFFSET_ARGB = intArrayOf(3, 0, 1, 2) + val BANDOFFSET_MONO = intArrayOf(0) + + val COLORSPACE_SRGB = java.awt.color.ColorSpace.CS_sRGB + val COLORSPACE_GRAY = java.awt.color.ColorSpace.CS_GRAY + val COLORSPACE_GREY = net.torvald.terrarum.utils.RasterWriter.COLORSPACE_GRAY + val COLORSPACE_CIEXYZ = java.awt.color.ColorSpace.CS_CIEXYZ + val COLORSPACE_RGB_LINEAR_GAMMA = java.awt.color.ColorSpace.CS_LINEAR_RGB + + @Throws(java.io.IOException::class) + fun writePNG_RGB(w: Int, h: Int, rasterData: ByteArray, path: String) { + net.torvald.terrarum.utils.RasterWriter.writePNG(w, h, rasterData, BANDOFFSET_RGB, COLORSPACE_SRGB, path) + } + + @Throws(java.io.IOException::class) + fun writePNG_Mono(w: Int, h: Int, rasterData: ByteArray, path: String) { + net.torvald.terrarum.utils.RasterWriter.writePNG(w, h, rasterData, BANDOFFSET_MONO, COLORSPACE_GREY, path) + } + + @Throws(java.io.IOException::class) + fun writePNG(w: Int, h: Int, rasterData: ByteArray, bandOffsets: IntArray, awt_colorspace: Int, path: String) { + val buffer = java.awt.image.DataBufferByte(rasterData, rasterData.size) + val raster = java.awt.image.Raster.createInterleavedRaster( + buffer, w, h, bandOffsets.size * w, bandOffsets.size, bandOffsets, null) + + val colorModel = java.awt.image.ComponentColorModel(java.awt.color.ColorSpace.getInstance(awt_colorspace), false, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE) + + val image = java.awt.image.BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied, null) + + javax.imageio.ImageIO.write(image, "PNG", java.io.File(path)) + } + +} diff --git a/src/net/torvald/terrarum/weather/WeatherMixer.kt b/src/net/torvald/terrarum/weather/WeatherMixer.kt index 75159eaac..b66046668 100644 --- a/src/net/torvald/terrarum/weather/WeatherMixer.kt +++ b/src/net/torvald/terrarum/weather/WeatherMixer.kt @@ -1,7 +1,6 @@ package net.torvald.terrarum.weather -import com.jme3.math.FastMath -import net.torvald.JsonFetcher +import net.torvald.terrarum.utils.JsonFetcher import net.torvald.colourutil.* import net.torvald.random.HQRNG import net.torvald.terrarum.* diff --git a/work_files/GameDesign/BACKEND_DESIGN.md b/work_files/GameDesign/BACKEND_DESIGN.md index ffc6ec98a..f28352e12 100644 --- a/work_files/GameDesign/BACKEND_DESIGN.md +++ b/work_files/GameDesign/BACKEND_DESIGN.md @@ -1,3 +1,5 @@ +The extension of [```THE_ENGINE.md```](THE_ENGINE.md) + The game has elements that are: - Actors