aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-11-12 21:38:31 +0100
committerLinnea Gräf <nea@nea.moe>2024-11-12 21:38:31 +0100
commitfc88e54a2e88c87bcfd5e7dbd6866764faa3e503 (patch)
treec5ec7980b67c47ce0d89175cb6ac9a180a94c3f3 /src
parentb774daef5bd961f955d365ce07bd5aa4acb161f4 (diff)
downloadFirmament-fc88e54a2e88c87bcfd5e7dbd6866764faa3e503.tar.gz
Firmament-fc88e54a2e88c87bcfd5e7dbd6866764faa3e503.tar.bz2
Firmament-fc88e54a2e88c87bcfd5e7dbd6866764faa3e503.zip
feat: Add descriptions for config options
Diffstat (limited to 'src')
-rw-r--r--src/compat/moulconfig/java/MCConfigEditorIntegration.kt51
-rw-r--r--src/compat/moulconfig/java/ProcessedCategoryFirm.kt2
-rw-r--r--src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt2
-rw-r--r--src/compat/yacl/java/YaclIntegration.kt2
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java19
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java38
-rw-r--r--src/main/kotlin/Firmament.kt1
-rw-r--r--src/main/kotlin/features/debug/DeveloperFeatures.kt92
-rw-r--r--src/main/kotlin/gui/config/ManagedConfig.kt1
-rw-r--r--src/main/kotlin/gui/config/ManagedOption.kt99
-rw-r--r--src/main/kotlin/util/MC.kt12
-rw-r--r--src/main/resources/assets/firmament/textures/socials/discord.pngbin0 -> 10386 bytes
-rw-r--r--src/main/resources/assets/firmament/textures/socials/git.pngbin0 -> 79519 bytes
-rw-r--r--src/main/resources/assets/firmament/textures/socials/modrinth.pngbin0 -> 4521 bytes
-rw-r--r--src/main/resources/fabric.mod.json3
15 files changed, 228 insertions, 94 deletions
diff --git a/src/compat/moulconfig/java/MCConfigEditorIntegration.kt b/src/compat/moulconfig/java/MCConfigEditorIntegration.kt
index 7686beb..f1e7a98 100644
--- a/src/compat/moulconfig/java/MCConfigEditorIntegration.kt
+++ b/src/compat/moulconfig/java/MCConfigEditorIntegration.kt
@@ -2,7 +2,10 @@ package moe.nea.firmament.compat.moulconfig
import com.google.auto.service.AutoService
import io.github.notenoughupdates.moulconfig.Config
+import io.github.notenoughupdates.moulconfig.DescriptionRendereringBehaviour
+import io.github.notenoughupdates.moulconfig.Social
import io.github.notenoughupdates.moulconfig.common.IMinecraft
+import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
import io.github.notenoughupdates.moulconfig.gui.GuiComponent
import io.github.notenoughupdates.moulconfig.gui.GuiElementWrapper
import io.github.notenoughupdates.moulconfig.gui.GuiOptionEditor
@@ -22,10 +25,14 @@ import io.github.notenoughupdates.moulconfig.observer.GetSetter
import io.github.notenoughupdates.moulconfig.processor.ProcessedCategory
import io.github.notenoughupdates.moulconfig.processor.ProcessedOption
import java.lang.reflect.Type
+import java.net.URI
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
import kotlin.time.DurationUnit
import net.minecraft.client.gui.screen.Screen
+import net.minecraft.util.Identifier
+import net.minecraft.util.Util
+import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.config.BooleanHandler
import moe.nea.firmament.gui.config.ClickHandler
import moe.nea.firmament.gui.config.DurationHandler
@@ -37,6 +44,7 @@ import moe.nea.firmament.gui.config.KeyBindingHandler
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.gui.config.ManagedOption
import moe.nea.firmament.gui.config.StringHandler
+import moe.nea.firmament.gui.toMoulConfig
import moe.nea.firmament.keybindings.SavedKeyBinding
import moe.nea.firmament.util.ErrorUtil
import moe.nea.firmament.util.FirmFormatters
@@ -287,6 +295,47 @@ class MCConfigEditorIntegration : FirmamentConfigScreenProvider {
override fun shouldAutoFocusSearchbar(): Boolean {
return true
}
+
+ override fun getTitle(): String {
+ return "Firmament"
+ }
+
+ @Deprecated("Deprecated in java")
+ override fun executeRunnable(runnableId: Int) {
+ if (runnableId >= 0)
+ ErrorUtil.softError("Executed runnable $runnableId")
+ }
+
+ override fun getDescriptionBehaviour(option: ProcessedOption?): DescriptionRendereringBehaviour {
+ return DescriptionRendereringBehaviour.EXPAND_PANEL
+ }
+
+ fun mkSocial(name: String, identifier: Identifier, link: String) = object : Social() {
+ override fun onClick() {
+ Util.getOperatingSystem().open(URI(link))
+ }
+
+ override fun getTooltip(): List<String> {
+ return listOf(name)
+ }
+
+ override fun getIcon(): MyResourceLocation {
+ return identifier.toMoulConfig()
+ }
+ }
+
+ private val socials = listOf<Social>(
+ mkSocial("Discord", Firmament.identifier("textures/socials/discord.png"),
+ Firmament.modContainer.metadata.contact.get("discord").get()),
+ mkSocial("Source Code", Firmament.identifier("textures/socials/git.png"),
+ Firmament.modContainer.metadata.contact.get("sources").get()),
+ mkSocial("Modrinth", Firmament.identifier("textures/socials/modrinth.png"),
+ Firmament.modContainer.metadata.contact.get("modrinth").get()),
+ )
+
+ override fun getSocials(): List<Social> {
+ return socials
+ }
}
val categories = ManagedConfig.Category.entries.map {
val options = mutableListOf<ProcessedOptionFirm>()
@@ -295,7 +344,7 @@ class MCConfigEditorIntegration : FirmamentConfigScreenProvider {
val categoryAccordionId = nextAccordionId++
options.add(object : ProcessedOptionFirm(-1, configObject) {
override fun getDebugDeclarationLocation(): String {
- return "FirmamentConfig:$config.name"
+ return "FirmamentConfig:${config.name}"
}
override fun getName(): String {
diff --git a/src/compat/moulconfig/java/ProcessedCategoryFirm.kt b/src/compat/moulconfig/java/ProcessedCategoryFirm.kt
index 19e1112..5313441 100644
--- a/src/compat/moulconfig/java/ProcessedCategoryFirm.kt
+++ b/src/compat/moulconfig/java/ProcessedCategoryFirm.kt
@@ -26,7 +26,7 @@ class ProcessedCategoryFirm(
}
override fun getDescription(): String {
- return "Missing description" // TODO: add description
+ return category.description.string
}
override fun getIdentifier(): String {
diff --git a/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt b/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt
index c42ad3f..2bc5cd4 100644
--- a/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt
+++ b/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt
@@ -18,7 +18,7 @@ abstract class ProcessedEditableOptionFirm<T : Any>(
}
override fun getDescription(): String {
- return "Missing description" // TODO: add description
+ return managedOption.labelDescription.string
}
override fun explicitNotifyChange() {
diff --git a/src/compat/yacl/java/YaclIntegration.kt b/src/compat/yacl/java/YaclIntegration.kt
index 239d3a0..9aec501 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.OptionDescription
import dev.isxander.yacl3.api.OptionGroup
import dev.isxander.yacl3.api.YetAnotherConfigLib
import dev.isxander.yacl3.api.controller.ControllerBuilder
@@ -69,6 +70,7 @@ class YaclIntegration : FirmamentConfigScreenProvider {
fun <T> createDefaultBinding(function: (Option<T>) -> ControllerBuilder<T>): Option.Builder<T> {
return Option.createBuilder<T>()
.name(managedOption.labelText)
+ .description(OptionDescription.of(managedOption.labelDescription))
.binding(binding as Binding<T>)
.controller { function(it) }
}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java b/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java
new file mode 100644
index 0000000..ef8c9eb
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java
@@ -0,0 +1,19 @@
+package moe.nea.firmament.mixins.devenv;
+
+import net.minecraft.text.TranslatableTextContent;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(TranslatableTextContent.class)
+public abstract class EarlyInstantiateTranslations {
+ @Shadow
+ protected abstract void updateTranslations();
+
+ @Inject(method = "<init>", at = @At("TAIL"))
+ private void onInit(String key, String fallback, Object[] args, CallbackInfo ci) {
+ updateTranslations();
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java b/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java
new file mode 100644
index 0000000..33840c1
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java
@@ -0,0 +1,38 @@
+package moe.nea.firmament.mixins.devenv;
+
+import moe.nea.firmament.features.debug.DeveloperFeatures;
+import moe.nea.firmament.util.MC;
+import net.minecraft.client.resource.language.TranslationStorage;
+import net.minecraft.text.Text;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import java.util.Set;
+import java.util.TreeSet;
+
+@Mixin(TranslationStorage.class)
+public abstract class WarnOnMissingTranslations {
+ @Shadow
+ public abstract boolean hasTranslation(String key);
+
+ @Unique
+ private final Set<String> missingTranslations = new TreeSet<>();
+
+ @Inject(method = "get", at = @At("HEAD"))
+ private void onGetTranslationKey(String key, String fallback, CallbackInfoReturnable<String> cir) {
+ warnForMissingTranslation(key);
+ }
+
+ @Unique
+ private void warnForMissingTranslation(String key) {
+ if (!key.contains("firmament")) return;
+ if (hasTranslation(key)) return;
+ if (!missingTranslations.add(key)) return;
+ MC.INSTANCE.sendChat(Text.literal("Missing firmament translation: " + key));
+ DeveloperFeatures.hookMissingTranslations(missingTranslations);
+ }
+}
diff --git a/src/main/kotlin/Firmament.kt b/src/main/kotlin/Firmament.kt
index e0541f1..9f15bff 100644
--- a/src/main/kotlin/Firmament.kt
+++ b/src/main/kotlin/Firmament.kt
@@ -49,6 +49,7 @@ import moe.nea.firmament.util.SBData
import moe.nea.firmament.util.data.IDataHolder
object Firmament {
+ val modContainer by lazy { FabricLoader.getInstance().getModContainer(MOD_ID).get() }
const val MOD_ID = "firmament"
val DEBUG = System.getProperty("firmament.debug") == "true"
diff --git a/src/main/kotlin/features/debug/DeveloperFeatures.kt b/src/main/kotlin/features/debug/DeveloperFeatures.kt
index d4b118b..8f0c25c 100644
--- a/src/main/kotlin/features/debug/DeveloperFeatures.kt
+++ b/src/main/kotlin/features/debug/DeveloperFeatures.kt
@@ -1,12 +1,16 @@
package moe.nea.firmament.features.debug
+import java.io.File
import java.nio.file.Path
import java.util.concurrent.CompletableFuture
+import kotlinx.serialization.json.encodeToStream
import kotlin.io.path.absolute
import kotlin.io.path.exists
import net.minecraft.client.MinecraftClient
import net.minecraft.text.Text
import moe.nea.firmament.Firmament
+import moe.nea.firmament.annotations.Subscribe
+import moe.nea.firmament.events.TickEvent
import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.util.MC
@@ -14,41 +18,57 @@ import moe.nea.firmament.util.TimeMark
import moe.nea.firmament.util.iterate
object DeveloperFeatures : FirmamentFeature {
- override val identifier: String
- get() = "developer"
- override val config: TConfig
- get() = TConfig
- override val defaultEnabled: Boolean
- get() = Firmament.DEBUG
-
- val gradleDir =
- Path.of(".").absolute()
- .iterate { it.parent }
- .find { it.resolve("settings.gradle.kts").exists() }
-
- object TConfig : ManagedConfig("developer", Category.DEV) {
- val autoRebuildResources by toggle("auto-rebuild") { false }
- }
-
- @JvmStatic
- fun hookOnBeforeResourceReload(client: MinecraftClient): CompletableFuture<Void> {
- val reloadFuture = if (TConfig.autoRebuildResources && isEnabled && gradleDir != null) {
- val builder = ProcessBuilder("./gradlew", ":processResources")
- builder.directory(gradleDir.toFile())
- builder.inheritIO()
- val process = builder.start()
- MC.sendChat(Text.translatable("firmament.dev.resourcerebuild.start"))
- val startTime = TimeMark.now()
- process.toHandle().onExit().thenApply {
- MC.sendChat(Text.stringifiedTranslatable(
- "firmament.dev.resourcerebuild.done",
- startTime.passedTime()))
- Unit
- }
- } else {
- CompletableFuture.completedFuture(Unit)
- }
- return reloadFuture.thenCompose { client.reloadResources() }
- }
+ override val identifier: String
+ get() = "developer"
+ override val config: TConfig
+ get() = TConfig
+ override val defaultEnabled: Boolean
+ get() = Firmament.DEBUG
+
+ val gradleDir =
+ Path.of(".").absolute()
+ .iterate { it.parent }
+ .find { it.resolve("settings.gradle.kts").exists() }
+
+ object TConfig : ManagedConfig("developer", Category.DEV) {
+ val autoRebuildResources by toggle("auto-rebuild") { false }
+ }
+
+ var missingTranslations: Set<String>? = null
+
+ @JvmStatic
+ fun hookMissingTranslations(missingTranslations: Set<String>) {
+ this.missingTranslations = missingTranslations
+ }
+
+ @Subscribe
+ fun dumpMissingTranslations(tickEvent: TickEvent) {
+ val toDump = missingTranslations ?: return
+ missingTranslations = null
+ File("missing_translations.json").outputStream().use {
+ Firmament.json.encodeToStream(toDump.associateWith { "Mis" + "sing translation" }, it)
+ }
+ }
+
+ @JvmStatic
+ fun hookOnBeforeResourceReload(client: MinecraftClient): CompletableFuture<Void> {
+ val reloadFuture = if (TConfig.autoRebuildResources && isEnabled && gradleDir != null) {
+ val builder = ProcessBuilder("./gradlew", ":processResources")
+ builder.directory(gradleDir.toFile())
+ builder.inheritIO()
+ val process = builder.start()
+ MC.sendChat(Text.translatable("firmament.dev.resourcerebuild.start"))
+ val startTime = TimeMark.now()
+ process.toHandle().onExit().thenApply {
+ MC.sendChat(Text.stringifiedTranslatable(
+ "firmament.dev.resourcerebuild.done",
+ startTime.passedTime()))
+ Unit
+ }
+ } else {
+ CompletableFuture.completedFuture(Unit)
+ }
+ return reloadFuture.thenCompose { client.reloadResources() }
+ }
}
diff --git a/src/main/kotlin/gui/config/ManagedConfig.kt b/src/main/kotlin/gui/config/ManagedConfig.kt
index c8b6ce8..8222a46 100644
--- a/src/main/kotlin/gui/config/ManagedConfig.kt
+++ b/src/main/kotlin/gui/config/ManagedConfig.kt
@@ -44,6 +44,7 @@ abstract class ManagedConfig(
;
val labelText: Text = Text.translatable("firmament.config.category.${name.lowercase()}")
+ val description: Text = Text.translatable("firmament.config.category.${name.lowercase()}.description")
val configs: MutableList<ManagedConfig> = mutableListOf()
}
diff --git a/src/main/kotlin/gui/config/ManagedOption.kt b/src/main/kotlin/gui/config/ManagedOption.kt
index 4a8d773..d1aba83 100644
--- a/src/main/kotlin/gui/config/ManagedOption.kt
+++ b/src/main/kotlin/gui/config/ManagedOption.kt
@@ -1,5 +1,3 @@
-
-
package moe.nea.firmament.gui.config
import io.github.notenoughupdates.moulconfig.observer.GetSetter
@@ -9,54 +7,57 @@ import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import net.minecraft.text.Text
import moe.nea.firmament.Firmament
+import moe.nea.firmament.util.ErrorUtil
class ManagedOption<T : Any>(
- val element: ManagedConfig,
- val propertyName: String,
- val default: () -> T,
- val handler: ManagedConfig.OptionHandler<T>
+ val element: ManagedConfig,
+ val propertyName: String,
+ val default: () -> T,
+ val handler: ManagedConfig.OptionHandler<T>
) : ReadWriteProperty<Any?, T>, GetSetter<T> {
- override fun set(newValue: T) {
- this.value = newValue
- }
-
- override fun get(): T {
- return this.value
- }
-
- val rawLabelText = "firmament.config.${element.name}.${propertyName}"
- val labelText = Text.translatable(rawLabelText)
-
- lateinit var value: T
-
- override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
- this.value = value
- }
-
- override fun getValue(thisRef: Any?, property: KProperty<*>): T {
- return value
- }
-
- fun load(root: JsonElement) {
- if (root is JsonObject && root.containsKey(propertyName)) {
- try {
- value = handler.fromJson(root[propertyName]!!)
- return
- } catch (e: Exception) {
- Firmament.logger.error(
- "Exception during loading of config file ${element.name}. This will reset this config.",
- e
- )
- }
- }
- value = default()
- }
-
- fun toJson(): JsonElement? {
- return handler.toJson(value)
- }
-
- fun appendToGui(guiapp: GuiAppender) {
- handler.emitGuiElements(this, guiapp)
- }
+ override fun set(newValue: T) {
+ this.value = newValue
+ }
+
+ override fun get(): T {
+ return this.value
+ }
+
+ val rawLabelText = "firmament.config.${element.name}.${propertyName}"
+ val labelText: Text = Text.translatable(rawLabelText)
+ val descriptionTranslationKey = "firmament.config.${element.name}.${propertyName}.description"
+ val labelDescription: Text = Text.translatable(descriptionTranslationKey)
+
+ lateinit var value: T
+
+ override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
+ this.value = value
+ }
+
+ override fun getValue(thisRef: Any?, property: KProperty<*>): T {
+ return value
+ }
+
+ fun load(root: JsonElement) {
+ if (root is JsonObject && root.containsKey(propertyName)) {
+ try {
+ value = handler.fromJson(root[propertyName]!!)
+ return
+ } catch (e: Exception) {
+ ErrorUtil.softError(
+ "Exception during loading of config file ${element.name}. This will reset this config.",
+ e
+ )
+ }
+ }
+ value = default()
+ }
+
+ fun toJson(): JsonElement? {
+ return handler.toJson(value)
+ }
+
+ fun appendToGui(guiapp: GuiAppender) {
+ handler.emitGuiElements(this, guiapp)
+ }
}
diff --git a/src/main/kotlin/util/MC.kt b/src/main/kotlin/util/MC.kt
index 1b7739f..cbcd8ae 100644
--- a/src/main/kotlin/util/MC.kt
+++ b/src/main/kotlin/util/MC.kt
@@ -3,6 +3,7 @@ package moe.nea.firmament.util
import io.github.moulberry.repo.data.Coordinate
import java.util.concurrent.ConcurrentLinkedQueue
import net.minecraft.client.MinecraftClient
+import net.minecraft.client.gui.hud.InGameHud
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.screen.ingame.HandledScreen
import net.minecraft.client.network.ClientPlayerEntity
@@ -28,9 +29,10 @@ object MC {
init {
TickEvent.subscribe("MC:push") {
- while (true) {
- inGameHud.chatHud.addMessage(messageQueue.poll() ?: break)
- }
+ if (inGameHud.chatHud != null && world != null)
+ while (true) {
+ inGameHud.chatHud.addMessage(messageQueue.poll() ?: break)
+ }
while (true) {
(nextTickTodos.poll() ?: break).invoke()
}
@@ -41,7 +43,7 @@ object MC {
}
fun sendChat(text: Text) {
- if (instance.isOnThread)
+ if (instance.isOnThread && inGameHud.chatHud != null && world != null)
inGameHud.chatHud.addMessage(text)
else
messageQueue.add(text)
@@ -86,7 +88,7 @@ object MC {
inline val interactionManager get() = instance.interactionManager
inline val textureManager get() = instance.textureManager
inline val options get() = instance.options
- inline val inGameHud get() = instance.inGameHud
+ inline val inGameHud: InGameHud get() = instance.inGameHud
inline val font get() = instance.textRenderer
inline val soundManager get() = instance.soundManager
inline val player: ClientPlayerEntity? get() = instance.player
diff --git a/src/main/resources/assets/firmament/textures/socials/discord.png b/src/main/resources/assets/firmament/textures/socials/discord.png
new file mode 100644
index 0000000..e9dc50d
--- /dev/null
+++ b/src/main/resources/assets/firmament/textures/socials/discord.png
Binary files differ
diff --git a/src/main/resources/assets/firmament/textures/socials/git.png b/src/main/resources/assets/firmament/textures/socials/git.png
new file mode 100644
index 0000000..d7ab359
--- /dev/null
+++ b/src/main/resources/assets/firmament/textures/socials/git.png
Binary files differ
diff --git a/src/main/resources/assets/firmament/textures/socials/modrinth.png b/src/main/resources/assets/firmament/textures/socials/modrinth.png
new file mode 100644
index 0000000..bfc9403
--- /dev/null
+++ b/src/main/resources/assets/firmament/textures/socials/modrinth.png
Binary files differ
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index 9b00adf..3b988b1 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -14,7 +14,8 @@
],
"contact": {
"discord": "https://discord.gg/64pFP94AWA",
- "sources": "https://git.nea.moe/nea/firmament/"
+ "sources": "https://github.com/nea89o/Firmament",
+ "modrinth": "https://modrinth.com/mod/firmament"
},
"license": "GPL 3.0 or Later",
"accessWidener": "firmament.accesswidener",