mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
character import wip
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
"GAME_ACTION_MOVE_VERB" : "Move",
|
"GAME_ACTION_MOVE_VERB" : "Move",
|
||||||
"GAME_ACTION_ZOOM" : "Zoom",
|
"GAME_ACTION_ZOOM" : "Zoom",
|
||||||
"MENU_IO_AUTOSAVE": "Autosave",
|
"MENU_IO_AUTOSAVE": "Autosave",
|
||||||
|
"MENU_IO_CLEAR": "Clear",
|
||||||
"MENU_IO_IMPORT": "Import",
|
"MENU_IO_IMPORT": "Import",
|
||||||
"MENU_IO_MANUAL_SAVE": "Manual Save",
|
"MENU_IO_MANUAL_SAVE": "Manual Save",
|
||||||
"MENU_LABEL_COPYRIGHT": "Copyright",
|
"MENU_LABEL_COPYRIGHT": "Copyright",
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
"MENU_LABEL_IME": "IME",
|
"MENU_LABEL_IME": "IME",
|
||||||
"MENU_LABEL_IME_TOGGLE": "Toggle IME",
|
"MENU_LABEL_IME_TOGGLE": "Toggle IME",
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "Keyboard Layout",
|
"MENU_LABEL_KEYBOARD_LAYOUT": "Keyboard Layout",
|
||||||
|
"MENU_LABEL_PASTE": "Paste",
|
||||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Clipboard",
|
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "Paste from Clipboard",
|
||||||
"MENU_LABEL_PRESS_START_SYMBOL": "Press >",
|
"MENU_LABEL_PRESS_START_SYMBOL": "Press >",
|
||||||
"MENU_LABEL_RESET" : "Reset",
|
"MENU_LABEL_RESET" : "Reset",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"GAME_ACTION_MOVE_VERB" : "이동하기",
|
"GAME_ACTION_MOVE_VERB" : "이동하기",
|
||||||
"GAME_ACTION_ZOOM" : "확대·축소",
|
"GAME_ACTION_ZOOM" : "확대·축소",
|
||||||
"MENU_IO_AUTOSAVE": "자동 저장",
|
"MENU_IO_AUTOSAVE": "자동 저장",
|
||||||
|
"MENU_IO_CLEAR": "지우기",
|
||||||
"MENU_IO_IMPORT": "가져오기",
|
"MENU_IO_IMPORT": "가져오기",
|
||||||
"MENU_IO_MANUAL_SAVE": "수동 저장",
|
"MENU_IO_MANUAL_SAVE": "수동 저장",
|
||||||
"MENU_LABEL_COPYRIGHT": "저작권",
|
"MENU_LABEL_COPYRIGHT": "저작권",
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
"MENU_LABEL_IME": "입력기",
|
"MENU_LABEL_IME": "입력기",
|
||||||
"MENU_LABEL_IME_TOGGLE": "입력기 켜고 끄기",
|
"MENU_LABEL_IME_TOGGLE": "입력기 켜고 끄기",
|
||||||
"MENU_LABEL_KEYBOARD_LAYOUT": "자판 배열",
|
"MENU_LABEL_KEYBOARD_LAYOUT": "자판 배열",
|
||||||
|
"MENU_LABEL_PASTE": "붙여넣기",
|
||||||
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "복사한 텍스트 붙여넣기",
|
"MENU_LABEL_PASTE_FROM_CLIPBOARD": "복사한 텍스트 붙여넣기",
|
||||||
"MENU_LABEL_PRESS_START_SYMBOL": ">을 누르세요",
|
"MENU_LABEL_PRESS_START_SYMBOL": ">을 누르세요",
|
||||||
"MENU_LABEL_RESET" : "재설정",
|
"MENU_LABEL_RESET" : "재설정",
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing."
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "Copy the Avatar Code into the clipboard, then hit the Paste button below.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_2": ""
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다."
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "아바타 코드를 클립보드에 복사한 다음, 아래의 붙여넣기 버튼을 눌러주세요.",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_2": ""
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
"cloudChance": 250,
|
"cloudChance": 250,
|
||||||
"cloudGamma": [0.48, 1.8],
|
"cloudGamma": [0.48, 1.8],
|
||||||
"cloudGammaVariance": [0.1, 0.1],
|
"cloudGammaVariance": [0.1, 0.1],
|
||||||
"windSpeed": 0.25,
|
"windSpeed": 10.25,
|
||||||
"windSpeedVariance": 1.0,
|
"windSpeedVariance": 1.0,
|
||||||
"clouds": {
|
"clouds": {
|
||||||
"cumulonimbus": {
|
"cumulonimbus": {
|
||||||
|
|||||||
161
src/net/torvald/terrarum/modulebasegame/ui/UIImportAvatar.kt
Normal file
161
src/net/torvald/terrarum/modulebasegame/ui/UIImportAvatar.kt
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.ui
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.Input
|
||||||
|
import com.badlogic.gdx.graphics.Camera
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.Second
|
||||||
|
import net.torvald.terrarum.ceilToInt
|
||||||
|
import net.torvald.terrarum.gamecontroller.*
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.serialise.Ascii85Codec
|
||||||
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
import net.torvald.terrarum.ui.UIItem
|
||||||
|
import net.torvald.terrarum.ui.UIItemTextButton
|
||||||
|
import net.torvald.terrarum.utils.Clipboard
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-24.
|
||||||
|
*/
|
||||||
|
class UIImportAvatar(val remoCon: UIRemoCon) : Advanceable() {
|
||||||
|
|
||||||
|
override var width = 480 // SAVE_CELL_WIDTH
|
||||||
|
override var height = 480
|
||||||
|
override var openCloseTime: Second = OPENCLOSE_GENERIC
|
||||||
|
|
||||||
|
private val drawX = (Toolkit.drawWidth - width) / 2
|
||||||
|
private val drawY = (App.scr.height - height) / 2
|
||||||
|
private val cols = 80
|
||||||
|
private val rows = 30
|
||||||
|
private val goButtonWidth = 180
|
||||||
|
|
||||||
|
|
||||||
|
private val codeBox = UIItemCodeBox(this, (Toolkit.drawWidth - App.fontSmallNumbers.W * cols) / 2, drawY, cols, rows)
|
||||||
|
|
||||||
|
private val clearButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_IO_CLEAR"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
private val pasteButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_LABEL_PASTE"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
|
||||||
|
|
||||||
|
private val backButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_LABEL_BACK"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
private val goButton = UIItemTextButton(this,
|
||||||
|
{ Lang["MENU_IO_IMPORT"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
|
||||||
|
init {
|
||||||
|
addUIitem(codeBox)
|
||||||
|
addUIitem(clearButton)
|
||||||
|
addUIitem(pasteButton)
|
||||||
|
addUIitem(backButton)
|
||||||
|
addUIitem(goButton)
|
||||||
|
|
||||||
|
clearButton.clickOnceListener = { _,_ ->
|
||||||
|
codeBox.clearTextBuffer()
|
||||||
|
}
|
||||||
|
pasteButton.clickOnceListener = { _,_ ->
|
||||||
|
codeBox.pasteFromClipboard()
|
||||||
|
}
|
||||||
|
backButton.clickOnceListener = { _,_ ->
|
||||||
|
remoCon.openUI(UILoadSavegame(remoCon))
|
||||||
|
}
|
||||||
|
goButton.clickOnceListener = { _,_ ->
|
||||||
|
doImport()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun updateUI(delta: Float) {
|
||||||
|
uiItems.forEach { it.update(delta) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||||
|
uiItems.forEach { it.render(batch, camera) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun advanceMode(button: UIItem) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doImport() {
|
||||||
|
val rawStr = codeBox.textBuffer.toString()
|
||||||
|
// sanity check
|
||||||
|
|
||||||
|
|
||||||
|
val ascii85codec = Ascii85Codec((33..117).map { it.toChar() }.joinToString(""))
|
||||||
|
val ascii85str = rawStr.substring(2 until rawStr.length - 2).replace("z", "!!!!!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UIItemCodeBox(parent: UIImportAvatar, initialX: Int, initialY: Int, val cols: Int = 80, val rows: Int = 24) : UIItem(parent, initialX, initialY) {
|
||||||
|
|
||||||
|
override val width = App.fontSmallNumbers.W * cols
|
||||||
|
override val height = App.fontSmallNumbers.H * rows
|
||||||
|
override fun dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private var highlightCol: Color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
|
||||||
|
var selected = false
|
||||||
|
|
||||||
|
private var textCursorPosition = 0
|
||||||
|
internal var textBuffer = StringBuilder()
|
||||||
|
|
||||||
|
fun pasteFromClipboard() {
|
||||||
|
textBuffer.clear()
|
||||||
|
Clipboard.fetch().forEach {
|
||||||
|
if (it.code in 33..122) textBuffer.append(it)
|
||||||
|
}
|
||||||
|
textCursorPosition += textBuffer.length
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(delta: Float) {
|
||||||
|
super.update(delta)
|
||||||
|
// if (!selected && mousePushed)
|
||||||
|
// selected = true
|
||||||
|
// else if (selected && mouseDown && !mouseUp)
|
||||||
|
// selected = false
|
||||||
|
|
||||||
|
if (textBuffer.isEmpty() && (Gdx.input.isKeyJustPressed(Input.Keys.V) && (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT)))) {
|
||||||
|
pasteFromClipboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
|
// draw box backgrounds
|
||||||
|
batch.color = UIInventoryFull.CELL_COL
|
||||||
|
Toolkit.fillArea(batch, posX, posY, width, height)
|
||||||
|
|
||||||
|
// draw borders
|
||||||
|
batch.color = if (selected) Toolkit.Theme.COL_SELECTED else if (mouseUp) Toolkit.Theme.COL_MOUSE_UP else Toolkit.Theme.COL_INACTIVE
|
||||||
|
Toolkit.drawBoxBorder(batch, posX - 1, posY - 1, width + 2, height + 2)
|
||||||
|
|
||||||
|
// draw texts
|
||||||
|
if (textBuffer.isEmpty()) {
|
||||||
|
batch.color = Toolkit.Theme.COL_INACTIVE
|
||||||
|
App.fontGame.draw(batch, Lang["CONTEXT_IMPORT_AVATAR_INSTRUCTION_1"], posX + 5, posY)
|
||||||
|
App.fontGame.draw(batch, Lang["CONTEXT_IMPORT_AVATAR_INSTRUCTION_2"], posX + 5f, posY + App.fontGame.lineHeight)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
val scroll = ((textBuffer.length.toDouble() / cols).ceilToInt() - rows).coerceAtLeast(0)
|
||||||
|
for (i in scroll * cols until textBuffer.length) {
|
||||||
|
val c = textBuffer[i]
|
||||||
|
val x = ((i - scroll * cols) % cols) * App.fontSmallNumbers.W.toFloat()
|
||||||
|
val y = ((i - scroll * cols) / cols) * App.fontSmallNumbers.H.toFloat()
|
||||||
|
|
||||||
|
App.fontSmallNumbers.draw(batch, "$c", posX + x, posY + y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearTextBuffer() {
|
||||||
|
textBuffer.clear()
|
||||||
|
textCursorPosition = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ object UITitleRemoConYaml {
|
|||||||
|
|
||||||
// todo add MENU_IO_IMPORT
|
// todo add MENU_IO_IMPORT
|
||||||
val injectedMenuSingleCharSel = """
|
val injectedMenuSingleCharSel = """
|
||||||
- MENU_IO_IMPORT
|
- MENU_IO_IMPORT : net.torvald.terrarum.modulebasegame.ui.UIImportAvatar
|
||||||
- CONTEXT_CHARACTER_NEW : net.torvald.terrarum.modulebasegame.ui.UINewCharacter
|
- CONTEXT_CHARACTER_NEW : net.torvald.terrarum.modulebasegame.ui.UINewCharacter
|
||||||
- MENU_LABEL_RETURN
|
- MENU_LABEL_RETURN
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -4,27 +4,26 @@ import net.torvald.terrarum.savegame.toBigEndian
|
|||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
|
|
||||||
/**
|
/** My own string set that:
|
||||||
* Ascii85 implementation with my own character table based on RFC 1924. Will NOT truncate '00000' into something else;
|
* - no "/": avoids nonstandard JSON comment key which GDX will happily parse away
|
||||||
* just gzip the inputstream instead!
|
* - no "\": you know what I mean\\intention
|
||||||
|
* - no "$": avoids Kotlin string template
|
||||||
|
* - no "[{]},": even the dumbest parser can comprehend the output
|
||||||
*/
|
*/
|
||||||
object Ascii85 {
|
open class Ascii85Codec(private val CHAR_TABLE: String = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#%&'()*+-.:;<=>?@^_`|~") {
|
||||||
/** My own string set that:
|
init {
|
||||||
* - no "/": avoids nonstandard JSON comment key which GDX will happily parse away
|
if (CHAR_TABLE.length != 85) throw IllegalArgumentException("CHAR_TABLE is not 85 chars long")
|
||||||
* - no "\": you know what I mean\\intention
|
}
|
||||||
* - no "$": avoids Kotlin string template
|
|
||||||
* - no "[{]},": even the dumbest parser can comprehend the output
|
|
||||||
*/
|
|
||||||
private const val CHAR_TABLE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#%&'()*+-.:;<=>?@^_`|~"
|
|
||||||
/** As per Adobe standard */
|
/** As per Adobe standard */
|
||||||
//private val CHAR_TABLE = (33 until (33+85)).toList().map { it.toChar() }.joinToString("") // testing only!
|
//private val CHAR_TABLE = (33 until (33+85)).toList().map { it.toChar() }.joinToString("") // testing only!
|
||||||
|
|
||||||
private val INVERSE_TABLE = LongArray(127)
|
private val INVERSE_TABLE = LongArray(127)
|
||||||
|
|
||||||
/** Int of `-1` */
|
/** Int of `-1` */
|
||||||
const val PAD_BYTE = -1
|
val PAD_BYTE = -1
|
||||||
/** Null-character (`\0`) */
|
/** Null-character (`\0`) */
|
||||||
const val PAD_CHAR = 0.toChar()
|
val PAD_CHAR = 0.toChar()
|
||||||
|
|
||||||
private val INTERNAL_PAD_BYTE = 0
|
private val INTERNAL_PAD_BYTE = 0
|
||||||
private val INTERNAL_PAD_CHAR = CHAR_TABLE.last()
|
private val INTERNAL_PAD_CHAR = CHAR_TABLE.last()
|
||||||
@@ -97,10 +96,10 @@ object Ascii85 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val sum = (INVERSE_TABLE[s1.toInt()] * 52200625) +
|
val sum = (INVERSE_TABLE[s1.toInt()] * 52200625) +
|
||||||
(INVERSE_TABLE[s2.toInt()] * 614125) +
|
(INVERSE_TABLE[s2.toInt()] * 614125) +
|
||||||
(INVERSE_TABLE[s3.toInt()] * 7225) +
|
(INVERSE_TABLE[s3.toInt()] * 7225) +
|
||||||
(INVERSE_TABLE[s4.toInt()] * 85) +
|
(INVERSE_TABLE[s4.toInt()] * 85) +
|
||||||
INVERSE_TABLE[s5.toInt()]
|
INVERSE_TABLE[s5.toInt()]
|
||||||
return ByteArray(4 - padLen) { sum.ushr((3 - it) * 8).and(255).toByte() }
|
return ByteArray(4 - padLen) { sum.ushr((3 - it) * 8).and(255).toByte() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +136,12 @@ object Ascii85 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ascii85 implementation with my own character table based on RFC 1924. Will NOT truncate '00000' into something else;
|
||||||
|
* just gzip the inputstream instead!
|
||||||
|
*/
|
||||||
|
object Ascii85 : Ascii85Codec()
|
||||||
|
|
||||||
fun UUID.toAscii85() =
|
fun UUID.toAscii85() =
|
||||||
Ascii85.encodeBytes(this.mostSignificantBits.toBigEndian() + this.leastSignificantBits.toBigEndian())
|
Ascii85.encodeBytes(this.mostSignificantBits.toBigEndian() + this.leastSignificantBits.toBigEndian())
|
||||||
fun String.ascii85toUUID(): UUID {
|
fun String.ascii85toUUID(): UUID {
|
||||||
|
|||||||
Reference in New Issue
Block a user