control preset to be stored into separate file

This commit is contained in:
minjaesong
2026-02-07 16:19:42 +09:00
parent e838991826
commit 068d0bf1b2
22 changed files with 336 additions and 87 deletions

View File

@@ -447,6 +447,15 @@ public class App implements ApplicationListener {
createDirs();
initialiseConfig();
readConfigJson();
// Initialise control preset config (separate from main config)
ControlPresetConfig.initialise();
// Migrate control settings on first run with new system
File controlsFile = new File(controlPresetDir);
if (!controlsFile.exists()) {
ControlPresetConfig.migrateFromGenericConfig();
}
setGamepadButtonLabels();
rectifyConfigs();
@@ -1487,6 +1496,8 @@ public class App implements ApplicationListener {
public static String worldsDir;
/** defaultDir + "/config.json" */
public static String configDir;
/** defaultDir + "/controls.json" */
public static String controlPresetDir;
/** defaultDir + "/LoadOrder.txt" */
public static String loadOrderDir;
/** defaultDir + "/Imported" */
@@ -1532,6 +1543,7 @@ public class App implements ApplicationListener {
playersDir = defaultDir + "/Players";
worldsDir = defaultDir + "/Worlds";
configDir = defaultDir + "/config.json";
controlPresetDir = defaultDir + "/controls.json";
loadOrderDir = defaultDir + "/LoadOrder.txt";
recycledPlayersDir = defaultDir + "/Recycled/Players";
recycledWorldsDir = defaultDir + "/Recycled/Worlds";
@@ -1806,6 +1818,15 @@ public class App implements ApplicationListener {
public static Object getConfigMaster(String key1) {
String key = key1.toLowerCase();
// Delegate control_key_*, control_mouse_*, control_preset_keyboard to ControlPresetConfig
if (ControlPresetConfig.isControlKey(key)) {
Object result = ControlPresetConfig.get(key);
if (result != null) {
return result;
}
// Fall through to check defaults if ControlPresetConfig doesn't have it
}
Object config;
try {
config = gameConfig.get(key);

View File

@@ -0,0 +1,229 @@
package net.torvald.terrarum
import com.badlogic.gdx.Input
import com.badlogic.gdx.utils.Json
import com.badlogic.gdx.utils.JsonValue
import com.badlogic.gdx.utils.JsonWriter
import net.torvald.terrarum.utils.JsonFetcher
import java.io.File
import java.io.FileWriter
/**
* Holds and manages the control preset configuration separately from the main config.
* This allows users to easily share their control configurations via controls.json.
*
* Modules can register custom control labels using [registerModuleControl].
*
* Created by minjaesong on 2026-02-03.
*/
object ControlPresetConfig {
private val configMap = KVHashMap()
private val jsoner = Json(JsonWriter.OutputType.json)
// Default values for built-in controls
private val defaults = hashMapOf<String, Any>(
"control_preset_keyboard" to "WASD",
// Keyboard controls (ESDF defaults matching DefaultConfig)
"control_key_up" to Input.Keys.E,
"control_key_left" to Input.Keys.S,
"control_key_down" to Input.Keys.D,
"control_key_right" to Input.Keys.F,
"control_key_jump" to Input.Keys.SPACE,
"control_key_movementaux" to Input.Keys.A,
"control_key_inventory" to Input.Keys.Q,
"control_key_interact" to Input.Keys.R,
"control_key_discard" to Input.Keys.T,
"control_key_close" to Input.Keys.C,
"control_key_zoom" to Input.Keys.Z,
"control_key_gamemenu" to Input.Keys.TAB,
"control_key_crafting" to Input.Keys.W,
"control_key_quicksel" to Input.Keys.SHIFT_LEFT,
"control_key_toggleime" to Input.Keys.ALT_RIGHT,
// Mouse controls
"control_mouse_primary" to Input.Buttons.LEFT,
"control_mouse_secondary" to Input.Buttons.RIGHT,
"control_mouse_quicksel" to Input.Buttons.MIDDLE,
// Array-type controls
"control_key_quickslots" to ((Input.Keys.NUM_1..Input.Keys.NUM_9) + arrayOf(Input.Keys.NUM_0)).map { 1.0 * it }.toDoubleArray(),
"control_key_quickselalt" to intArrayOf(Input.Keys.BACKSPACE, Input.Keys.CONTROL_LEFT, Input.Keys.BACKSLASH).map { 1.0 * it }.toDoubleArray(),
)
init {
// Set up JSON serialiser for KVHashMap
jsoner.ignoreUnknownFields = true
jsoner.setUsePrototypes(false)
jsoner.setIgnoreDeprecated(false)
jsoner.setSerializer(KVHashMap::class.java, object : Json.Serializer<KVHashMap> {
override fun write(json: Json, obj: KVHashMap, knownType: Class<*>?) {
json.writeObjectStart()
obj.hashMap.toSortedMap().forEach { (k, v) ->
json.writeValue(k, v)
}
json.writeObjectEnd()
}
override fun read(json: Json, jsonData: JsonValue, type: Class<*>?): KVHashMap {
val map = KVHashMap()
JsonFetcher.forEachSiblings(jsonData) { key, obj ->
map[key] = json.readValue(null, obj)
}
return map
}
})
}
/**
* Initialises the control preset config with defaults, then loads from file.
* Should be called during App initialisation, BEFORE modules load.
*/
@JvmStatic
fun initialise() {
// Populate with defaults
defaults.forEach { (k, v) -> configMap[k] = v }
// Load from file if exists
loadFromFile()
}
/**
* Registers a custom control for a module.
* @param moduleName The module's identifier (directory name)
* @param device One of "key", "mouse" (not "gamepad")
* @param label The control label (e.g., "special_action")
* @param defaultValue The default key/button code
*/
fun registerModuleControl(moduleName: String, device: String, label: String, defaultValue: Int) {
require(device in listOf("key", "mouse")) { "Device must be 'key' or 'mouse', got '$device'" }
val key = "${moduleName}:control_${device}_$label"
if (!configMap.hasKey(key)) {
configMap[key] = defaultValue
}
}
/**
* Returns true if this key should be handled by ControlPresetConfig instead of App.gameConfig
*/
@JvmStatic
fun isControlKey(key: String): Boolean {
val k = key.lowercase()
return k.startsWith("control_key_") || k.startsWith("control_mouse_") || k == "control_preset_keyboard" ||
(k.contains(":control_key_") || k.contains(":control_mouse_"))
}
@JvmStatic
fun getString(key: String): String? = configMap.getAsString(key.lowercase()) ?: defaults[key.lowercase()] as? String
@JvmStatic
fun getInt(key: String): Int {
val k = key.lowercase()
val value = configMap[k] ?: defaults[k]
return when (value) {
is Int -> value
is Double -> value.toInt()
else -> -1
}
}
@JvmStatic
fun getIntArray(key: String): IntArray {
val k = key.lowercase()
val arr = configMap[k] ?: defaults[k]
return when (arr) {
is DoubleArray -> arr.map { it.toInt() }.toIntArray()
is IntArray -> arr
else -> intArrayOf()
}
}
@JvmStatic
fun getDoubleArray(key: String): DoubleArray {
val k = key.lowercase()
val arr = configMap[k] ?: defaults[k]
return when (arr) {
is DoubleArray -> arr
is IntArray -> arr.map { it.toDouble() }.toDoubleArray()
else -> doubleArrayOf()
}
}
@JvmStatic
fun get(key: String): Any? {
val k = key.lowercase()
return configMap[k] ?: defaults[k]
}
@JvmStatic
fun set(key: String, value: Any) {
configMap[key.lowercase()] = value
}
fun containsKey(key: String): Boolean {
val k = key.lowercase()
return configMap.hasKey(k) || defaults.containsKey(k)
}
/**
* Returns the key set of configured controls (excludes defaults not yet written)
*/
val keySet: Set<Any>
get() = configMap.keySet
private fun loadFromFile() {
val file = File(App.controlPresetDir)
if (!file.exists()) return
try {
val json = JsonFetcher(App.controlPresetDir)
var entry: JsonValue? = json.child
while (entry != null) {
configMap[entry.name] = when {
entry.isArray -> entry.asDoubleArray()
entry.isDouble -> entry.asDouble()
entry.isBoolean -> entry.asBoolean()
entry.isLong -> entry.asInt()
else -> entry.asString()
}
entry = entry.next
}
} catch (e: Exception) {
System.err.println("[ControlPresetConfig] Failed to load controls.json: ${e.message}")
}
}
@JvmStatic
fun save() {
try {
val writer = FileWriter(App.controlPresetDir, false)
writer.write(jsoner.prettyPrint(configMap))
writer.close()
} catch (e: Exception) {
System.err.println("[ControlPresetConfig] Failed to save controls.json: ${e.message}")
}
}
/**
* Migrates control settings from App.gameConfig to this config.
* Called once during first run with new system.
*/
@JvmStatic
fun migrateFromGenericConfig() {
val keysToMigrate = App.gameConfig.keySet.filter { key ->
val k = (key as String).lowercase()
k.startsWith("control_key_") || k.startsWith("control_mouse_") || k == "control_preset_keyboard"
}
if (keysToMigrate.isEmpty()) return
keysToMigrate.forEach { key ->
val k = key as String
configMap[k] = App.gameConfig[k]!!
}
save()
println("[ControlPresetConfig] Migrated ${keysToMigrate.size} control settings from config.json")
}
}

View File

@@ -3,6 +3,8 @@ package net.torvald.terrarum
import com.badlogic.gdx.Input
/**
* For mod authors: use `registerPreset()` to register new preset. This must be done on your [ModuleEntryPoint]
*
* Created by minjaesong on 2023-08-24.
*/
object ControlPresets {
@@ -23,7 +25,7 @@ object ControlPresets {
"control_key_gamemenu" to Input.Keys.TAB,
"control_key_crafting" to Input.Keys.F,
"control_key_quicksel" to Input.Keys.CONTROL_LEFT, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
"control_key_quicksel" to Input.Keys.CONTROL_LEFT, // pie menu is now LShift because CapsLock is actually used by my bespoke keyboard input
)
val esdf = hashMapOf<String, Int>(
@@ -42,7 +44,7 @@ object ControlPresets {
"control_key_gamemenu" to Input.Keys.TAB,
"control_key_crafting" to Input.Keys.W,
"control_key_quicksel" to Input.Keys.SHIFT_LEFT, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
"control_key_quicksel" to Input.Keys.SHIFT_LEFT, // pie menu is now LShift because CapsLock is actually used by my bespoke keyboard input
)
val ijkl = hashMapOf<String, Int>(
@@ -61,7 +63,7 @@ object ControlPresets {
"control_key_gamemenu" to Input.Keys.LEFT_BRACKET,
"control_key_crafting" to Input.Keys.O,
"control_key_quicksel" to Input.Keys.APOSTROPHE, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
"control_key_quicksel" to Input.Keys.APOSTROPHE, // pie menu is now LShift because CapsLock is actually used by my bespoke keyboard input
)
val empty = hashMapOf<String, Int>()
@@ -73,19 +75,31 @@ object ControlPresets {
"Custom" to empty,
)
val presetLabels = listOf( // ordered
val presetLabels = mutableListOf<String>( // ordered
"WASD",
"ESDF",
"IJKL",
"Custom",
)
/**
* Retrieves a keycode assigned to the action given as `label`, using currently active preset (`ControlPresetConfig.getString("control_preset_keyboard")`) as a reference.
*
* If `ControlPresetConfig.getString("control_preset_keyboard")` evaluates to `null`, preset "Custom" will be referenced instead.
*
* @throws IllegalStateException if for some reason the currently active preset is not a known one
*/
fun getKey(label: String?): Int {
if (label == null) return -1
val presetName = App.getConfigString("control_preset_keyboard") ?: "Custom"
val presetName = ControlPresetConfig.getString("control_preset_keyboard") ?: "Custom"
return (presets[presetName] ?: throw IllegalStateException("No such keyboard preset: $presetName")).getOrDefault(label, App.getConfigInt(label))
return (presets[presetName] ?: throw IllegalStateException("No such keyboard preset: $presetName")).getOrDefault(label, ControlPresetConfig.getInt(label))
}
fun registerPreset(label: String, keymap: HashMap<String, Int>) {
presets[label] = keymap
presetLabels.addLast(label)
}
}

View File

@@ -37,7 +37,7 @@ object DefaultConfig {
"usexinput" to true, // when FALSE, LT+RT input on xbox controller is impossible
"control_preset_keyboard" to "WASD",
// control_preset_keyboard now lives in ControlPresetConfig (controls.json)
"control_gamepad_keyn" to 3,
"control_gamepad_keyw" to 2,
@@ -65,38 +65,9 @@ object DefaultConfig {
// to accomodate shifted zero point of analog stick
"control_gamepad_axiszeropoints" to doubleArrayOf(0.0,0.0,0.0,0.0),
"control_gamepad_labelstyle" to "msxbone", // "nwii", "logitech", "sonyps", "msxb360", "msxbone"
// control-keyboard (GDX key codes,
"control_key_up" to Input.Keys.E,
"control_key_left" to Input.Keys.S,
"control_key_down" to Input.Keys.D,
"control_key_right" to Input.Keys.F, // ESDF Masterrace
"control_key_jump" to Input.Keys.SPACE,
"control_key_movementaux" to Input.Keys.A, // movement-auxiliary, or hookshot
"control_key_inventory" to Input.Keys.Q,
"control_key_interact" to Input.Keys.R,
"control_key_discard" to Input.Keys.T,
"control_key_close" to Input.Keys.C, // this or hard-coded ESC
"control_key_zoom" to Input.Keys.Z,
"control_key_gamemenu" to Input.Keys.TAB,
"control_key_crafting" to Input.Keys.W,
"control_key_quicksel" to Input.Keys.SHIFT_LEFT, // pie menu is now LShift because CapsLock is actually used by the my bespoke keyboard input
"control_mouse_quicksel" to Input.Buttons.MIDDLE, // middle click to open pie menu
// 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!
"control_key_quickslots" to ((Input.Keys.NUM_1..Input.Keys.NUM_9) + arrayOf(Input.Keys.NUM_0)).map { 1.0*it }.toDoubleArray(),
"control_key_quickselalt" to intArrayOf(Input.Keys.BACKSPACE, Input.Keys.CONTROL_LEFT, Input.Keys.BACKSLASH).map { 1.0*it }.toDoubleArray(),
"control_key_toggleime" to Input.Keys.ALT_RIGHT,
"config_mouseprimary" to Input.Buttons.LEFT, // left mouse
"config_mousesecondary" to Input.Buttons.RIGHT, // right mouse
"control_gamepad_labelstyle" to "msxbone", // "nintendo", "logitech", "sony", "msxb360", "msxbone"
// control_key_*, control_mouse_* entries now live in ControlPresetConfig (controls.json)
"pcgamepadenv" to "console",

View File

@@ -269,9 +269,9 @@ object Terrarum : Disposable {
inline val updateRate: Double
get() = 1.0 / Gdx.graphics.deltaTime
val mouseDown: Boolean
get() = Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))
get() = Gdx.input.isButtonPressed(App.getConfigInt("control_mouse_primary"))
val mouseJustDown: Boolean
get() = Gdx.input.isButtonJustPressed(App.getConfigInt("config_mouseprimary"))
get() = Gdx.input.isButtonJustPressed(App.getConfigInt("control_mouse_primary"))
val mouseOnPlayer: Boolean
get() = ingame?.actorNowPlaying?.mouseUp ?: false

View File

@@ -145,7 +145,7 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
terrarumIngame.worldPrimaryClickStart(actor, App.UPDATE_RATE)
worldPrimaryClickLatched = true
}
if (actor != null && Gdx.input.isButtonPressed(App.getConfigInt("config_mousesecondary"))) {
if (actor != null && Gdx.input.isButtonPressed(App.getConfigInt("control_mouse_secondary"))) {
terrarumIngame.worldSecondaryClickStart(actor, App.UPDATE_RATE)
}
@@ -258,10 +258,10 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
// fire world click events; the event is defined as Ingame's (or any others') WorldClick event
// if (terrarumIngame.uiContainer.map { if ((it?.isOpening == true || it?.isOpened == true) && it.mouseUp) 1 else 0 }.sum() == 0) { // no UI on the mouse, right?
if (button == App.getConfigInt("config_mouseprimary")) {
if (button == App.getConfigInt("control_mouse_primary")) {
terrarumIngame.worldPrimaryClickEnd(terrarumIngame.actorNowPlaying!!, App.UPDATE_RATE)
}
if (button == App.getConfigInt("config_mousesecondary")) {
if (button == App.getConfigInt("control_mouse_secondary")) {
terrarumIngame.worldSecondaryClickEnd(terrarumIngame.actorNowPlaying!!, App.UPDATE_RATE)
}
// }

View File

@@ -332,7 +332,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
if (!Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))) {
if (!Gdx.input.isButtonPressed(App.getConfigInt("control_mouse_primary"))) {
disableMouseClick = false
}
}
@@ -368,7 +368,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
// TODO drag support using bresenham's algo
// for some reason it just doesn't work...
}
else if (!uiPenMenu.isVisible && Gdx.input.isButtonPressed(App.getConfigInt("config_mousesecondary"))) {
else if (!uiPenMenu.isVisible && Gdx.input.isButtonPressed(App.getConfigInt("control_mouse_secondary"))) {
// open pen menu
// position the menu to where the cursor is
uiPenMenu.posX = Terrarum.mouseScreenX - uiPenMenu.width / 2

View File

@@ -513,7 +513,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
if (Terrarum.mouseScreenX in tx - 32 until tx + tw + 32 &&
Terrarum.mouseScreenY in ty2 - 16 until ty2 + App.fontGame.lineHeight.toInt() + 16) {
if (Gdx.input.isButtonJustPressed(App.getConfigInt("config_mouseprimary"))) {
if (Gdx.input.isButtonJustPressed(App.getConfigInt("control_mouse_primary"))) {
OpenURL(TerrarumAppConfiguration.FIXED_LATEST_DOWNLOAD_LINK)
}
batch.color = Toolkit.Theme.COL_SELECTED

View File

@@ -153,7 +153,7 @@ object BlockBase {
val wirePlaceMode = WireCodex[itemID].branching
if (Gdx.input.isButtonJustPressed(App.getConfigInt("config_mouseprimary")) ||
if (Gdx.input.isButtonJustPressed(App.getConfigInt("control_mouse_primary")) ||
!isNeighbouring(ww, mtx, mty, oldTileX, oldTileY)) {
initialMouseDownTileX = mtx
initialMouseDownTileY = mty

View File

@@ -22,8 +22,8 @@ class ItemWrench(originalID: ItemID) : GameItem(originalID), FixtureInteractionB
companion object {
private val SP = "\u3000"
private val ML = getMouseButton(App.getConfigInt("config_mouseprimary"))
private val MR = getMouseButton(App.getConfigInt("config_mousesecondary"))
private val ML = getMouseButton(App.getConfigInt("control_mouse_primary"))
private val MR = getMouseButton(App.getConfigInt("control_mouse_secondary"))
}
override val disallowToolDragging = true

View File

@@ -35,9 +35,9 @@ object SmelterGuiEventBuilder {
): (GameItem?, Long, Int, Any?, UIItemInventoryCellBase) -> Unit { return { gameItem: GameItem?, amount: Long, mouseButton: Int, itemExtraInfo: Any?, theButton: UIItemInventoryCellBase ->
val playerInventory = getPlayerInventory()
val amount = if (mouseButton == App.getConfigInt("config_mouseprimary"))
val amount = if (mouseButton == App.getConfigInt("control_mouse_primary"))
amount
else if (mouseButton == App.getConfigInt("config_mousesecondary"))
else if (mouseButton == App.getConfigInt("control_mouse_secondary"))
1
else
null
@@ -175,9 +175,9 @@ object SmelterGuiEventBuilder {
itemListUpdate { oreItemFilter(it.itm) }
}
else if (oreItemStatus.isNotNull()) {
val removeCount = if (mouseButton == App.getConfigInt("config_mouseprimary"))
val removeCount = if (mouseButton == App.getConfigInt("control_mouse_primary"))
oreItemStatus.qty
else if (mouseButton == App.getConfigInt("config_mousesecondary"))
else if (mouseButton == App.getConfigInt("control_mouse_secondary"))
1L
else
null
@@ -254,9 +254,9 @@ object SmelterGuiEventBuilder {
itemListUpdate { ItemCodex.hasTag(it.itm, "COMBUSTIBLE") }
}
else if (fireboxItemStatus.isNotNull()) {
val removeCount = if (mouseButton == App.getConfigInt("config_mouseprimary"))
val removeCount = if (mouseButton == App.getConfigInt("control_mouse_primary"))
fireboxItemStatus.qty
else if (mouseButton == App.getConfigInt("config_mousesecondary"))
else if (mouseButton == App.getConfigInt("control_mouse_secondary"))
1L
else
null
@@ -333,9 +333,9 @@ object SmelterGuiEventBuilder {
}
if (productItemStatus.isNotNull()) {
val removeCount = if (mouseButton == App.getConfigInt("config_mouseprimary"))
val removeCount = if (mouseButton == App.getConfigInt("control_mouse_primary"))
productItemStatus.qty
else if (mouseButton == App.getConfigInt("config_mousesecondary"))
else if (mouseButton == App.getConfigInt("control_mouse_secondary"))
1L
else
null

View File

@@ -260,8 +260,8 @@ class UIAlloyingFurnace(val smelter: FixtureAlloyingFurnace) : UICanvas(
}
private val SP = "\u3000"
private val ML = getMouseButton(App.getConfigInt("config_mouseprimary"))
private val MR = getMouseButton(App.getConfigInt("config_mousesecondary"))
private val ML = getMouseButton(App.getConfigInt("control_mouse_primary"))
private val MR = getMouseButton(App.getConfigInt("control_mouse_secondary"))
private val MW = getMouseButton(2)
private val controlHelpForSmelter = listOf(
// no slot selected

View File

@@ -150,7 +150,7 @@ open class UIItemInventoryItemGrid(
fun createInvCellGenericTouchDownFun(listRebuildFun: () -> Unit): (GameItem?, Long, Int, Any?, UIItemInventoryCellBase) -> Unit {
return { item: GameItem?, amount: Long, button: Int, _, _ ->
if (button == App.getConfigInt("config_mouseprimary")) {
if (button == App.getConfigInt("control_mouse_primary")) {
if (item != null && Terrarum.ingame != null) {
// equip da shit
val itemEquipSlot = item.equipPosition

View File

@@ -61,7 +61,7 @@ class UIJukeboxInventory(val parent: UIJukebox) : UICanvas() {
init {
fixtureDiscCell.forEachIndexed { index, thisButton ->
thisButton.touchDownFun = { gameItem, amount, mouseButton, _, _ ->
if (operatedByTheInstaller && mouseButton == App.getConfigInt("config_mouseprimary")) {
if (operatedByTheInstaller && mouseButton == App.getConfigInt("control_mouse_primary")) {
if (gameItem != null) {
// if the disc being removed is the same disc being played, stop the playback
if (index == parent.parent.discCurrentlyPlaying) {
@@ -175,7 +175,7 @@ class UIJukeboxSonglistPanel(val parent: UIJukebox) : UICanvas() {
colourTheme = songButtonColourTheme,
keyDownFun = { _, _, _ -> Unit },
touchDownFun = { index, button, _ ->
if (button == App.getConfigInt("config_mouseprimary") && !parent.parent.musicIsPlaying) {
if (button == App.getConfigInt("control_mouse_primary") && !parent.parent.musicIsPlaying) {
parent.parent.playDisc(index)
}
}

View File

@@ -139,7 +139,8 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
}*/
presetSelector.selectionChangeListener = { index ->
App.setConfig("control_preset_keyboard", ControlPresets.presetLabels[index])
ControlPresetConfig.set("control_preset_keyboard", ControlPresets.presetLabels[index])
ControlPresetConfig.save()
updateKeycaps()
}
@@ -163,8 +164,11 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
"control_key_crafting",
"control_key_discard",
).forEach {
App.setConfig(it, DefaultConfig.hashMap[it]!! as Int)
// Reset to ESDF defaults (matches ControlPresetConfig defaults)
val defaultKey = ControlPresets.esdf[it] ?: return@forEach
ControlPresetConfig.set(it, defaultKey)
}
ControlPresetConfig.save()
}
private fun updateKeycaps() {
@@ -243,18 +247,19 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
}
fun setControlOf(key: Int, control: Int) {
if (App.getConfigString("control_preset_keyboard") != "Custom") {
System.err.println("[UIKeyboardControlPanel] cannot set a control if the preset is not 'Custom' (current preset: ${App.getConfigString("control_preset_keyboard")})")
if (ControlPresetConfig.getString("control_preset_keyboard") != "Custom") {
System.err.println("[UIKeyboardControlPanel] cannot set a control if the preset is not 'Custom' (current preset: ${ControlPresetConfig.getString("control_preset_keyboard")})")
return
}
if (control >= 0) {
val controlName = UIItemControlPaletteBaloon.indexToConfigKey[control]!!
val conflicts = App.gameConfig.keySet.filter {
// Check for conflicts in ControlPresetConfig
val conflicts = ControlPresetConfig.keySet.filter {
(it as String).startsWith("control_key_")
}.map {
(it as String).let { it to
try { (App.getConfigInt(it) == key) }
try { (ControlPresetConfig.getInt(it) == key) }
catch (_: ClassCastException) { false }
}
}.filter { it.second }.map { it.first }.firstOrNull()
@@ -262,13 +267,14 @@ class UIKeyboardControlPanel(remoCon: UIRemoCon?) : UICanvas() {
println("[UIKeyboardControlPanel] key=$key, control=$controlName")
if (conflicts != null) {
val oldValue = App.getConfigInt(controlName)
App.setConfig(conflicts, oldValue)
val oldValue = ControlPresetConfig.getInt(controlName)
ControlPresetConfig.set(conflicts, oldValue)
println("[UIKeyboardControlPanel] set config $conflicts=$oldValue")
}
App.setConfig(controlName, key)
ControlPresetConfig.set(controlName, key)
ControlPresetConfig.save()
println("[UIKeyboardControlPanel] set config $controlName=$key")
}
updateKeycaps()

View File

@@ -246,8 +246,8 @@ class UISmelterBasic(val smelter: FixtureSmelterBasic) : UICanvas(
}
private val SP = "\u3000"
private val ML = getMouseButton(App.getConfigInt("config_mouseprimary"))
private val MR = getMouseButton(App.getConfigInt("config_mousesecondary"))
private val ML = getMouseButton(App.getConfigInt("control_mouse_primary"))
private val MR = getMouseButton(App.getConfigInt("control_mouse_secondary"))
private val MW = getMouseButton(2)
private val controlHelpForSmelter = listOf(
// no slot selected

View File

@@ -97,9 +97,9 @@ internal class UIStorageChest : UICanvas(
itemListChest = UITemplateHalfInventory(this, true, { getFixtureInventory() }, { chestNameFun() }).also {
it.itemListKeyDownFun = { _, _, _, _, _ -> Unit }
it.itemListTouchDownFun = { gameItem, amount, button, _, _ ->
val amount = if (button == App.getConfigInt("config_mouseprimary"))
val amount = if (button == App.getConfigInt("control_mouse_primary"))
amount
else if (button == App.getConfigInt("config_mousesecondary"))
else if (button == App.getConfigInt("control_mouse_secondary"))
1
else
null
@@ -137,9 +137,9 @@ internal class UIStorageChest : UICanvas(
itemListPlayer = UITemplateHalfInventory(this, false).also {
it.itemListKeyDownFun = { _, _, _, _, _ -> Unit }
it.itemListTouchDownFun = { gameItem, amount, button, _, _ ->
val amount = if (button == App.getConfigInt("config_mouseprimary"))
val amount = if (button == App.getConfigInt("control_mouse_primary"))
amount
else if (button == App.getConfigInt("config_mousesecondary"))
else if (button == App.getConfigInt("control_mouse_secondary"))
1
else
null
@@ -227,8 +227,8 @@ internal class UIStorageChest : UICanvas(
private val cellsWidth = (UIItemInventoryItemGrid.listGap + UIItemInventoryElemWide.height) * 6 - UIItemInventoryItemGrid.listGap
private val SP = "\u3000"
private val ML = getMouseButton(App.getConfigInt("config_mouseprimary"))
private val MR = getMouseButton(App.getConfigInt("config_mousesecondary"))
private val ML = getMouseButton(App.getConfigInt("control_mouse_primary"))
private val MR = getMouseButton(App.getConfigInt("control_mouse_secondary"))
private val MW = getMouseButton(2)
private val controlHelpLeft: String
get() = if (App.environment == RunningEnvironment.PC)

View File

@@ -96,7 +96,7 @@ class UIWorldPortalCargo(val full: UIWorldPortal) : UICanvas(), HasInventory {
keyDownFun = { _, _, _, _, _ -> Unit },
wheelFun = { _, _, _, _, _, _ -> },
touchDownFun = { gameItem, amount, button, _, _ ->
if (button == App.getConfigInt("config_mouseprimary")) {
if (button == App.getConfigInt("control_mouse_primary")) {
if (gameItem != null) {
negotiator.refund(getFixtureInventory(), getPlayerInventory(), gameItem, amount)
}
@@ -119,7 +119,7 @@ class UIWorldPortalCargo(val full: UIWorldPortal) : UICanvas(), HasInventory {
keyDownFun = { _, _, _, _, _ -> Unit },
wheelFun = { _, _, _, _, _, _ -> },
touchDownFun = { gameItem, amount, button, _, _ ->
if (button == App.getConfigInt("config_mouseprimary")) {
if (button == App.getConfigInt("control_mouse_primary")) {
if (gameItem != null) {
negotiator.accept(getPlayerInventory(), getFixtureInventory(), gameItem, amount)
}

View File

@@ -4,6 +4,7 @@ import com.badlogic.gdx.utils.Json
import com.badlogic.gdx.utils.JsonValue
import com.badlogic.gdx.utils.JsonWriter
import net.torvald.terrarum.App
import net.torvald.terrarum.ControlPresetConfig
import net.torvald.terrarum.KVHashMap
import net.torvald.terrarum.Principii
import net.torvald.terrarum.utils.JsonFetcher
@@ -61,9 +62,16 @@ object WriteConfig {
}*/
operator fun invoke() {
// Filter out control entries that now live in controls.json
val filteredConfig = KVHashMap()
App.gameConfig.hashMap.forEach { (k, v) ->
if (!ControlPresetConfig.isControlKey(k)) {
filteredConfig[k] = v
}
}
val writer = java.io.FileWriter(App.configDir, false)
//writer.write(getJson())
writer.write(jsoner.prettyPrint(App.gameConfig))
writer.write(jsoner.prettyPrint(filteredConfig))
writer.close()
}

View File

@@ -87,7 +87,7 @@ class ConsoleWindow : UICanvas() {
releaseTooltip()
// click to enter the actor's reference ID
if (lb.size > 0 && !clickLatched && Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))) {
if (lb.size > 0 && !clickLatched && Gdx.input.isButtonPressed(App.getConfigInt("control_mouse_primary"))) {
clickLatched = true
textinput.appendText(lb.first().substringBefore(' '))
}
@@ -100,7 +100,7 @@ class ConsoleWindow : UICanvas() {
uiItems.forEach { it.update(delta) }
if (!Gdx.input.isButtonPressed(App.getConfigInt("config_mouseprimary"))) {
if (!Gdx.input.isButtonPressed(App.getConfigInt("control_mouse_primary"))) {
clickLatched = false
}

View File

@@ -7,7 +7,7 @@ import java.util.concurrent.atomic.AtomicBoolean
/**
* Created by minjaesong on 2024-01-10.
*/
class MouseLatch(val button: List<Int> = listOf(App.getConfigInt("config_mouseprimary"))) {
class MouseLatch(val button: List<Int> = listOf(App.getConfigInt("control_mouse_primary"))) {
private val status = AtomicBoolean()

View File

@@ -249,7 +249,7 @@ abstract class UIItem(var parentUI: UICanvas, val initialX: Int, val initialY: I
actionDone = true
}
if (!clickOnceListenerFired && mouseUp && button == App.getConfigInt("config_mouseprimary")) {
if (!clickOnceListenerFired && mouseUp && button == App.getConfigInt("control_mouse_primary")) {
clickOnceListener.invoke(itemRelativeMouseX, itemRelativeMouseY)
if (!suppressHaptic)
playHapticPushedDown()