aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-10-13 21:46:46 +0200
committerLinnea Gräf <nea@nea.moe>2024-10-13 21:46:46 +0200
commit4e9b0ded27df8b6ce7f5b2fa1b4b1ddbc1cbd452 (patch)
treea489fdd97e6c4dde1bd77bf216ed9c2ec2657db3 /src
parent0cc77949c907d38497f8cdf6fd8198fe5f0a9440 (diff)
downloadFirmament-4e9b0ded27df8b6ce7f5b2fa1b4b1ddbc1cbd452.tar.gz
Firmament-4e9b0ded27df8b6ce7f5b2fa1b4b1ddbc1cbd452.tar.bz2
Firmament-4e9b0ded27df8b6ce7f5b2fa1b4b1ddbc1cbd452.zip
Add config categories
Diffstat (limited to 'src')
-rw-r--r--src/compat/configured/java/BaseConfigNode.kt5
-rw-r--r--src/compat/configured/java/ConfiguredCompat.kt3
-rw-r--r--src/compat/yacl/java/YaclIntegration.kt24
-rw-r--r--src/main/kotlin/commands/rome.kt7
-rw-r--r--src/main/kotlin/features/chat/AutoCompletions.kt76
-rw-r--r--src/main/kotlin/features/chat/ChatLinks.kt2
-rw-r--r--src/main/kotlin/features/debug/DeveloperFeatures.kt2
-rw-r--r--src/main/kotlin/features/debug/PowerUserTools.kt2
-rw-r--r--src/main/kotlin/features/diana/DianaWaypoints.kt2
-rw-r--r--src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt2
-rw-r--r--src/main/kotlin/features/events/carnival/CarnivalFeatures.kt2
-rw-r--r--src/main/kotlin/features/fixes/CompatibliltyFeatures.kt2
-rw-r--r--src/main/kotlin/features/fixes/Fixes.kt2
-rw-r--r--src/main/kotlin/features/inventory/ItemRarityCosmetics.kt2
-rw-r--r--src/main/kotlin/features/inventory/PetFeatures.kt3
-rw-r--r--src/main/kotlin/features/inventory/PriceData.kt2
-rw-r--r--src/main/kotlin/features/inventory/SaveCursorPosition.kt2
-rw-r--r--src/main/kotlin/features/inventory/SlotLocking.kt2
-rw-r--r--src/main/kotlin/features/inventory/buttons/InventoryButtons.kt2
-rw-r--r--src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt2
-rw-r--r--src/main/kotlin/features/mining/PickaxeAbility.kt2
-rw-r--r--src/main/kotlin/features/mining/PristineProfitTracker.kt2
-rw-r--r--src/main/kotlin/features/texturepack/CustomSkyBlockTextures.kt2
-rw-r--r--src/main/kotlin/features/world/FairySouls.kt2
-rw-r--r--src/main/kotlin/features/world/Waypoints.kt2
-rw-r--r--src/main/kotlin/gui/config/AllConfigsGui.kt46
-rw-r--r--src/main/kotlin/gui/config/ManagedConfig.kt340
-rw-r--r--src/main/kotlin/gui/config/ManagedOption.kt2
-rw-r--r--src/main/kotlin/repo/RepoManager.kt4
-rw-r--r--src/main/resources/assets/firmament/gui/config/category.xml42
-rw-r--r--src/main/resources/assets/firmament/gui/config/main.xml6
-rw-r--r--src/main/resources/assets/firmament/lang/en_us.json13
32 files changed, 363 insertions, 246 deletions
diff --git a/src/compat/configured/java/BaseConfigNode.kt b/src/compat/configured/java/BaseConfigNode.kt
index 7330990..afe0375 100644
--- a/src/compat/configured/java/BaseConfigNode.kt
+++ b/src/compat/configured/java/BaseConfigNode.kt
@@ -4,11 +4,12 @@ import com.mrcrayfish.configured.api.IConfigEntry
import com.mrcrayfish.configured.api.IConfigValue
import net.minecraft.text.Text
import moe.nea.firmament.gui.config.AllConfigsGui
+import moe.nea.firmament.gui.config.ManagedConfig
object BaseConfigNode : IConfigEntry {
override fun getChildren(): List<IConfigEntry> {
- return AllConfigsGui.allConfigs.map {
- ConfigNode(it)
+ return ManagedConfig.allManagedConfigs.getAll().map {
+ ConfigNode(it) // TODO: fix add categories here
}
}
diff --git a/src/compat/configured/java/ConfiguredCompat.kt b/src/compat/configured/java/ConfiguredCompat.kt
index a5b78bb..8e8b022 100644
--- a/src/compat/configured/java/ConfiguredCompat.kt
+++ b/src/compat/configured/java/ConfiguredCompat.kt
@@ -6,6 +6,7 @@ import com.mrcrayfish.configured.api.IModConfigProvider
import com.mrcrayfish.configured.api.ModContext
import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.config.AllConfigsGui
+import moe.nea.firmament.gui.config.ManagedConfig
/**
* Registered in `fabric.mod.json` at `custom.configured.providers`
@@ -23,7 +24,7 @@ class ConfiguredCompat : IModConfigProvider {
return "firmament.config.all-configs"
}
})
- AllConfigsGui.allConfigs.mapTo(this) { ConfigCategory(it) }
+ ManagedConfig.allManagedConfigs.getAll().mapTo(this) { ConfigCategory(it) }
}
}
}
diff --git a/src/compat/yacl/java/YaclIntegration.kt b/src/compat/yacl/java/YaclIntegration.kt
index 6c9354a..fc5ff59 100644
--- a/src/compat/yacl/java/YaclIntegration.kt
+++ b/src/compat/yacl/java/YaclIntegration.kt
@@ -6,6 +6,7 @@ import dev.isxander.yacl3.api.ButtonOption
import dev.isxander.yacl3.api.ConfigCategory
import dev.isxander.yacl3.api.LabelOption
import dev.isxander.yacl3.api.Option
+import dev.isxander.yacl3.api.OptionGroup
import dev.isxander.yacl3.api.YetAnotherConfigLib
import dev.isxander.yacl3.api.controller.ControllerBuilder
import dev.isxander.yacl3.api.controller.DoubleSliderControllerBuilder
@@ -17,7 +18,6 @@ import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.Text
-import moe.nea.firmament.gui.config.AllConfigsGui
import moe.nea.firmament.gui.config.BooleanHandler
import moe.nea.firmament.gui.config.ClickHandler
import moe.nea.firmament.gui.config.DurationHandler
@@ -36,15 +36,20 @@ import moe.nea.firmament.util.FirmFormatters
@AutoService(FirmamentConfigScreenProvider::class)
class YaclIntegration : FirmamentConfigScreenProvider {
fun buildCategories() =
- AllConfigsGui.allConfigs
+ ManagedConfig.Category.entries
.map(::buildCategory)
- private fun buildCategory(managedConfig: ManagedConfig): ConfigCategory {
+ private fun buildCategory(category: ManagedConfig.Category): ConfigCategory {
return ConfigCategory.createBuilder()
- .name(managedConfig.labelText)
- .also {
- it.rootGroupBuilder()
- .options(buildOptions(managedConfig.sortedOptions))
+ .name(category.labelText)
+ .also { categoryB ->
+ category.configs.forEach {
+ categoryB.group(
+ OptionGroup.createBuilder()
+ .name(it.labelText)
+ .options(buildOptions(it.sortedOptions))
+ .build())
+ }
}
.build()
}
@@ -54,7 +59,10 @@ class YaclIntegration : FirmamentConfigScreenProvider {
private fun <T : Any> buildOption(managedOption: ManagedOption<T>): Option<*> {
val handler = managedOption.handler
- val binding = Binding.generic(managedOption.default(), managedOption::value, managedOption::value.setter)
+ val binding = Binding.generic(managedOption.default(),
+ managedOption::value,
+ { managedOption.value = it; managedOption.element.save() })
+
fun <T> createDefaultBinding(function: (Option<T>) -> ControllerBuilder<T>): Option.Builder<T> {
return Option.createBuilder<T>()
.name(managedOption.labelText)
diff --git a/src/main/kotlin/commands/rome.kt b/src/main/kotlin/commands/rome.kt
index cc4f4ba..4f54872 100644
--- a/src/main/kotlin/commands/rome.kt
+++ b/src/main/kotlin/commands/rome.kt
@@ -17,6 +17,7 @@ import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverviewScreen
import moe.nea.firmament.gui.config.AllConfigsGui
import moe.nea.firmament.gui.config.BooleanHandler
+import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.gui.config.ManagedOption
import moe.nea.firmament.init.MixinPlugin
import moe.nea.firmament.repo.HypixelStaticData
@@ -39,11 +40,11 @@ fun firmamentCommand() = literal("firmament") {
thenLiteral("toggle") {
thenArgument("config", string()) { config ->
suggestsList {
- AllConfigsGui.allConfigs.asSequence().map { it.name }.asIterable()
+ ManagedConfig.allManagedConfigs.getAll().asSequence().map { it.name }.asIterable()
}
thenArgument("property", string()) { property ->
suggestsList {
- (AllConfigsGui.allConfigs.find { it.name == this[config] } ?: return@suggestsList listOf())
+ (ManagedConfig.allManagedConfigs.getAll().find { it.name == this[config] } ?: return@suggestsList listOf())
.allOptions.entries.asSequence().filter { it.value.handler is BooleanHandler }
.map { it.key }
.asIterable()
@@ -52,7 +53,7 @@ fun firmamentCommand() = literal("firmament") {
val config = this[config]
val property = this[property]
- val configObj = AllConfigsGui.allConfigs.find { it.name == config }
+ val configObj = ManagedConfig.allManagedConfigs.getAll().find { it.name == config }
if (configObj == null) {
source.sendFeedback(
Text.stringifiedTranslatable(
diff --git a/src/main/kotlin/features/chat/AutoCompletions.kt b/src/main/kotlin/features/chat/AutoCompletions.kt
index 9144898..9e0de40 100644
--- a/src/main/kotlin/features/chat/AutoCompletions.kt
+++ b/src/main/kotlin/features/chat/AutoCompletions.kt
@@ -1,5 +1,3 @@
-
-
package moe.nea.firmament.features.chat
import com.mojang.brigadier.arguments.StringArgumentType.string
@@ -17,41 +15,41 @@ import moe.nea.firmament.util.MC
object AutoCompletions : FirmamentFeature {
- object TConfig : ManagedConfig(identifier) {
- val provideWarpTabCompletion by toggle("warp-complete") { true }
- val replaceWarpIsByWarpIsland by toggle("warp-is") { true }
- }
-
- override val config: ManagedConfig?
- get() = TConfig
- override val identifier: String
- get() = "auto-completions"
-
- @Subscribe
- fun onMaskCommands(event: MaskCommands) {
- if (TConfig.provideWarpTabCompletion) {
- event.mask("warp")
- }
- }
-
- @Subscribe
- fun onCommandEvent(event: CommandEvent) {
- if (!TConfig.provideWarpTabCompletion) return
- event.deleteCommand("warp")
- event.register("warp") {
- thenArgument("to", string()) { toArg ->
- suggestsList {
- RepoManager.neuRepo.constants?.islands?.warps?.flatMap { listOf(it.warp) + it.aliases } ?: listOf()
- }
- thenExecute {
- val warpName = get(toArg)
- if (warpName == "is" && TConfig.replaceWarpIsByWarpIsland) {
- MC.sendServerCommand("warp island")
- } else {
- MC.sendServerCommand("warp $warpName")
- }
- }
- }
- }
- }
+ object TConfig : ManagedConfig(identifier, Category.CHAT) {
+ val provideWarpTabCompletion by toggle("warp-complete") { true }
+ val replaceWarpIsByWarpIsland by toggle("warp-is") { true }
+ }
+
+ override val config: ManagedConfig?
+ get() = TConfig
+ override val identifier: String
+ get() = "auto-completions"
+
+ @Subscribe
+ fun onMaskCommands(event: MaskCommands) {
+ if (TConfig.provideWarpTabCompletion) {
+ event.mask("warp")
+ }
+ }
+
+ @Subscribe
+ fun onCommandEvent(event: CommandEvent) {
+ if (!TConfig.provideWarpTabCompletion) return
+ event.deleteCommand("warp")
+ event.register("warp") {
+ thenArgument("to", string()) { toArg ->
+ suggestsList {
+ RepoManager.neuRepo.constants?.islands?.warps?.flatMap { listOf(it.warp) + it.aliases } ?: listOf()
+ }
+ thenExecute {
+ val warpName = get(toArg)
+ if (warpName == "is" && TConfig.replaceWarpIsByWarpIsland) {
+ MC.sendServerCommand("warp island")
+ } else {
+ MC.sendServerCommand("warp $warpName")
+ }
+ }
+ }
+ }
+ }
}
diff --git a/src/main/kotlin/features/chat/ChatLinks.kt b/src/main/kotlin/features/chat/ChatLinks.kt
index f2cb78a..0681f57 100644
--- a/src/main/kotlin/features/chat/ChatLinks.kt
+++ b/src/main/kotlin/features/chat/ChatLinks.kt
@@ -35,7 +35,7 @@ object ChatLinks : FirmamentFeature {
override val identifier: String
get() = "chat-links"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.CHAT) {
val enableLinks by toggle("links-enabled") { true }
val imageEnabled by toggle("image-enabled") { true }
val allowAllHosts by toggle("allow-all-hosts") { false }
diff --git a/src/main/kotlin/features/debug/DeveloperFeatures.kt b/src/main/kotlin/features/debug/DeveloperFeatures.kt
index 56ee398..2001a3f 100644
--- a/src/main/kotlin/features/debug/DeveloperFeatures.kt
+++ b/src/main/kotlin/features/debug/DeveloperFeatures.kt
@@ -26,7 +26,7 @@ object DeveloperFeatures : FirmamentFeature {
.iterate { it.parent }
.find { it.resolve("settings.gradle.kts").exists() }
- object TConfig : ManagedConfig("developer") {
+ object TConfig : ManagedConfig("developer", Category.DEV) {
val autoRebuildResources by toggle("auto-rebuild") { false }
}
diff --git a/src/main/kotlin/features/debug/PowerUserTools.kt b/src/main/kotlin/features/debug/PowerUserTools.kt
index 529f011..83e3aff 100644
--- a/src/main/kotlin/features/debug/PowerUserTools.kt
+++ b/src/main/kotlin/features/debug/PowerUserTools.kt
@@ -37,7 +37,7 @@ object PowerUserTools : FirmamentFeature {
override val identifier: String
get() = "power-user"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.DEV) {
val showItemIds by toggle("show-item-id") { false }
val copyItemId by keyBindingWithDefaultUnbound("copy-item-id")
val copyTexturePackId by keyBindingWithDefaultUnbound("copy-texture-pack-id")
diff --git a/src/main/kotlin/features/diana/DianaWaypoints.kt b/src/main/kotlin/features/diana/DianaWaypoints.kt
index 205e237..6d87262 100644
--- a/src/main/kotlin/features/diana/DianaWaypoints.kt
+++ b/src/main/kotlin/features/diana/DianaWaypoints.kt
@@ -10,7 +10,7 @@ object DianaWaypoints : FirmamentFeature {
override val identifier get() = "diana"
override val config get() = TConfig
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.EVENTS) {
val ancestralSpadeSolver by toggle("ancestral-spade") { true }
val ancestralSpadeTeleport by keyBindingWithDefaultUnbound("ancestral-teleport")
val nearbyWaypoints by toggle("nearby-waypoints") { true }
diff --git a/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt b/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt
index 8926a95..825cd6c 100644
--- a/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt
+++ b/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt
@@ -28,7 +28,7 @@ object AnniversaryFeatures : FirmamentFeature {
override val identifier: String
get() = "anniversary"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.EVENTS) {
val enableShinyPigTracker by toggle("shiny-pigs") {true}
val trackPigCooldown by position("pig-hud", 200, 300) { Point(0.1, 0.2) }
}
diff --git a/src/main/kotlin/features/events/carnival/CarnivalFeatures.kt b/src/main/kotlin/features/events/carnival/CarnivalFeatures.kt
index 1e6d97a..840fb8c 100644
--- a/src/main/kotlin/features/events/carnival/CarnivalFeatures.kt
+++ b/src/main/kotlin/features/events/carnival/CarnivalFeatures.kt
@@ -5,7 +5,7 @@ import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig
object CarnivalFeatures : FirmamentFeature {
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.EVENTS) {
val enableBombSolver by toggle("bombs-solver") { true }
val displayTutorials by toggle("tutorials") { true }
}
diff --git a/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt b/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt
index 7c43cf6..fa9cdda 100644
--- a/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt
+++ b/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt
@@ -16,7 +16,7 @@ object CompatibliltyFeatures : FirmamentFeature {
override val identifier: String
get() = "compatibility"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.INTEGRATIONS) {
val enhancedExplosions by toggle("explosion-enabled") { false }
val explosionSize by integer("explosion-power", 10, 50) { 1 }
}
diff --git a/src/main/kotlin/features/fixes/Fixes.kt b/src/main/kotlin/features/fixes/Fixes.kt
index d7b7a1c..5d70b1a 100644
--- a/src/main/kotlin/features/fixes/Fixes.kt
+++ b/src/main/kotlin/features/fixes/Fixes.kt
@@ -21,7 +21,7 @@ object Fixes : FirmamentFeature {
override val identifier: String
get() = "fixes"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.MISC) { // TODO: split this config
val fixUnsignedPlayerSkins by toggle("player-skins") { true }
var autoSprint by toggle("auto-sprint") { false }
val autoSprintKeyBinding by keyBindingWithDefaultUnbound("auto-sprint-keybinding")
diff --git a/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt b/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt
index 424f13b..77f5071 100644
--- a/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt
+++ b/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt
@@ -22,7 +22,7 @@ object ItemRarityCosmetics : FirmamentFeature {
override val identifier: String
get() = "item-rarity-cosmetics"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
val showItemRarityBackground by toggle("background") { false }
val showItemRarityInHotbar by toggle("background-hotbar") { false }
}
diff --git a/src/main/kotlin/features/inventory/PetFeatures.kt b/src/main/kotlin/features/inventory/PetFeatures.kt
index 81124f3..2c11e76 100644
--- a/src/main/kotlin/features/inventory/PetFeatures.kt
+++ b/src/main/kotlin/features/inventory/PetFeatures.kt
@@ -7,7 +7,6 @@ import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.petData
-import moe.nea.firmament.util.unformattedString
import moe.nea.firmament.util.useMatch
object PetFeatures : FirmamentFeature {
@@ -17,7 +16,7 @@ object PetFeatures : FirmamentFeature {
override val config: ManagedConfig?
get() = TConfig
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
val highlightEquippedPet by toggle("highlight-pet") { true }
}
diff --git a/src/main/kotlin/features/inventory/PriceData.kt b/src/main/kotlin/features/inventory/PriceData.kt
index c61f8e8..4477203 100644
--- a/src/main/kotlin/features/inventory/PriceData.kt
+++ b/src/main/kotlin/features/inventory/PriceData.kt
@@ -15,7 +15,7 @@ object PriceData : FirmamentFeature {
override val identifier: String
get() = "price-data"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
val tooltipEnabled by toggle("enable-always") { true }
val enableKeybinding by keyBindingWithDefaultUnbound("enable-keybind")
}
diff --git a/src/main/kotlin/features/inventory/SaveCursorPosition.kt b/src/main/kotlin/features/inventory/SaveCursorPosition.kt
index 1c55753..c47867b 100644
--- a/src/main/kotlin/features/inventory/SaveCursorPosition.kt
+++ b/src/main/kotlin/features/inventory/SaveCursorPosition.kt
@@ -15,7 +15,7 @@ object SaveCursorPosition : FirmamentFeature {
override val identifier: String
get() = "save-cursor-position"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
val enable by toggle("enable") { true }
val tolerance by duration("tolerance", 10.milliseconds, 5000.milliseconds) { 500.milliseconds }
}
diff --git a/src/main/kotlin/features/inventory/SlotLocking.kt b/src/main/kotlin/features/inventory/SlotLocking.kt
index 9f13af8..611b7e4 100644
--- a/src/main/kotlin/features/inventory/SlotLocking.kt
+++ b/src/main/kotlin/features/inventory/SlotLocking.kt
@@ -46,7 +46,7 @@ object SlotLocking : FirmamentFeature {
val lockedUUIDs: MutableSet<UUID> = mutableSetOf(),
)
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
val lockSlot by keyBinding("lock") { GLFW.GLFW_KEY_L }
val lockUUID by keyBindingWithOutDefaultModifiers("lock-uuid") {
SavedKeyBinding(GLFW.GLFW_KEY_L, shift = true)
diff --git a/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt b/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt
index fa90d21..ca64f80 100644
--- a/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt
+++ b/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt
@@ -20,7 +20,7 @@ object InventoryButtons : FirmamentFeature {
override val identifier: String
get() = "inventory-buttons"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
val _openEditor by button("open-editor") {
openEditor()
}
diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt
index b615c73..333b0fb 100644
--- a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt
+++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt
@@ -27,7 +27,7 @@ object StorageOverlay : FirmamentFeature {
override val identifier: String
get() = "storage-overlay"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.INVENTORY) {
val alwaysReplace by toggle("always-replace") { true }
val columns by integer("rows", 1, 10) { 3 }
val scrollSpeed by integer("scroll-speed", 1, 50) { 10 }
diff --git a/src/main/kotlin/features/mining/PickaxeAbility.kt b/src/main/kotlin/features/mining/PickaxeAbility.kt
index 1853d65..1444284 100644
--- a/src/main/kotlin/features/mining/PickaxeAbility.kt
+++ b/src/main/kotlin/features/mining/PickaxeAbility.kt
@@ -39,7 +39,7 @@ object PickaxeAbility : FirmamentFeature {
get() = "pickaxe-info"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.MINING) {
val cooldownEnabled by toggle("ability-cooldown") { true }
val cooldownScale by integer("ability-scale", 16, 64) { 16 }
val drillFuelBar by toggle("fuel-bar") { true }
diff --git a/src/main/kotlin/features/mining/PristineProfitTracker.kt b/src/main/kotlin/features/mining/PristineProfitTracker.kt
index f1bc7e5..dd9be42 100644
--- a/src/main/kotlin/features/mining/PristineProfitTracker.kt
+++ b/src/main/kotlin/features/mining/PristineProfitTracker.kt
@@ -49,7 +49,7 @@ object PristineProfitTracker : FirmamentFeature {
override val config: ManagedConfig?
get() = TConfig
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.MINING) {
val timeout by duration("timeout", 0.seconds, 120.seconds) { 30.seconds }
val gui by position("position", 80, 30) { Point(0.05, 0.2) }
}
diff --git a/src/main/kotlin/features/texturepack/CustomSkyBlockTextures.kt b/src/main/kotlin/features/texturepack/CustomSkyBlockTextures.kt
index 2aca8e8..b641959 100644
--- a/src/main/kotlin/features/texturepack/CustomSkyBlockTextures.kt
+++ b/src/main/kotlin/features/texturepack/CustomSkyBlockTextures.kt
@@ -26,7 +26,7 @@ object CustomSkyBlockTextures : FirmamentFeature {
override val identifier: String
get() = "custom-skyblock-textures"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.INTEGRATIONS) { // TODO: should this be its own thing?
val enabled by toggle("enabled") { true }
val skullsEnabled by toggle("skulls-enabled") { true }
val cacheForever by toggle("cache-forever") { true }
diff --git a/src/main/kotlin/features/world/FairySouls.kt b/src/main/kotlin/features/world/FairySouls.kt
index 8a8291a..eec9b04 100644
--- a/src/main/kotlin/features/world/FairySouls.kt
+++ b/src/main/kotlin/features/world/FairySouls.kt
@@ -38,7 +38,7 @@ object FairySouls : FirmamentFeature {
object DConfig : ProfileSpecificDataHolder<Data>(serializer(), "found-fairysouls", ::Data)
- object TConfig : ManagedConfig("fairy-souls") {
+ object TConfig : ManagedConfig("fairy-souls", Category.MISC) {
val displaySouls by toggle("show") { false }
val resetSouls by button("reset") {
DConfig.data?.foundSouls?.clear() != null
diff --git a/src/main/kotlin/features/world/Waypoints.kt b/src/main/kotlin/features/world/Waypoints.kt
index 91a06da..d535b4e 100644
--- a/src/main/kotlin/features/world/Waypoints.kt
+++ b/src/main/kotlin/features/world/Waypoints.kt
@@ -38,7 +38,7 @@ object Waypoints : FirmamentFeature {
override val identifier: String
get() = "waypoints"
- object TConfig : ManagedConfig(identifier) {
+ object TConfig : ManagedConfig(identifier, Category.MINING) { // TODO: add to misc
val tempWaypointDuration by duration("temp-waypoint-duration", 0.seconds, 1.hours) { 30.seconds }
val showIndex by toggle("show-index") { true }
val skipToNearest by toggle("skip-to-nearest") { false }
diff --git a/src/main/kotlin/gui/config/AllConfigsGui.kt b/src/main/kotlin/gui/config/AllConfigsGui.kt
index c72b8b0..0e68bc8 100644
--- a/src/main/kotlin/gui/config/AllConfigsGui.kt
+++ b/src/main/kotlin/gui/config/AllConfigsGui.kt
@@ -4,24 +4,35 @@ import io.github.notenoughupdates.moulconfig.observer.ObservableList
import io.github.notenoughupdates.moulconfig.xml.Bind
import net.minecraft.client.gui.screen.Screen
import net.minecraft.text.Text
-import moe.nea.firmament.features.FeatureManager
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.MoulConfigUtils
import moe.nea.firmament.util.ScreenUtil.setScreenLater
object AllConfigsGui {
+//
+// val allConfigs
+// get() = listOf(
+// RepoManager.Config
+// ) + FeatureManager.allFeatures.mapNotNull { it.config }
- val allConfigs
- get() = listOf(
- RepoManager.Config
- ) + FeatureManager.allFeatures.mapNotNull { it.config }
+ object ConfigConfig : ManagedConfig("configconfig", Category.META) {
+ val enableYacl by toggle("enable-yacl") { false }
+ }
fun <T> List<T>.toObservableList(): ObservableList<T> = ObservableList(this)
- class MainMapping(val allConfigs: List<ManagedConfig>) {
+ class CategoryMapping(val category: ManagedConfig.Category) {
@get:Bind("configs")
- val configs = allConfigs.map { EntryMapping(it) }.toObservableList()
+ val configs = category.configs.map { EntryMapping(it) }.toObservableList()
+
+ @Bind
+ fun name() = category.labelText.string
+
+ @Bind
+ fun close() {
+ MC.screen?.close()
+ }
class EntryMapping(val config: ManagedConfig) {
@Bind
@@ -34,12 +45,29 @@ object AllConfigsGui {
}
}
+ class CategoryView {
+ @get:Bind("categories")
+ val categories = ManagedConfig.Category.entries
+ .map { CategoryEntry(it) }
+ .toObservableList()
+
+ class CategoryEntry(val category: ManagedConfig.Category) {
+ @Bind
+ fun name() = category.labelText.string
+
+ @Bind
+ fun open() {
+ MC.screen = MoulConfigUtils.loadScreen("config/category", CategoryMapping(category), MC.screen)
+ }
+ }
+ }
+
fun makeBuiltInScreen(parent: Screen? = null): Screen {
- return MoulConfigUtils.loadScreen("config/main", MainMapping(allConfigs), parent)
+ return MoulConfigUtils.loadScreen("config/main", CategoryView(), parent)
}
fun makeScreen(parent: Screen? = null): Screen {
- val wantedKey = if (RepoManager.Config.enableYacl) "yacl" else "builtin"
+ val wantedKey = if (ConfigConfig.enableYacl) "yacl" else "builtin"
val provider = FirmamentConfigScreenProvider.providers.find { it.key == wantedKey }
?: FirmamentConfigScreenProvider.providers.first()
return provider.open(parent)
diff --git a/src/main/kotlin/gui/config/ManagedConfig.kt b/src/main/kotlin/gui/config/ManagedConfig.kt
index 0d942e2..44c6e59 100644
--- a/src/main/kotlin/gui/config/ManagedConfig.kt
+++ b/src/main/kotlin/gui/config/ManagedConfig.kt
@@ -1,5 +1,3 @@
-
-
package moe.nea.firmament.gui.config
import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
@@ -26,157 +24,191 @@ import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.FirmButtonComponent
import moe.nea.firmament.keybindings.SavedKeyBinding
import moe.nea.firmament.util.ScreenUtil.setScreenLater
-
-abstract class ManagedConfig(override val name: String) : ManagedConfigElement() {
-
- interface OptionHandler<T : Any> {
- fun initOption(opt: ManagedOption<T>) {}
- fun toJson(element: T): JsonElement?
- fun fromJson(element: JsonElement): T
- fun emitGuiElements(opt: ManagedOption<T>, guiAppender: GuiAppender)
- }
-
- val file = Firmament.CONFIG_DIR.resolve("$name.json")
- val data: JsonObject by lazy {
- try {
- Firmament.json.decodeFromString(
- file.readText()
- )
- } catch (e: Exception) {
- Firmament.logger.info("Could not read config $name. Loading empty config.")
- JsonObject(mutableMapOf())
- }
- }
-
- fun save() {
- val data = JsonObject(allOptions.mapNotNull { (key, value) ->
- value.toJson()?.let {
- key to it
- }
- }.toMap())
- file.parent.createDirectories()
- file.writeText(Firmament.json.encodeToString(data))
- }
-
-
- val allOptions = mutableMapOf<String, ManagedOption<*>>()
- val sortedOptions = mutableListOf<ManagedOption<*>>()
-
- private var latestGuiAppender: GuiAppender? = null
-
- protected fun <T : Any> option(
- propertyName: String,
- default: () -> T,
- handler: OptionHandler<T>
- ): ManagedOption<T> {
- if (propertyName in allOptions) error("Cannot register the same name twice")
- return ManagedOption(this, propertyName, default, handler).also {
- it.handler.initOption(it)
- it.load(data)
- allOptions[propertyName] = it
- sortedOptions.add(it)
- }
- }
-
- protected fun toggle(propertyName: String, default: () -> Boolean): ManagedOption<Boolean> {
- return option(propertyName, default, BooleanHandler(this))
- }
-
- protected fun duration(
- propertyName: String,
- min: Duration,
- max: Duration,
- default: () -> Duration,
- ): ManagedOption<Duration> {
- return option(propertyName, default, DurationHandler(this, min, max))
- }
-
-
- protected fun position(
- propertyName: String,
- width: Int,
- height: Int,
- default: () -> Point,
- ): ManagedOption<HudMeta> {
- val label = Text.translatable("firmament.config.${name}.${propertyName}")
- return option(propertyName, {
- val p = default()
- HudMeta(HudPosition(p.x, p.y, 1F), label, width, height)
- }, HudMetaHandler(this, label, width, height))
- }
-
- protected fun keyBinding(
- propertyName: String,
- default: () -> Int,
- ): ManagedOption<SavedKeyBinding> = keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(default()) }
-
- protected fun keyBindingWithOutDefaultModifiers(
- propertyName: String,
- default: () -> SavedKeyBinding,
- ): ManagedOption<SavedKeyBinding> {
- return option(propertyName, default, KeyBindingHandler("firmament.config.${name}.${propertyName}", this))
- }
-
- protected fun keyBindingWithDefaultUnbound(
- propertyName: String,
- ): ManagedOption<SavedKeyBinding> {
- return keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN) }
- }
-
- protected fun integer(
- propertyName: String,
- min: Int,
- max: Int,
- default: () -> Int,
- ): ManagedOption<Int> {
- return option(propertyName, default, IntegerHandler(this, min, max))
- }
-
- protected fun button(propertyName: String, runnable: () -> Unit): ManagedOption<Unit> {
- return option(propertyName, { }, ClickHandler(this, runnable))
- }
-
- protected fun string(propertyName: String, default: () -> String): ManagedOption<String> {
- return option(propertyName, default, StringHandler(this))
- }
-
-
- fun reloadGui() {
- latestGuiAppender?.reloadables?.forEach { it() }
- }
-
- val translationKey get() = "firmament.config.${name}"
- val labelText = Text.translatable(translationKey)
-
- fun getConfigEditor(parent: Screen? = null): Screen {
- var screen: Screen? = null
- val guiapp = GuiAppender(400) { requireNotNull(screen) { "Screen Accessor called too early" } }
- latestGuiAppender = guiapp
- guiapp.appendFullRow(RowComponent(
- FirmButtonComponent(TextComponent("←")) {
- if (parent != null) {
- save()
- setScreenLater(parent)
- } else {
- AllConfigsGui.showAllGuis()
- }
- }
- ))
- sortedOptions.forEach { it.appendToGui(guiapp) }
- guiapp.reloadables.forEach { it() }
- val component = CenterComponent(PanelComponent(ScrollPanelComponent(400, 300, ColumnComponent(guiapp.panel)), 10, PanelComponent.DefaultBackgroundRenderer.VANILLA))
- screen = object : GuiComponentWrapper(GuiContext(component)) {
- override fun close() {
- if (context.onBeforeClose() == CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE) {
- client!!.setScreen(parent)
- }
- }
- }
- return screen
- }
-
- fun showConfigEditor(parent: Screen? = null) {
- setScreenLater(getConfigEditor(parent))
- }
+import moe.nea.firmament.util.collections.InstanceList
+
+abstract class ManagedConfig(
+ override val name: String,
+ val category: Category,
+ // TODO: allow vararg secondaryCategories: Category,
+) : ManagedConfigElement() {
+ enum class Category {
+ // Böse Kategorie, nicht benutzten lol
+ MISC,
+ CHAT,
+ INVENTORY,
+ MINING,
+ EVENTS,
+ INTEGRATIONS,
+ META,
+ DEV,
+ ;
+
+ val labelText: Text = Text.translatable("firmament.config.category.${name.lowercase()}")
+ val configs: MutableList<ManagedConfig> = mutableListOf()
+ }
+
+ companion object {
+ val allManagedConfigs = InstanceList<ManagedConfig>("ManagedConfig")
+ }
+
+ interface OptionHandler<T : Any> {
+ fun initOption(opt: ManagedOption<T>) {}
+ fun toJson(element: T): JsonElement?
+ fun fromJson(element: JsonElement): T
+ fun emitGuiElements(opt: ManagedOption<T>, guiAppender: GuiAppender)
+ }
+
+ init {
+ allManagedConfigs.getAll().forEach {
+ require(it.name != name) { "Duplicate name '$name' used for config" }
+ }
+ allManagedConfigs.add(this)
+ category.configs.add(this)
+ }
+
+ val file = Firmament.CONFIG_DIR.resolve("$name.json")
+ val data: JsonObject by lazy {
+ try {
+ Firmament.json.decodeFromString(
+ file.readText()
+ )
+ } catch (e: Exception) {
+ Firmament.logger.info("Could not read config $name. Loading empty config.")
+ JsonObject(mutableMapOf())
+ }
+ }
+
+ fun save() {
+ val data = JsonObject(allOptions.mapNotNull { (key, value) ->
+ value.toJson()?.let {
+ key to it
+ }
+ }.toMap())
+ file.parent.createDirectories()
+ file.writeText(Firmament.json.encodeToString(data))
+ }
+
+
+ val allOptions = mutableMapOf<String, ManagedOption<*>>()
+ val sortedOptions = mutableListOf<ManagedOption<*>>()
+
+ private var latestGuiAppender: GuiAppender? = null
+
+ protected fun <T : Any> option(
+ propertyName: String,
+ default: () -> T,
+ handler: OptionHandler<T>
+ ): ManagedOption<T> {
+ if (propertyName in allOptions) error("Cannot register the same name twice")
+ return ManagedOption(this, propertyName, default, handler).also {
+ it.handler.initOption(it)
+ it.load(data)
+ allOptions[propertyName] = it
+ sortedOptions.add(it)
+ }
+ }
+
+ protected fun toggle(propertyName: String, default: () -> Boolean): ManagedOption<Boolean> {
+ return option(propertyName, default, BooleanHandler(this))
+ }
+
+ protected fun duration(
+ propertyName: String,
+ min: Duration,
+ max: Duration,
+ default: () -> Duration,
+ ): ManagedOption<Duration> {
+ return option(propertyName, default, DurationHandler(this, min, max))
+ }
+
+
+ protected fun position(
+ propertyName: String,
+ width: Int,
+ height: Int,
+ default: () -> Point,
+ ): ManagedOption<HudMeta> {
+ val label = Text.translatable("firmament.config.${name}.${propertyName}")
+ return option(propertyName, {
+ val p = default()
+ HudMeta(HudPosition(p.x, p.y, 1F), label, width, height)
+ }, HudMetaHandler(this, label, width, height))
+ }
+
+ protected fun keyBinding(
+ propertyName: String,
+ default: () -> Int,
+ ): ManagedOption<SavedKeyBinding> = keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(default()) }
+
+ protected fun keyBindingWithOutDefaultModifiers(
+ propertyName: String,
+ default: () -> SavedKeyBinding,
+ ): ManagedOption<SavedKeyBinding> {
+ return option(propertyName, default, KeyBindingHandler("firmament.config.${name}.${propertyName}", this))
+ }
+
+ protected fun keyBindingWithDefaultUnbound(
+ propertyName: String,
+ ): ManagedOption<SavedKeyBinding> {
+ return keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN) }
+ }
+
+ protected fun integer(
+ propertyName: String,
+ min: Int,
+ max: Int,
+ default: () -> Int,
+ ): ManagedOption<Int> {
+ return option(propertyName, default, IntegerHandler(this, min, max))
+ }
+
+ protected fun button(propertyName: String, runnable: () -> Unit): ManagedOption<Unit> {
+ return option(propertyName, { }, ClickHandler(this, runnable))
+ }
+
+ protected fun string(propertyName: String, default: () -> String): ManagedOption<String> {
+ return option(propertyName, default, StringHandler(this))
+ }
+
+
+ fun reloadGui() {
+ latestGuiAppender?.reloadables?.forEach { it() }
+ }
+
+ val translationKey get() = "firmament.config.${name}"
+ val labelText = Text.translatable(translationKey)
+
+ fun getConfigEditor(parent: Screen? = null): Screen {
+ var screen: Screen? = null
+ val guiapp = GuiAppender(400) { requireNotNull(screen) { "Screen Accessor called too early" } }
+ latestGuiAppender = guiapp
+ guiapp.appendFullRow(RowComponent(
+ FirmButtonComponent(TextComponent("←")) {
+ if (parent != null) {
+ save()
+ setScreenLater(parent)
+ } else {
+ AllConfigsGui.showAllGuis()
+ }
+ }
+ ))
+ sortedOptions.forEach { it.appendToGui(guiapp) }
+ guiapp.reloadables.forEach { it() }
+ val component = CenterComponent(PanelComponent(ScrollPanelComponent(400, 300, ColumnComponent(guiapp.panel)),
+ 10,
+ PanelComponent.DefaultBackgroundRenderer.VANILLA))
+ screen = object : GuiComponentWrapper(GuiContext(component)) {
+ override fun close() {
+ if (context.onBeforeClose() == CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE) {
+ client!!.setScreen(parent)
+ }
+ }
+ }
+ return screen
+ }
+
+ fun showConfigEditor(parent: Screen? = null) {
+ setScreenLater(getConfigEditor(parent))
+ }
}
diff --git a/src/main/kotlin/gui/config/ManagedOption.kt b/src/main/kotlin/gui/config/ManagedOption.kt
index b7264e8..4a8d773 100644
--- a/src/main/kotlin/gui/config/ManagedOption.kt
+++ b/src/main/kotlin/gui/config/ManagedOption.kt
@@ -11,7 +11,7 @@ import net.minecraft.text.Text
import moe.nea.firmament.Firmament
class ManagedOption<T : Any>(
- val element: ManagedConfigElement,
+ val element: ManagedConfig,
val propertyName: String,
val default: () -> T,
val handler: ManagedConfig.OptionHandler<T>
diff --git a/src/main/kotlin/repo/RepoManager.kt b/src/main/kotlin/repo/RepoManager.kt
index 4c25daa..5cf84bd 100644
--- a/src/main/kotlin/repo/RepoManager.kt
+++ b/src/main/kotlin/repo/RepoManager.kt
@@ -19,7 +19,7 @@ import moe.nea.firmament.util.MinecraftDispatcher
import moe.nea.firmament.util.SkyblockId
object RepoManager {
- object Config : ManagedConfig("repo") {
+ object Config : ManagedConfig("repo", Category.META) {
var username by string("username") { "NotEnoughUpdates" }
var reponame by string("reponame") { "NotEnoughUpdates-REPO" }
var branch by string("branch") { "master" }
@@ -31,8 +31,6 @@ object RepoManager {
save()
}
- val enableYacl by toggle("enable-yacl") { false }
-
val disableItemGroups by toggle("disable-item-groups") { true }
val reload by button("reload") {
save()
diff --git a/src/main/resources/assets/firmament/gui/config/category.xml b/src/main/resources/assets/firmament/gui/config/category.xml
new file mode 100644
index 0000000..e34b018
--- /dev/null
+++ b/src/main/resources/assets/firmament/gui/config/category.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Root xmlns="http://notenoughupdates.org/moulconfig"
+ xmlns:firm="http://firmament.nea.moe/moulconfig">
+ <Center>
+ <Panel background="VANILLA" insets="10">
+ <Column>
+ <Row>
+ <Align vertical="CENTER">
+ <firm:Button onClick="@close">
+ <Text text="Back"/>
+ </firm:Button>
+ </Align>
+ <Align vertical="CENTER">
+ <Row>
+ <Text text=" "/>
+ <Text text="@name"/>
+ </Row>
+ </Align>
+ </Row>
+ <Spacer height="5"/>
+ <ScrollPanel width="400" height="300">
+ <Array data="@configs">
+ <firm:Fixed width="380" height="30">
+ <Panel background="VANILLA">
+ <Center>
+ <Row>
+ <Center>
+ <Text text="@name"/>
+ </Center>
+ <firm:Button onClick="@openEditor">
+ <Text text="Edit"/>
+ </firm:Button>
+ </Row>
+ </Center>
+ </Panel>
+ </firm:Fixed>
+ </Array>
+ </ScrollPanel>
+ </Column>
+ </Panel>
+ </Center>
+</Root>
diff --git a/src/main/resources/assets/firmament/gui/config/main.xml b/src/main/resources/assets/firmament/gui/config/main.xml
index 84b0115..8953ada 100644
--- a/src/main/resources/assets/firmament/gui/config/main.xml
+++ b/src/main/resources/assets/firmament/gui/config/main.xml
@@ -6,7 +6,7 @@
<Column>
<Text text="Firmament Config"/>
<ScrollPanel width="400" height="300">
- <Array data="@configs">
+ <Array data="@categories">
<firm:Fixed width="380" height="30">
<Panel background="VANILLA">
<Center>
@@ -14,8 +14,8 @@
<Center>
<Text text="@name"/>
</Center>
- <firm:Button onClick="@openEditor">
- <Text text="Edit"/>
+ <firm:Button onClick="@open">
+ <Text text="Open"/>
</firm:Button>
</Row>
</Center>
diff --git a/src/main/resources/assets/firmament/lang/en_us.json b/src/main/resources/assets/firmament/lang/en_us.json
index f7a128d..8e8478b 100644
--- a/src/main/resources/assets/firmament/lang/en_us.json
+++ b/src/main/resources/assets/firmament/lang/en_us.json
@@ -73,15 +73,24 @@
"firmament.config.repo.username.hint": "NotEnoughUpdates",
"firmament.config.repo.reponame": "Repo Name",
"firmament.config.repo.reponame.hint": "NotEnoughUpdates-REPO",
- "firmament.config.repo.enable-yacl": "Use YACL Config",
+ "firmament.config.configconfig.enable-yacl": "Use YACL Config",
"firmament.config.repo.branch": "Repo Branch",
- "firmament.config.repo.branch.hint": "dangerous",
+ "firmament.config.configconfig": "Firmaments Config",
+ "firmament.config.repo.branch.hint": "dangerous",
"firmament.config.repo.reset": "Reset",
"firmament.config.repo.disable-item-groups": "Disable Item Groups",
"firmament.config.repo.reload": "Reload Item List",
"firmament.config.repo.redownload": "Redownload Item List",
"firmament.config.pets": "Pets",
"firmament.config.pets.highlight-pet": "Highlight active pet",
+ "firmament.config.category.misc": "Miscellaneous",
+ "firmament.config.category.mining": "Mining",
+ "firmament.config.category.events": "Events",
+ "firmament.config.category.chat": "Chat",
+ "firmament.config.category.inventory": "Inventory",
+ "firmament.config.category.integrations": "Integrations & Textures",
+ "firmament.config.category.meta": "Meta & Firmament",
+ "firmament.config.category.dev": "Developer & Debug",
"firmament.ursa.debugrequest.start": "Ursa request launched",
"firmament.ursa.debugrequest.result": "Ursa request succeeded: %s",
"firmament.sbinfo.nolocraw": "No locraw data available",