mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
code input wip
This commit is contained in:
@@ -159,9 +159,12 @@ object InputStrober {
|
|||||||
|
|
||||||
data class TerrarumKeyboardEvent(
|
data class TerrarumKeyboardEvent(
|
||||||
val type: Int,
|
val type: Int,
|
||||||
val character: String, // representative key symbol
|
/** representative key symbol */
|
||||||
val headkey: Int, // representative keycode
|
val character: String,
|
||||||
|
/** representative keycode */
|
||||||
|
val headkey: Int,
|
||||||
val repeatCount: Int,
|
val repeatCount: Int,
|
||||||
|
/** always fixed size of 8 elements */
|
||||||
val keycodes: IntArray
|
val keycodes: IntArray
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import net.torvald.terrarum.App
|
|||||||
import net.torvald.terrarum.ControlPresets
|
import net.torvald.terrarum.ControlPresets
|
||||||
import net.torvald.terrarum.INGAME
|
import net.torvald.terrarum.INGAME
|
||||||
import net.torvald.terrarum.RunningEnvironment
|
import net.torvald.terrarum.RunningEnvironment
|
||||||
|
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.ui.*
|
import net.torvald.terrarum.ui.*
|
||||||
import net.torvald.unicode.getKeycapPC
|
import net.torvald.unicode.getKeycapPC
|
||||||
@@ -54,6 +55,27 @@ class UIRedeemCodeMachine : UICanvas(
|
|||||||
private val thisOffsetX = UIInventoryFull.INVENTORY_CELLS_OFFSET_X() + UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap - halfSlotOffset
|
private val thisOffsetX = UIInventoryFull.INVENTORY_CELLS_OFFSET_X() + UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap - halfSlotOffset
|
||||||
private val yEnd = -UIInventoryFull.YPOS_CORRECTION + (App.scr.height + UIInventoryFull.internalHeight).div(2).toFloat()
|
private val yEnd = -UIInventoryFull.YPOS_CORRECTION + (App.scr.height + UIInventoryFull.internalHeight).div(2).toFloat()
|
||||||
|
|
||||||
|
private val alphnums = (('0'..'9') + ('a'..'z') + ('A'..'Z')).map { "$it" }.toHashSet()
|
||||||
|
|
||||||
|
override fun inputStrobed(e: TerrarumKeyboardEvent) {
|
||||||
|
super.inputStrobed(e)
|
||||||
|
|
||||||
|
if (alphnums.contains(e.character)) {
|
||||||
|
inputPanel.acceptChar(e.character[0].uppercaseChar())
|
||||||
|
}
|
||||||
|
else if (e.keycodes[0] == Input.Keys.BACKSPACE && e.keycodes[1] == 0) {
|
||||||
|
inputPanel.backspace()
|
||||||
|
}
|
||||||
|
else if (e.keycodes[0] == Input.Keys.FORWARD_DEL && e.keycodes[1] == 0) {
|
||||||
|
inputPanel.reverseBackspace()
|
||||||
|
}
|
||||||
|
else if (e.keycodes[0] == Input.Keys.LEFT && e.keycodes[1] == 0) {
|
||||||
|
inputPanel.__moveCursorBackward(1)
|
||||||
|
}
|
||||||
|
else if (e.keycodes[0] == Input.Keys.RIGHT && e.keycodes[1] == 0) {
|
||||||
|
inputPanel.__moveCursorForward(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
|
override fun renderImpl(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
|
||||||
UIInventoryFull.drawBackground(batch, 1f)
|
UIInventoryFull.drawBackground(batch, 1f)
|
||||||
|
|||||||
@@ -43,10 +43,15 @@ class UIItemRedeemCodeArea(
|
|||||||
|
|
||||||
|
|
||||||
private val inputText = StringBuilder(textCols * textRows)
|
private val inputText = StringBuilder(textCols * textRows)
|
||||||
|
private fun ensureLength() {
|
||||||
|
inputText.append(" ".repeat((textCols * textRows) - inputText.length + 1))
|
||||||
|
inputText.setLength(textCols * textRows)
|
||||||
|
}
|
||||||
private var textCaret = 0
|
private var textCaret = 0
|
||||||
fun clearInput() { inputText.clear(); textCaret = 0 }
|
fun clearInput() { inputText.clear(); textCaret = 0 }
|
||||||
fun acceptChar(char: Char): Boolean {
|
fun acceptChar(char: Char): Boolean {
|
||||||
if (textCaret in 0 until textCols * textRows) {
|
if (textCaret in 0 until textCols * textRows) {
|
||||||
|
ensureLength()
|
||||||
inputText.insert(textCaret, char)
|
inputText.insert(textCaret, char)
|
||||||
textCaret++
|
textCaret++
|
||||||
return true
|
return true
|
||||||
@@ -54,25 +59,27 @@ class UIItemRedeemCodeArea(
|
|||||||
else return false
|
else return false
|
||||||
}
|
}
|
||||||
fun backspace(): Boolean {
|
fun backspace(): Boolean {
|
||||||
if (textCaret in 1 until textCols * textRows) {
|
if (textCaret in 1 .. textCols * textRows) {
|
||||||
inputText.deleteCharAt(textCaret - 1)
|
inputText.deleteCharAt(textCaret - 1)
|
||||||
|
ensureLength()
|
||||||
textCaret--
|
textCaret--
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
else return false
|
else return false
|
||||||
}
|
}
|
||||||
fun reverseBackspace(): Boolean {
|
fun reverseBackspace(): Boolean {
|
||||||
if (textCaret in 0 until (textCols * textRows - 1)) {
|
if (textCaret in 0 .. (textCols * textRows - 1)) {
|
||||||
inputText.deleteCharAt(textCaret)
|
inputText.deleteCharAt(textCaret)
|
||||||
|
ensureLength()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
else return false
|
else return false
|
||||||
}
|
}
|
||||||
fun __moveCursorBackward(delta: Int = 1) {
|
fun __moveCursorBackward(delta: Int = 1) {
|
||||||
textCaret = (textCaret - 1).coerceIn(0, textCols * textRows)
|
textCaret = (textCaret - 1).coerceIn(0, textCols * textRows - 1)
|
||||||
}
|
}
|
||||||
fun __moveCursorForward(delta: Int = 1) {
|
fun __moveCursorForward(delta: Int = 1) {
|
||||||
textCaret = (textCaret + 1).coerceIn(0, textCols * textRows)
|
textCaret = (textCaret + 1).coerceIn(0, textCols * textRows - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getInputAsString() = inputText.toString()
|
fun getInputAsString() = inputText.toString()
|
||||||
@@ -117,7 +124,7 @@ class UIItemRedeemCodeArea(
|
|||||||
for (x in 0 until textCols) {
|
for (x in 0 until textCols) {
|
||||||
BigAlphNum.draw(
|
BigAlphNum.draw(
|
||||||
batch,
|
batch,
|
||||||
"${inputText.getOrElse(y * textRows + x) { ' ' }}",
|
"${inputText.getOrElse(y * textCols + x) { ' ' }}",
|
||||||
posX + CELL_W * x + 2f,
|
posX + CELL_W * x + 2f,
|
||||||
posY + CELL_H * y + 4f
|
posY + CELL_H * y + 4f
|
||||||
)
|
)
|
||||||
@@ -127,8 +134,8 @@ class UIItemRedeemCodeArea(
|
|||||||
// draw caret
|
// draw caret
|
||||||
if (cursorBlinkTimer < 0.5f) {
|
if (cursorBlinkTimer < 0.5f) {
|
||||||
batch.color = caretCol
|
batch.color = caretCol
|
||||||
val cx = textCaret % textCols
|
val cx = if (textCaret >= textCols * textRows) textCols else textCaret % textCols
|
||||||
val cy = textCaret / textCols
|
val cy = if (textCaret >= textCols * textRows) textRows - 1 else textCaret / textCols
|
||||||
Toolkit.drawStraightLine(
|
Toolkit.drawStraightLine(
|
||||||
batch,
|
batch,
|
||||||
posX + CELL_W * cx - 1,
|
posX + CELL_W * cx - 1,
|
||||||
|
|||||||
87
src/net/torvald/terrarum/utils/BloomFilter.kt
Normal file
87
src/net/torvald/terrarum/utils/BloomFilter.kt
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package net.torvald.terrarum.utils
|
||||||
|
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.security.MessageDigest
|
||||||
|
import java.security.NoSuchAlgorithmException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-02-05.
|
||||||
|
*/
|
||||||
|
class BloomFilter(capacity: Int, k: Int) {
|
||||||
|
private var set: ByteArray
|
||||||
|
|
||||||
|
private var keySize = 0
|
||||||
|
private var setSize: Int = 0
|
||||||
|
|
||||||
|
private var empty = true
|
||||||
|
|
||||||
|
private var md: MessageDigest? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
setSize = capacity
|
||||||
|
set = ByteArray(setSize)
|
||||||
|
keySize = k
|
||||||
|
empty = true
|
||||||
|
md = try {
|
||||||
|
MessageDigest.getInstance("MD5")
|
||||||
|
}
|
||||||
|
catch (e: NoSuchAlgorithmException) {
|
||||||
|
throw IllegalArgumentException("Error : MD5 Hash not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun makeEmpty() {
|
||||||
|
set = ByteArray(setSize)
|
||||||
|
empty = true
|
||||||
|
md = try {
|
||||||
|
MessageDigest.getInstance("MD5")
|
||||||
|
}
|
||||||
|
catch (e: NoSuchAlgorithmException) {
|
||||||
|
throw IllegalArgumentException("Error : MD5 Hash not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun restoreFromByteArray(oldSet: ByteArray) {
|
||||||
|
if (this.set.size != oldSet.size)
|
||||||
|
throw IllegalStateException("Cannot restore from bytes: expected ${this.set.size} byte-set, got ${oldSet.size} instead")
|
||||||
|
|
||||||
|
this.set = oldSet
|
||||||
|
|
||||||
|
empty = set.all { it == 0.toByte() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isEmpty() = empty
|
||||||
|
|
||||||
|
private fun getHash(i: Int): Int {
|
||||||
|
md!!.reset()
|
||||||
|
val bytes: ByteArray = ByteBuffer.allocate(4).putInt(i).array()
|
||||||
|
md!!.update(bytes, 0, bytes.size)
|
||||||
|
return Math.abs(BigInteger(1, md!!.digest()).toInt()) % (set.size - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(obj: Int) {
|
||||||
|
val tmpset = getSetArray(obj)
|
||||||
|
for (i in tmpset) set[i] = 1
|
||||||
|
empty = false
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun contains(obj: Int): Boolean {
|
||||||
|
val tmpset = getSetArray(obj)
|
||||||
|
for (i in tmpset) if (set[i].toInt() != 1) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSetArray(obj: Int): IntArray {
|
||||||
|
val tmpset = IntArray(keySize)
|
||||||
|
tmpset[0] = getHash(obj)
|
||||||
|
for (i in 1 until keySize) tmpset[i] = getHash(tmpset[i - 1])
|
||||||
|
return tmpset
|
||||||
|
}
|
||||||
|
|
||||||
|
fun serialise(): ByteArray {
|
||||||
|
val returningSet = ByteArray(setSize)
|
||||||
|
System.arraycopy(set, 0, returningSet, 0, setSize)
|
||||||
|
return returningSet
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,8 @@ The main game directory is composed of following directories:
|
|||||||
[-5] screenshot.tga.gz
|
[-5] screenshot.tga.gz
|
||||||
[-1025] !optional! sprite-bodypart-name-to-entry-number-map.properties,
|
[-1025] !optional! sprite-bodypart-name-to-entry-number-map.properties,
|
||||||
[-1026] !optional! spriteglow-bodypart-name-to-entry-number-map.properties,
|
[-1026] !optional! spriteglow-bodypart-name-to-entry-number-map.properties,
|
||||||
|
/* -2147483648 and onward are for BLOBs */
|
||||||
|
[-2147483648] Redeemed Codes Bloom Filter
|
||||||
[1+] !optional! bodyparts tga.gz
|
[1+] !optional! bodyparts tga.gz
|
||||||
}
|
}
|
||||||
*if file -1025 is not there, read bodyparts from assets directory
|
*if file -1025 is not there, read bodyparts from assets directory
|
||||||
|
|||||||
Reference in New Issue
Block a user