some organisation, Base32 password generator

This commit is contained in:
minjaesong
2017-05-03 02:37:03 +09:00
parent f8435711dd
commit c1ef44c2f2
29 changed files with 367 additions and 217 deletions

View File

@@ -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<sup>[citation needed]</sup> and has large memory footprint<sup>[citation needed]</sup> 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 ##

58
THE_ENGINE.md Normal file
View File

@@ -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<sup>[citation needed]</sup> and has large memory footprint<sup>[citation needed]</sup> 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

View File

@@ -1,21 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Lua" name="Lua">
<configuration SdkName="LuaJ" />
</facet>
<facet type="kotlin-language" name="Kotlin">
<configuration version="2" platform="JVM 1.6" useProjectSettings="false">
<compilerSettings />
<compilerArguments>
<option name="jvmTarget" value="1.6" />
<option name="languageVersion" value="1.1" />
<option name="apiVersion" value="1.1" />
<option name="coroutinesEnable" value="true" />
</compilerArguments>
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">

View File

@@ -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
}
}

View File

@@ -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))
}
}

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -84,5 +84,7 @@ abstract class Actor(val renderOrder: RenderOrder) : Comparable<Actor>, Runnable
*
* @param value null if the key is deleted
*/
abstract fun actorValueChanged(key: String, value: Any?)
abstract @Event fun onActorValueChange(key: String, value: Any?)
}
annotation class Event

View File

@@ -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!!

View File

@@ -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)
}
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
/**

View File

@@ -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

View File

@@ -1,6 +1,6 @@
package net.torvald.terrarum.gamecontroller
import net.torvald.JsonFetcher
import net.torvald.terrarum.utils.JsonFetcher
import java.util.*
/**

View File

@@ -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.*

View File

@@ -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<CSVRecord> {
csvString = StringBuffer() // reset buffer every time it called
readCSVasString(csvFilePath)
fun readFromFile(csvFilePath: String): List<org.apache.commons.csv.CSVRecord> {
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<CSVRecord> {
val csvParser = CSVParser.parse(
fun readFromString(csv: String): List<org.apache.commons.csv.CSVRecord> {
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()
}
}

View File

@@ -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 {

View File

@@ -1,4 +1,4 @@
package net.torvald
package net.torvald.terrarum.utils
import java.awt.Toolkit
import java.awt.datatransfer.DataFlavor

View File

@@ -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
}
}

View File

@@ -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()
}

View File

@@ -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<Int>()
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
}
}

View File

@@ -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))
}
}

View File

@@ -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.*

View File

@@ -1,3 +1,5 @@
The extension of [```THE_ENGINE.md```](THE_ENGINE.md)
The game has elements that are:
- Actors