From 643a5e9a8cd199e0d262f5b89d4f60eaca97662f Mon Sep 17 00:00:00 2001 From: alexcrea Date: Fri, 14 Aug 2026 00:40:52 +0200 Subject: [PATCH 01/14] fix eco enchant again --- build.gradle.kts | 2 +- .../plugins/EcoEnchantDependency.kt | 23 +++++++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2cc60a02..af02a354 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,7 +22,7 @@ plugins { } group = "xyz.alexcrea" -version = "2.0.0" +version = "2.0.1" val isDevBuild = System.getenv("SMALL_COMMIT_HASH") != null val isPreRelease = System.getenv("IS_GITHUB_PRERELEASE") == "true" diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt index 78bc9d13..64078f0e 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/EcoEnchantDependency.kt @@ -5,6 +5,7 @@ import com.willfp.ecoenchants.enchant.EcoEnchant import com.willfp.ecoenchants.enchant.EcoEnchants import com.willfp.ecoenchants.enchant.UtilKt import io.delilaheve.CustomAnvil +import org.bukkit.Bukkit import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.plugin.Plugin import xyz.alexcrea.cuanvil.api.EnchantmentApi @@ -22,11 +23,11 @@ class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) { try { Class.forName("com.willfp.ecoenchants.enchant.EcoEnchants") isLegacy = false - } catch (_: ClassNotFoundException) { + } catch(_: ClassNotFoundException) { } this.isLegacy = isLegacy; - if (isLegacy) { + if(isLegacy) { this.legacyDependency = LegacyEcoEnchantDependency() } else { this.legacyDependency = null @@ -34,25 +35,27 @@ class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) { } - public fun getEcoLevelLimit(): Int { + fun getEcoLevelLimit(): Int { return UtilKt.infiniteIfNegative((ecoEnchantPlugin as EcoPlugin).configYml.getInt("anvil.enchant-limit")) } fun disableAnvilListener() { PrepareAnvilEvent.getHandlerList().unregister(this.ecoEnchantPlugin) + // I don't like that but modern ee use eco prepare anvil event + PrepareAnvilEvent.getHandlerList().unregister(Bukkit.getPluginManager().getPlugin("eco")!!) } private var ecoEnchantOldEnchantments: MutableSet? = null fun registerEnchantments() { CustomAnvil.instance.logger.info("Preparing Eco Enchant compatibility...") - if (isLegacy) { + if(isLegacy) { legacyDependency!!.registerEnchantments(); return } val enchantments = EcoEnchants.INSTANCE.values() - for (ecoEnchant in enchantments) { + for(ecoEnchant in enchantments) { EnchantmentApi.unregisterEnchantment(ecoEnchant.enchantment) // As eco enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant. EnchantmentApi.registerEnchantment(CAEcoEnchant(ecoEnchant)) } @@ -63,24 +66,24 @@ class EcoEnchantDependency(private val ecoEnchantPlugin: Plugin) { } fun handleConfigReload() { - if (isLegacy) { + if(isLegacy) { legacyDependency!!.handleConfigReload() return } // Should not happen in known case. - if (this.ecoEnchantOldEnchantments == null) return + if(this.ecoEnchantOldEnchantments == null) return val newEnchantments = EcoEnchants.INSTANCE.values() // Add new enchantments - for (ecoEnchant in newEnchantments) - if (!this.ecoEnchantOldEnchantments!!.contains(ecoEnchant)) + for(ecoEnchant in newEnchantments) + if(!this.ecoEnchantOldEnchantments!!.contains(ecoEnchant)) EnchantmentApi.registerEnchantment(CAEcoEnchant(ecoEnchant)) // Remove old enchantments that not now currently used this.ecoEnchantOldEnchantments!!.removeAll(newEnchantments) - for (oldEnchantment in this.ecoEnchantOldEnchantments!!) { + for(oldEnchantment in this.ecoEnchantOldEnchantments!!) { EnchantmentApi.unregisterEnchantment(oldEnchantment.enchantment) } From 6c4991f85214e46a6a96a46482d428c5e5a5ebec Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 16 Aug 2026 07:50:34 +0200 Subject: [PATCH 02/14] fix gradlew and up to 9.7.0, upgrade to java 21 [skip ci] version bump to 2.0.2 --- build.gradle.kts | 23 +++++++++++------------ gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index af02a354..4e9eb467 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,7 +22,7 @@ plugins { } group = "xyz.alexcrea" -version = "2.0.1" +version = "2.0.2" val isDevBuild = System.getenv("SMALL_COMMIT_HASH") != null val isPreRelease = System.getenv("IS_GITHUB_PRERELEASE") == "true" @@ -158,8 +158,8 @@ allprojects { // Set target version tasks.withType().configureEach { sourceCompatibility = - "16" // We aim for java 16 for minecraft 1.16.5. even if it not really supported by custom anvil. - targetCompatibility = "16" + "21" // We aim for java 21 for minecraft 1.21.0 + targetCompatibility = "21" options.encoding = "UTF-8" } @@ -167,7 +167,7 @@ allprojects { kotlin { compilerOptions { apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) - jvmTarget.set(JvmTarget.JVM_16) + jvmTarget.set(JvmTarget.JVM_21) } } @@ -212,7 +212,7 @@ tasks { exclude("net/kyori/**") } - val offlineJar by registering(ShadowJar::class) { + val offlineJar = register("OfflineJar") { configureBaseShadow("offline", emptyArray()) from(sourceSets.main.get().output) @@ -226,12 +226,12 @@ tasks { } -val sourcesJar by tasks.registering(Jar::class) { +val sourcesJar = tasks.register("sourcesJar") { archiveClassifier.set("sources") from(kotlin.sourceSets.main.get().kotlin) } -val javadocJar by tasks.registering(Jar::class, fun Jar.() { +val javadocJar = tasks.register("javadocJar", fun Jar.() { group = JavaBasePlugin.DOCUMENTATION_GROUP description = "Assembles Javadoc JAR" archiveClassifier.set("javadoc") @@ -355,10 +355,9 @@ publishing { } // hangar publish - fun executeGitCommand(vararg command: String): String { val byteOut = ByteArrayOutputStream() - exec { + providers.exec { commandLine = listOf("git", *command) standardOutput = byteOut } @@ -395,9 +394,9 @@ hangarPublish { if(!isOnline) versionName+= "-offline" version.set(versionName) - var releaseChannel = if (isDevBuild || isPreRelease) devChannel else releaseChannel - if(releaseChannel == null) return - channel.set(releaseChannel) + var finalReleaseChannel = if (isDevBuild || isPreRelease) devChannel else releaseChannel + if(finalReleaseChannel == null) return + channel.set(finalReleaseChannel) changelog.set(changelog(isOnline)) id.set("CustomAnvil") diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0b55a3bd..8bf5ce26 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From ca89b0d095dfc2250ab7044e3b1a04c33e32eeea Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 16 Aug 2026 08:44:58 +0200 Subject: [PATCH 03/14] go back to old datapack manager --- .../dependency/datapack/DataPackTester.kt | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt index 221dd2fa..e914ce0b 100644 --- a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt +++ b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt @@ -1,20 +1,40 @@ +@file:Suppress("DEPRECATION", "removal") + package xyz.alexcrea.cuanvil.dependency.datapack import io.papermc.paper.datapack.Datapack import org.bukkit.Bukkit +import org.bukkit.packs.DataPack import java.util.* object DataPackTester { + val legacyNames: List + get() = Bukkit.getDataPackManager().dataPacks + .stream().filter { obj -> obj.isEnabled } + .map { pack -> pack.key.key } + .toList() val enabledPacks: List get() { - return try { - Bukkit.getDatapackManager().enabledPacks + try { + // will throw error if do not exist + Bukkit::class.java.getDeclaredMethod("getDatapackManager") + + return Bukkit.getDatapackManager().enabledPacks .stream().map { obj: Datapack -> obj.name } .toList() - } catch (_: Exception){ + } catch(_: NoSuchMethodException) { + try { + DataPack::class.java.getDeclaredMethod("getKey") + } catch(e: NoSuchMethodException) { + System.err.println("Could not find compatible datapack manager") + System.err.println("If you are using a datapack that should be compatible with CustomAnvil. It will not get detected...") + return emptyList() + } + return legacyNames + } catch(_: Exception) { // Assume cause UnimplementedOperationException on mock server - Collections.emptyList() + return Collections.emptyList() } } } From 6ea84302475d70353e22aea90eef469a2dc65132 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 16 Aug 2026 10:21:09 +0200 Subject: [PATCH 04/14] update a bunch of stuff in gradle --- build.gradle.kts | 16 ++++++++-------- impl/ExcellentEnchant5_4/build.gradle.kts | 2 +- impl/LegacyEcoEnchant/build.gradle.kts | 2 +- nms/nms-common/build.gradle.kts | 2 +- nms/nms-paper/build.gradle.kts | 2 +- nms/v1_21R1/build.gradle.kts | 2 +- nms/v1_21R2/build.gradle.kts | 2 +- nms/v1_21R3/build.gradle.kts | 2 +- nms/v1_21R4/build.gradle.kts | 2 +- nms/v1_21R5/build.gradle.kts | 2 +- nms/v1_21R6/build.gradle.kts | 2 +- nms/v1_21R7/build.gradle.kts | 2 +- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4e9eb467..3cec962f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,17 +8,17 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget import java.io.ByteArrayOutputStream plugins { - kotlin("jvm") version "2.3.0" + kotlin("jvm") version "2.4.0" java - id("org.jetbrains.dokka").version("1.9.20") - id("com.gradleup.shadow").version("9.3.0") + id("org.jetbrains.dokka").version("2.2.0") + id("com.gradleup.shadow").version("9.6.1") // Maven publish `maven-publish` signing - id("cn.lalaki.central").version("1.2.8") + id("cn.lalaki.central").version("2.0.8") // Paper - id("io.papermc.paperweight.userdev") version "2.0.0-beta.17" apply false - id("io.papermc.hangar-publish-plugin") version "0.1.2" + id("io.papermc.paperweight.userdev") version "2.0.0-beta.21" apply false + id("io.papermc.hangar-publish-plugin") version "0.1.4" } group = "xyz.alexcrea" @@ -166,7 +166,7 @@ allprojects { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } @@ -200,7 +200,7 @@ tasks { shadowJar { configureBaseShadow("", arrayOf( - "org.jetbrains.kotlin:kotlin-stdlib:2.3.0", + "org.jetbrains.kotlin:kotlin-stdlib:2.4.0", "net.kyori:adventure-text-minimessage:4.25.0", "net.kyori:adventure-text-serializer-plain:4.25.0", "net.kyori:adventure-text-serializer-legacy:4.25.0", diff --git a/impl/ExcellentEnchant5_4/build.gradle.kts b/impl/ExcellentEnchant5_4/build.gradle.kts index 9fe598b1..e624d159 100644 --- a/impl/ExcellentEnchant5_4/build.gradle.kts +++ b/impl/ExcellentEnchant5_4/build.gradle.kts @@ -2,7 +2,7 @@ group = rootProject.group version = rootProject.version plugins { - kotlin("jvm") version "2.3.0" + kotlin("jvm") version "2.4.0" } repositories { diff --git a/impl/LegacyEcoEnchant/build.gradle.kts b/impl/LegacyEcoEnchant/build.gradle.kts index 3c3f1aeb..71c62a78 100644 --- a/impl/LegacyEcoEnchant/build.gradle.kts +++ b/impl/LegacyEcoEnchant/build.gradle.kts @@ -2,7 +2,7 @@ group = rootProject.group version = rootProject.version plugins { - kotlin("jvm") version "2.3.0" + kotlin("jvm") version "2.4.0" } // Imitate needed class and method to support legacy version of EcoEnchant diff --git a/nms/nms-common/build.gradle.kts b/nms/nms-common/build.gradle.kts index 46f684d7..69777bae 100644 --- a/nms/nms-common/build.gradle.kts +++ b/nms/nms-common/build.gradle.kts @@ -29,7 +29,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/nms-paper/build.gradle.kts b/nms/nms-paper/build.gradle.kts index 19033be7..1fc283d7 100644 --- a/nms/nms-paper/build.gradle.kts +++ b/nms/nms-paper/build.gradle.kts @@ -29,7 +29,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R1/build.gradle.kts b/nms/v1_21R1/build.gradle.kts index bf2152cc..ba86048f 100644 --- a/nms/v1_21R1/build.gradle.kts +++ b/nms/v1_21R1/build.gradle.kts @@ -29,7 +29,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R2/build.gradle.kts b/nms/v1_21R2/build.gradle.kts index e65f6fd8..cbb75718 100644 --- a/nms/v1_21R2/build.gradle.kts +++ b/nms/v1_21R2/build.gradle.kts @@ -29,7 +29,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R3/build.gradle.kts b/nms/v1_21R3/build.gradle.kts index d06816cc..4b54abc6 100644 --- a/nms/v1_21R3/build.gradle.kts +++ b/nms/v1_21R3/build.gradle.kts @@ -29,7 +29,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R4/build.gradle.kts b/nms/v1_21R4/build.gradle.kts index 8bd22b9f..9e2f6e31 100644 --- a/nms/v1_21R4/build.gradle.kts +++ b/nms/v1_21R4/build.gradle.kts @@ -28,7 +28,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R5/build.gradle.kts b/nms/v1_21R5/build.gradle.kts index e7f7c47c..2b5520ef 100644 --- a/nms/v1_21R5/build.gradle.kts +++ b/nms/v1_21R5/build.gradle.kts @@ -28,7 +28,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R6/build.gradle.kts b/nms/v1_21R6/build.gradle.kts index 3189b5cb..69af3d8f 100644 --- a/nms/v1_21R6/build.gradle.kts +++ b/nms/v1_21R6/build.gradle.kts @@ -28,7 +28,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } diff --git a/nms/v1_21R7/build.gradle.kts b/nms/v1_21R7/build.gradle.kts index 91c3111a..0b39eee9 100644 --- a/nms/v1_21R7/build.gradle.kts +++ b/nms/v1_21R7/build.gradle.kts @@ -28,7 +28,7 @@ tasks.withType().configureEach { kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_2) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_4) jvmTarget.set(JvmTarget.JVM_21) } } From fc4df2903346cb7f90a062ae43ff2e28d071bc6a Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 16 Aug 2026 10:51:05 +0200 Subject: [PATCH 05/14] suppress or remove most warnings --- .../dependency/datapack/DataPackTester.kt | 3 +-- .../alexcrea/cuanvil/util/AnvilTitleUtil.kt | 1 + .../cuanvil/dependency/DependencyManager.kt | 10 +++++++--- .../plugins/ItemsAdderDependency.kt | 1 + .../plugins/LegacyEcoEnchantDependency.kt | 19 +++++++++++++------ .../dependency/plugins/ToolStatsDependency.kt | 10 +++++++--- 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt index e914ce0b..043c25f8 100644 --- a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt +++ b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/datapack/DataPackTester.kt @@ -1,5 +1,4 @@ @file:Suppress("DEPRECATION", "removal") - package xyz.alexcrea.cuanvil.dependency.datapack import io.papermc.paper.datapack.Datapack @@ -26,7 +25,7 @@ object DataPackTester { } catch(_: NoSuchMethodException) { try { DataPack::class.java.getDeclaredMethod("getKey") - } catch(e: NoSuchMethodException) { + } catch(_: NoSuchMethodException) { System.err.println("Could not find compatible datapack manager") System.err.println("If you are using a datapack that should be compatible with CustomAnvil. It will not get detected...") return emptyList() diff --git a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilTitleUtil.kt b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilTitleUtil.kt index dc8ac092..447b06e6 100644 --- a/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilTitleUtil.kt +++ b/nms/nms-paper/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilTitleUtil.kt @@ -13,6 +13,7 @@ object AnvilTitleUtil { private val runTaskMap = HashMap() + @Suppress("DEPRECATION") private fun actualRename(view: AnvilView, name: String, player: HumanEntity, anvilDialog: AnvilRenameDialog) { runTaskMap.remove(player.uniqueId) if (view.title == name) return diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt index 66dd5db4..fc715a44 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt @@ -30,7 +30,7 @@ import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT import xyz.alexcrea.cuanvil.util.MetricsUtil.trackError -import java.lang.reflect.Constructor +import java.lang.IllegalStateException import java.util.logging.Level @Suppress("UnstableApiUsage") @@ -337,10 +337,14 @@ object DependencyManager { private val prepareAnvilConstructor = - PrepareAnvilEvent::class.java.constructors.first() as Constructor + PrepareAnvilEvent::class.java.constructors.first() fun createFakeEvent(view: AnvilView, result: ItemStack?): PrepareAnvilEvent { - return prepareAnvilConstructor.newInstance(view, result) + val result = prepareAnvilConstructor.newInstance(view, result) + if(result !is PrepareAnvilEvent) + throw IllegalStateException("Could not create a PrepareAnvilEvent ?") + + return result } } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ItemsAdderDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ItemsAdderDependency.kt index 9f366b20..6ef257bb 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ItemsAdderDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ItemsAdderDependency.kt @@ -6,6 +6,7 @@ import org.bukkit.NamespacedKey import org.bukkit.inventory.ItemStack import org.bukkit.plugin.Plugin +@Suppress("DEPRECATION") class ItemsAdderDependency(plugin: Plugin) : GenericPluginDependency(plugin) { var isLoaded: Boolean = false get() { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/LegacyEcoEnchantDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/LegacyEcoEnchantDependency.kt index 60f00b85..7f4196cf 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/LegacyEcoEnchantDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/LegacyEcoEnchantDependency.kt @@ -10,13 +10,20 @@ class LegacyEcoEnchantDependency { private var ecoEnchantOldEnchantments: MutableSet? = null + private fun unregisterEnchantment(enchant: Any) { + EnchantmentApi.unregisterEnchantment((enchant as Enchantment).key) + } + + private fun registerEnchantment(ecoEnchant: EcoEnchant, enchant: Any) { + EnchantmentApi.registerEnchantment(CALegacyEcoEnchant(ecoEnchant, enchant as Enchantment)) + } + fun registerEnchantments() { val enchantments = EcoEnchants.values() for (ecoEnchant in enchantments) { - ecoEnchant as Enchantment - - EnchantmentApi.unregisterEnchantment(ecoEnchant) // As eco enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant. - EnchantmentApi.registerEnchantment(CALegacyEcoEnchant(ecoEnchant, ecoEnchant)) + // As eco enchants is loaded before custom anvil and register enchantment to registry, we need to unregister old "vanilla" enchant. + unregisterEnchantment(ecoEnchant) + registerEnchantment(ecoEnchant, ecoEnchant) } ecoEnchantOldEnchantments = HashSet(enchantments) @@ -31,13 +38,13 @@ class LegacyEcoEnchantDependency { // Add new enchantments for (ecoEnchant in newEnchantments) if (!this.ecoEnchantOldEnchantments!!.contains(ecoEnchant)) - EnchantmentApi.registerEnchantment(CALegacyEcoEnchant(ecoEnchant, ecoEnchant as Enchantment)) + registerEnchantment(ecoEnchant, ecoEnchant) // Remove old enchantments that not now currently used this.ecoEnchantOldEnchantments!!.removeAll(newEnchantments) for (oldEnchantment in this.ecoEnchantOldEnchantments!!) { - EnchantmentApi.unregisterEnchantment(oldEnchantment as Enchantment) + unregisterEnchantment(oldEnchantment) } this.ecoEnchantOldEnchantments = HashSet(newEnchantments) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ToolStatsDependency.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ToolStatsDependency.kt index f1193d17..8456ec87 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ToolStatsDependency.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/plugins/ToolStatsDependency.kt @@ -18,9 +18,13 @@ class ToolStatsDependency(plugin: Plugin) : GenericPluginDependency(plugin) { getTokenMethod.trySetAccessible() } - private fun ItemChecker.getTokenSafe(item: ItemStack?): Array { - if (item == null) return arrayOf() - return getTokenMethod.invoke(this, item) as Array + private fun ItemChecker.getTokenSafe(item: ItemStack?): Array<*> { + if (item == null) return arrayOf() + val result = getTokenMethod.invoke(this, item) + if(result !is Array<*>) + throw IllegalStateException("Could not get token from ToolStats") + + return result } override fun testAnvilResult(event: InventoryClickEvent): Boolean { From 4b3fd76dd0342e79de212c79121eb5f7bf64d04f Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 16 Aug 2026 18:19:26 +0200 Subject: [PATCH 06/14] make configuration cache work --- build.gradle.kts | 9 ++++++--- gradle.properties | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3cec962f..1d807537 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -178,7 +178,10 @@ tasks { fun ShadowJar.configureBaseShadow(suffix: String, libraries: Array) { val processedSuffix = if(suffix.isEmpty()) "" else "-$suffix" - val name = "${rootProject.name}-${effectiveVersion}${processedSuffix}.jar" + val version = effectiveVersion + val name = "${rootProject.name}-${version}${processedSuffix}.jar" + val librariesExpendTo = libraries.joinToString(transform = { "\"$it\"" }) + archiveFileName.set(name) // Shadow necessary dependency @@ -187,8 +190,8 @@ tasks { filesMatching("plugin.yml") { expand( - "version" to effectiveVersion + processedSuffix, - "libraries" to libraries.joinToString(transform = { "\"$it\"" }), + "version" to version + processedSuffix, + "libraries" to librariesExpendTo, ) } diff --git a/gradle.properties b/gradle.properties index 8bf9e80a..50a6ad2d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,5 @@ kotlin.code.style=official +org.gradle.configuration-cache=true # Signing signing.secretKeyRingFile=~/.gnupg/secring.gpg From 64edb99ce00ccdbfc0b10f0e6ed5da3fd7d087e3 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 16 Aug 2026 18:58:39 +0200 Subject: [PATCH 07/14] use provider for hangar changelog --- build.gradle.kts | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 1d807537..4ce228f4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,6 @@ import groovy.util.NodeList import io.papermc.hangarpublishplugin.model.HangarPublication import io.papermc.hangarpublishplugin.model.Platforms import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import java.io.ByteArrayOutputStream plugins { kotlin("jvm") version "2.4.0" @@ -215,7 +214,7 @@ tasks { exclude("net/kyori/**") } - val offlineJar = register("OfflineJar") { + val offlineJar = register("offlineJar") { configureBaseShadow("offline", emptyArray()) from(sourceSets.main.get().output) @@ -358,35 +357,25 @@ publishing { } // hangar publish -fun executeGitCommand(vararg command: String): String { - val byteOut = ByteArrayOutputStream() - providers.exec { - commandLine = listOf("git", *command) - standardOutput = byteOut - } - return byteOut.toString(Charsets.UTF_8.name()).trim() +fun latestCommitMessage(): Provider { + return providers.exec { + commandLine("git", "log", "-1", "--pretty=%B") + }.standardOutput.asText.map(String::trim) } - -fun latestCommitMessage(): String { - return executeGitCommand("log", "-1", "--pretty=%B") -} - -fun changelog(isOnline: Boolean): String { - var changelog = if(isDevBuild) latestCommitMessage() - else System.getenv("RELEASE_CHANGELOG") - - if(!isOnline) { - changelog = "This is an offline version of the plugin. \\\n" + - "This mean that this plugin libraries are shaded into this plugin \\\n" + - "You likely want to use the normal version of this plugin\n\n" + changelog - } - - if(changelog == null || changelog.isEmpty()) { - changelog = "empty changelog" - } +fun changelog(isOnline: Boolean): Provider { + val changelog = if(isDevBuild) latestCommitMessage() + else providers.environmentVariable("RELEASE_CHANGELOG") return changelog + .filter{!it.isEmpty()} + .map { + if(!isOnline) + return@map "This is an offline version of the plugin. \\\n" + + "This mean that this plugin libraries are shaded into this plugin \\\n" + + "You likely want to use the normal version of this plugin\n\n" + it + else return@map it + }.orElse("empty changelog") } hangarPublish { @@ -402,6 +391,7 @@ hangarPublish { channel.set(finalReleaseChannel) changelog.set(changelog(isOnline)) + id.set("CustomAnvil") apiKey.set(System.getenv("HANGAR_API_TOKEN")) From 948c49a71901480c704cb219af44d85a60258ed3 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Thu, 13 Aug 2026 01:51:03 +0200 Subject: [PATCH 08/14] language backend logic --- src/main/kotlin/io/delilaheve/CustomAnvil.kt | 30 ++++-- .../cuanvil/command/ReloadExecutor.kt | 4 + .../kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt | 93 +++++++++++++++++++ .../xyz/alexcrea/cuanvil/lang/Language.kt | 56 +++++++++++ src/main/resources/config.yml | 5 + 5 files changed, 179 insertions(+), 9 deletions(-) create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index a119bfc7..c88acfd3 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -17,6 +17,7 @@ import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant +import xyz.alexcrea.cuanvil.lang.Lang import xyz.alexcrea.cuanvil.listener.AnvilCloseListener import xyz.alexcrea.cuanvil.listener.AnvilResultListener import xyz.alexcrea.cuanvil.listener.ChatEventListener @@ -135,6 +136,25 @@ open class CustomAnvil : JavaPlugin() { */ override fun onEnable() { instance = this + // Load default configuration + try { + if(!ConfigHolder.loadDefaultConfig()) + throw RuntimeException("Error loading configuration file") + } catch (e: Exception) { + logger.log(Level.SEVERE, "error occurred loading default configuration", e) + MetricsUtil.trackError(e) + if(tryDirtyStart()) return + } + + // Load language + try { + Lang.reload() + } catch (e: Exception) { + logger.log(Level.SEVERE, "error occurred loading language file", e) + MetricsUtil.trackError(e) + if(tryDirtyStart()) return + } + try { legacyCheck() } catch (e: Exception) { @@ -143,6 +163,7 @@ open class CustomAnvil : JavaPlugin() { if(trySafeStart()) return } + // Add commands try { CustomAnvilCommand(this) @@ -152,15 +173,6 @@ open class CustomAnvil : JavaPlugin() { if(trySafeStart()) return } - // Load default configuration - try { - if(!ConfigHolder.loadDefaultConfig()) - throw RuntimeException("Error loading configuration file") - } catch (e: Exception) { - logger.log(Level.SEVERE, "error occurred loading default configuration", e) - MetricsUtil.trackError(e) - if(tryDirtyStart()) return - } // Load dependency try { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt index d3df341a..bc9a80be 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt @@ -8,6 +8,7 @@ import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.gui.config.global.* +import xyz.alexcrea.cuanvil.lang.Lang import xyz.alexcrea.cuanvil.update.UpdateHandler class ReloadExecutor : CASubCommand { @@ -58,6 +59,9 @@ class ReloadExecutor : CASubCommand { try { if (!ConfigHolder.reloadAllFromDisk(hardfail)) return false + // reload language config + Lang.reload() + // Then update all global gui containing value from config BasicConfigGui.getInstance()?.updateGuiValues() EnchantCostConfigGui.getInstance()?.updateGuiValues() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt new file mode 100644 index 00000000..b89ca6bd --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt @@ -0,0 +1,93 @@ +package xyz.alexcrea.cuanvil.lang + +import io.delilaheve.CustomAnvil +import xyz.alexcrea.cuanvil.config.ConfigHolder + +object Lang { + + private val default = Language(DEFAULT_LANG, false) + private var lang = default + + fun reload() { + val langID = langID + if(lang.name == langID && lang != default) + lang.reload() + else + lang = Language(langID) + + if(default != lang) default.reload() + } + + fun String.translate(): String { + val value = lang.get(this) + if(value != null) return value + + CustomAnvil.log("Missing language data for ${lang.name} using default") + + return default.get(this) ?: this + } + + fun String.translate(vararg params: Pair): String { + return translate( + params.asSequence() + .map { Pair(it.first, it.second.toString()) } + .toMap() + ) + } + + fun String.translate(vararg params: Pair): String { + return translate( + params.asSequence() + .map { Pair(it.first.toString(), it.second.toString()) } + .toMap() + ) + } + + fun String.translate(vararg params: Pair): String { + return translate(params.toMap()) + } + + fun String.translate(vararg params: Pair): String { + return translate( + params.asSequence() + .map { Pair(it.first.toString(), it.second) } + .toMap() + ) + } + + fun String.translate(params: Map): String { + val builder = StringBuilder(translate()) + + // replace all placeholder thingy %key -> value + for((key, replacement) in params) { + var current = 0 + while(true) { + current = builder.indexOf('%', current) + 1 + if(current < 0 || current + key.length > builder.length) break // may be able to be removed if bound checked in startsWith ? + if(!builder.startsWith(key, current, false)) continue + + builder.replace(current - 1, current + key.length, replacement) + current = current - 1 + replacement.length + } + } + + return builder.toString() + } + + /* + * Config Options & get + */ + const val LANG_PATH = "language" + const val DEFAULT_LANG = "en" + + /** + * Value of an item rename + */ + private val langID: String + get() { + return ConfigHolder.DEFAULT_CONFIG + .config + .getString(LANG_PATH, DEFAULT_LANG)!! + } + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt new file mode 100644 index 00000000..d06f9aba --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt @@ -0,0 +1,56 @@ +package xyz.alexcrea.cuanvil.lang + +import io.delilaheve.CustomAnvil +import org.bukkit.configuration.file.FileConfiguration +import org.bukkit.configuration.file.YamlConfiguration +import java.io.File +import java.io.InputStreamReader +import java.util.logging.Level + + +class Language(private val id: String, private val default: Boolean = false) { + + private val resourcePath: String + private val file: File + + private val conf: FileConfiguration + + init { + conf = YamlConfiguration() + resourcePath = "lang/$id.yml" + file = File(CustomAnvil.instance.dataFolder, resourcePath) + + reload() + } + + fun reload() { + if(file.exists() && !default) try { + conf.load(file) + return + } catch(e: Exception) { + CustomAnvil.instance.logger.log( + Level.SEVERE, + "Could not load custom Anvil config file. using to internal resource", + e + ) + } + + loadInternalResource() + } + + private fun loadInternalResource() { + val input = CustomAnvil.instance.getResource(resourcePath) + if(input != null) + conf.load(InputStreamReader(input)) + else + CustomAnvil.instance.logger.log(Level.SEVERE, "Language $id not found") + + } + + fun get(key: String): String? { + return conf.getString(key) + } + + val name: String + get() = conf.getString("name", id)!! +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 218c3a1f..f67ebb17 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -16,6 +16,11 @@ metric_type: auto # Accept true or false (true by default) metric_collect_errors: true +# Which language should the plugin should be +# If you like to add language yourself see TODO link to guide +# Currently available languages: en +language: en + # All anvil cost will be capped to limit_repair_value if enabled. # # In other words: From de86fe16babb3ab8307d897f084323560f7653c4 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Thu, 13 Aug 2026 10:10:37 +0200 Subject: [PATCH 09/14] translation key for load errors and warnings --- src/main/kotlin/io/delilaheve/CustomAnvil.kt | 79 +++++++++++--------- src/main/resources/lang/en.yml | 29 +++++++ 2 files changed, 71 insertions(+), 37 deletions(-) create mode 100644 src/main/resources/lang/en.yml diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index c88acfd3..8c284ef4 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -7,8 +7,6 @@ import org.bukkit.plugin.java.JavaPlugin import xyz.alexcrea.cuanvil.api.event.CAConfigReadyEvent import xyz.alexcrea.cuanvil.api.event.CAEnchantRegistryReadyEvent import xyz.alexcrea.cuanvil.command.CustomAnvilCommand -import xyz.alexcrea.cuanvil.command.EditConfigExecutor -import xyz.alexcrea.cuanvil.command.ReloadExecutor import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.MinecraftVersionUtil @@ -18,6 +16,7 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant import xyz.alexcrea.cuanvil.lang.Lang +import xyz.alexcrea.cuanvil.lang.Lang.translate import xyz.alexcrea.cuanvil.listener.AnvilCloseListener import xyz.alexcrea.cuanvil.listener.AnvilResultListener import xyz.alexcrea.cuanvil.listener.ChatEventListener @@ -109,11 +108,23 @@ open class CustomAnvil : JavaPlugin() { } } + /** + * Error Logging handler + */ + @JvmStatic fun logError(message: String, throwable: Throwable? = null, track: Boolean = true) { + instance.logger.log(Level.SEVERE, message, throwable) + addToLogQueue(message) + + if(track && throwable != null) { + MetricsUtil.trackError(throwable) + } + } } // stop plugin if we do not force a dirty start (true by default) // Return true if start was stopped private fun tryDirtyStart(): Boolean { + if(ConfigHolder.DEFAULT_CONFIG == null) return false if(!ConfigHolder.DEFAULT_CONFIG.config.getBoolean("dirty_start", false)) { Bukkit.getPluginManager().disablePlugin(this) return true @@ -124,6 +135,7 @@ open class CustomAnvil : JavaPlugin() { // stop plugin if we force a safe start (false by default) // Return true if start was stopped private fun trySafeStart(): Boolean { + if(ConfigHolder.DEFAULT_CONFIG == null) return false if(ConfigHolder.DEFAULT_CONFIG.config.getBoolean("safe_start", false)) { Bukkit.getPluginManager().disablePlugin(this) return true @@ -141,8 +153,7 @@ open class CustomAnvil : JavaPlugin() { if(!ConfigHolder.loadDefaultConfig()) throw RuntimeException("Error loading configuration file") } catch (e: Exception) { - logger.log(Level.SEVERE, "error occurred loading default configuration", e) - MetricsUtil.trackError(e) + logError("error occurred loading default configuration", e) if(tryDirtyStart()) return } @@ -150,16 +161,14 @@ open class CustomAnvil : JavaPlugin() { try { Lang.reload() } catch (e: Exception) { - logger.log(Level.SEVERE, "error occurred loading language file", e) - MetricsUtil.trackError(e) + logError("error occurred loading language file", e) if(tryDirtyStart()) return } try { legacyCheck() } catch (e: Exception) { - logger.log(Level.SEVERE, "error trying to check for legacy system", e) - MetricsUtil.trackError(e) + logError("error.load.legacy.failed".translate(), e) if(trySafeStart()) return } @@ -168,8 +177,7 @@ open class CustomAnvil : JavaPlugin() { try { CustomAnvilCommand(this) } catch (e: Exception) { - logger.log(Level.SEVERE, "error trying to register commands", e) - MetricsUtil.trackError(e) + logError("error.load.command-register".translate(), e) if(trySafeStart()) return } @@ -178,8 +186,7 @@ open class CustomAnvil : JavaPlugin() { try { DependencyManager.loadDependency() } catch (e: Exception) { - logger.log(Level.SEVERE, "error loading dependency compatibility", e) - MetricsUtil.trackError(e) + logError("error.load.compatibility".translate(), e) if(tryDirtyStart()) return } @@ -187,8 +194,7 @@ open class CustomAnvil : JavaPlugin() { try { registerListeners() } catch (e: Exception) { - logger.log(Level.SEVERE, "error registering listeners", e) - MetricsUtil.trackError(e) + logError("error.load.listeners".translate(), e) if(tryDirtyStart()) return } @@ -204,32 +210,22 @@ open class CustomAnvil : JavaPlugin() { MetricsUtil.shutdownMetrics() } - private fun loadEnchantmentSystemDirty() { - try { - loadEnchantmentSystem() - } catch (e: Exception) { - logger.log(Level.SEVERE, "error initializing enchantment system", e) - MetricsUtil.trackError(e) - tryDirtyStart() - } - } - private fun legacyCheck() { // Disable old plugin name if exist val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus") if (potentialPlugin != null) { Bukkit.getPluginManager().disablePlugin(potentialPlugin) - logger.warning("An old version of this plugin was detected") - logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus") + logger.warning("warning.load.legacy.old-name.1".translate()) + logger.warning("warning.load.legacy.old-name.2".translate()) } val isPaper = PlatformUtil.isPaper if(!isPaper) { - logger.warning("It seems you are using spigot") - logger.warning("Please take notice that spigot is less supported than paper and derivatives") + logger.warning("warning.load.legacy.spigot.1".translate()) + logger.warning("warning.load.legacy.spigot.2".translate()) if(MinecraftVersionUtil.isTooNewForSpigot) { - logger.warning("If replace too expensive is not working this is likely because of spigot") - logger.warning("As native nms is not supported for spigot starting 26.1") + logger.warning("warning.load.legacy.spigot-old.1".translate()) + logger.warning("warning.load.legacy.spigot-old.1".translate()) } } @@ -242,13 +238,13 @@ open class CustomAnvil : JavaPlugin() { UpdateUtils.currentMinecraftVersion().toString()) .setFeatured(featured) .setOnError { - logger.log(Level.WARNING, "error trying to fetch latest update", it) + logger.log(Level.WARNING, "error.load.update.check-fail".translate(), it) } .checkVersion { latestVer: String? -> CustomAnvil.latestVer = latestVer if(latestVer == null || version.contains(latestVer)) return@checkVersion - logger.warning("An update may be available: $latestVer") + logger.warning("warning.load.update.available".translate(Pair("version", latestVer))) } } @@ -263,6 +259,15 @@ open class CustomAnvil : JavaPlugin() { server.pluginManager.registerEvents(AnvilCloseListener(DependencyManager.packetManager), this) } + private fun loadEnchantmentSystemDirty() { + try { + loadEnchantmentSystem() + } catch (e: Exception) { + logError("error.load.enchant-system".translate(), e) + tryDirtyStart() + } + } + private fun loadEnchantmentSystem(){ // Register enchantments CAEnchantmentRegistry.getInstance().registerBukkit() @@ -273,7 +278,7 @@ open class CustomAnvil : JavaPlugin() { // Load config if (!ConfigHolder.loadNonDefaultConfig()) { - logger.log(Level.SEVERE,"Plugin has an issue while trying to load non default config... exiting...") + logError("error.load.non-default-config".translate()) server.pluginManager.disablePlugin(this) return } @@ -327,15 +332,15 @@ open class CustomAnvil : JavaPlugin() { try { val configReader = FileReader(resourceFile) yamlConfig.load(configReader) - } catch (test: Exception) { + } catch (_: Exception) { if (hardFailSafe) { // This is important and may impact gameplay if it does not load. // Failsafe is to stop the plugin - logger.severe("Resource ${resourceFile.path} Could not be load or reload.") - logger.severe("Disabling plugin.") + logError("error.reload.resource.fail".translate(Pair("path", resourceFile.path))) + logError("error.reload.resource.hard-fail".translate()) Bukkit.getPluginManager().disablePlugin(this) } else { - logger.warning("Resource ${resourceFile.path} Could not be load or reload.") + logError("error.reload.resource.fail".translate(Pair("path", resourceFile.path))) } return null } diff --git a/src/main/resources/lang/en.yml b/src/main/resources/lang/en.yml new file mode 100644 index 00000000..d466dd53 --- /dev/null +++ b/src/main/resources/lang/en.yml @@ -0,0 +1,29 @@ +name: English + +warning: + load: + legacy: + old-name: + 1: "An old version of this plugin was detected" + 2: "Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus" + spigot: + 1: "It seems you are using spigot" + 2: "Please take notice that spigot is less supported than paper and derivatives" + spigot-old: + 1: "If replace too expensive is not working this is likely because of spigot" + 2: "As native nms is not supported for spigot starting 26.1" + update.available: "An update may be available: %version" + +error: + load: + legacy.failed: "error trying to check for legacy system" + update.check-fail: "error trying to fetch latest update" + command-register: "error trying to register commands" + compatibility: "error loading dependency compatibility" + listeners: "error registering listeners" + enchant-system: "error initializing enchantment system" + non-default-config: "Plugin has an issue while trying to load non default config... exiting..." + reload: + resource: + fail: "Resource %path Could not be loaded or reloaded." + hard-fail: "Disabling plugin." From 743fd5d89141ab4475de5eaa2357e77403109918 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Thu, 13 Aug 2026 13:10:22 +0200 Subject: [PATCH 10/14] better translation system --- .../{PaperSpigotUtil.kt => PlatformUtil.kt} | 17 ++- src/main/kotlin/io/delilaheve/CustomAnvil.kt | 51 ++++--- .../cuanvil/command/DiagnosticExecutor.kt | 3 +- .../kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt | 53 +------- .../xyz/alexcrea/cuanvil/lang/Language.kt | 1 - .../xyz/alexcrea/cuanvil/lang/Message.kt | 128 ++++++++++++++++++ .../kotlin/xyz/alexcrea/cuanvil/lang/Msg.kt | 4 + .../xyz/alexcrea/cuanvil/lang/MsgError.kt | 26 ++++ .../xyz/alexcrea/cuanvil/lang/MsgWarning.kt | 17 +++ .../xyz/alexcrea/cuanvil/util/MetricsUtil.kt | 4 +- src/main/resources/lang/en.yml | 36 +++++ 11 files changed, 257 insertions(+), 83 deletions(-) rename nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/{PaperSpigotUtil.kt => PlatformUtil.kt} (88%) create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/lang/Msg.kt create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgError.kt create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigotUtil.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PlatformUtil.kt similarity index 88% rename from nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigotUtil.kt rename to nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PlatformUtil.kt index 20972bfa..3b47adaa 100644 --- a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigotUtil.kt +++ b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PlatformUtil.kt @@ -2,7 +2,7 @@ package xyz.alexcrea.cuanvil.dependency.util import net.kyori.adventure.text.Component import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer -import org.bukkit.inventory.ItemStack +import org.bukkit.command.CommandSender import org.bukkit.inventory.meta.ItemMeta // Mostly made for paper, spigot and folia support @@ -100,4 +100,19 @@ object PlatformUtil { } } + /** + * Try to send paper component to the player + * + * @param component The used component + * @return true if sent, else otherwise + */ + fun CommandSender.sendPaperMessage(component: Component): Boolean { + if(isPaper) { + this.sendMessage(component) + return true + } + + return false + } + } diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index 8c284ef4..df000bce 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -16,7 +16,8 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant import xyz.alexcrea.cuanvil.lang.Lang -import xyz.alexcrea.cuanvil.lang.Lang.translate +import xyz.alexcrea.cuanvil.lang.MsgError +import xyz.alexcrea.cuanvil.lang.MsgWarning import xyz.alexcrea.cuanvil.listener.AnvilCloseListener import xyz.alexcrea.cuanvil.listener.AnvilResultListener import xyz.alexcrea.cuanvil.listener.ChatEventListener @@ -111,12 +112,12 @@ open class CustomAnvil : JavaPlugin() { /** * Error Logging handler */ - @JvmStatic fun logError(message: String, throwable: Throwable? = null, track: Boolean = true) { - instance.logger.log(Level.SEVERE, message, throwable) - addToLogQueue(message) + @JvmStatic fun logError(message: String, throwable: Throwable? = null, track: Boolean = true, level: Level = Level.SEVERE) { + instance.logger.log(level, message, throwable) + addToLogQueue("Error: $message") - if(track && throwable != null) { - MetricsUtil.trackError(throwable) + if(track) { + MetricsUtil.trackError(message, throwable) } } } @@ -168,7 +169,7 @@ open class CustomAnvil : JavaPlugin() { try { legacyCheck() } catch (e: Exception) { - logError("error.load.legacy.failed".translate(), e) + MsgError.LOAD_LEGACY_FAILED.log(e) if(trySafeStart()) return } @@ -177,7 +178,7 @@ open class CustomAnvil : JavaPlugin() { try { CustomAnvilCommand(this) } catch (e: Exception) { - logError("error.load.command-register".translate(), e) + MsgError.LOAD_COMMAND_REGISTER.log(e) if(trySafeStart()) return } @@ -186,7 +187,7 @@ open class CustomAnvil : JavaPlugin() { try { DependencyManager.loadDependency() } catch (e: Exception) { - logError("error.load.compatibility".translate(), e) + MsgError.LOAD_COMPATIBILITY.log(e) if(tryDirtyStart()) return } @@ -194,7 +195,7 @@ open class CustomAnvil : JavaPlugin() { try { registerListeners() } catch (e: Exception) { - logError("error.load.listeners".translate(), e) + MsgError.LOAD_LISTENERS.log(e) if(tryDirtyStart()) return } @@ -215,18 +216,15 @@ open class CustomAnvil : JavaPlugin() { val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus") if (potentialPlugin != null) { Bukkit.getPluginManager().disablePlugin(potentialPlugin) - logger.warning("warning.load.legacy.old-name.1".translate()) - logger.warning("warning.load.legacy.old-name.2".translate()) + MsgWarning.LOAD_LEGACY_OLD_NAME.log() } val isPaper = PlatformUtil.isPaper if(!isPaper) { - logger.warning("warning.load.legacy.spigot.1".translate()) - logger.warning("warning.load.legacy.spigot.2".translate()) - if(MinecraftVersionUtil.isTooNewForSpigot) { - logger.warning("warning.load.legacy.spigot-old.1".translate()) - logger.warning("warning.load.legacy.spigot-old.1".translate()) - } + MsgWarning.LOAD_LEGACY_SPIGOT.log() + if(MinecraftVersionUtil.isTooNewForSpigot) + MsgWarning.LOAD_LEGACY_SPIGOT_OLD.log() + } val loader = if(isPaper) "paper" else "spigot" @@ -238,13 +236,13 @@ open class CustomAnvil : JavaPlugin() { UpdateUtils.currentMinecraftVersion().toString()) .setFeatured(featured) .setOnError { - logger.log(Level.WARNING, "error.load.update.check-fail".translate(), it) + MsgError.LOAD_UPDATE_CHECK_FAIL.log(it, level = Level.WARNING, track = false) } .checkVersion { latestVer: String? -> CustomAnvil.latestVer = latestVer if(latestVer == null || version.contains(latestVer)) return@checkVersion - logger.warning("warning.load.update.available".translate(Pair("version", latestVer))) + MsgWarning.LOAD_UPDATE_AVAILABLE.log(latestVer) } } @@ -263,7 +261,7 @@ open class CustomAnvil : JavaPlugin() { try { loadEnchantmentSystem() } catch (e: Exception) { - logError("error.load.enchant-system".translate(), e) + MsgError.LOAD_ENCHANT_SYSTEM.log(e) tryDirtyStart() } } @@ -278,7 +276,7 @@ open class CustomAnvil : JavaPlugin() { // Load config if (!ConfigHolder.loadNonDefaultConfig()) { - logError("error.load.non-default-config".translate()) + MsgError.LOAD_NON_DEFAULT_CONFIG.log() server.pluginManager.disablePlugin(this) return } @@ -332,16 +330,15 @@ open class CustomAnvil : JavaPlugin() { try { val configReader = FileReader(resourceFile) yamlConfig.load(configReader) - } catch (_: Exception) { + } catch (e: Exception) { + MsgError.RELOAD_FAIL.log(e, resourceFile.path) if (hardFailSafe) { // This is important and may impact gameplay if it does not load. // Failsafe is to stop the plugin - logError("error.reload.resource.fail".translate(Pair("path", resourceFile.path))) - logError("error.reload.resource.hard-fail".translate()) + MsgError.RELOAD_HARD_FAIL.log() Bukkit.getPluginManager().disablePlugin(this) - } else { - logError("error.reload.resource.fail".translate(Pair("path", resourceFile.path))) } + return null } return yamlConfig diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt index c2293afc..4998f14d 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt @@ -122,8 +122,7 @@ class DiagnosticExecutor : CASubCommand { if (sender is HumanEntity) { if (hasError) - sender.spigot() - .sendMessage(TextComponent(ChatColor.RED.toString() + "There was an error running the diagnostic")) + sender.sendMessage(ChatColor.RED.toString() + "There was an error running the diagnostic") val message = TextComponent(ChatColor.GREEN.toString() + "Click to copy diagnostic data") message.clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, stb.toString()) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt index b89ca6bd..db8a2b29 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt @@ -18,60 +18,13 @@ object Lang { if(default != lang) default.reload() } - fun String.translate(): String { - val value = lang.get(this) + fun getTranslated(key: String): String { + val value = lang.get(key) if(value != null) return value CustomAnvil.log("Missing language data for ${lang.name} using default") - return default.get(this) ?: this - } - - fun String.translate(vararg params: Pair): String { - return translate( - params.asSequence() - .map { Pair(it.first, it.second.toString()) } - .toMap() - ) - } - - fun String.translate(vararg params: Pair): String { - return translate( - params.asSequence() - .map { Pair(it.first.toString(), it.second.toString()) } - .toMap() - ) - } - - fun String.translate(vararg params: Pair): String { - return translate(params.toMap()) - } - - fun String.translate(vararg params: Pair): String { - return translate( - params.asSequence() - .map { Pair(it.first.toString(), it.second) } - .toMap() - ) - } - - fun String.translate(params: Map): String { - val builder = StringBuilder(translate()) - - // replace all placeholder thingy %key -> value - for((key, replacement) in params) { - var current = 0 - while(true) { - current = builder.indexOf('%', current) + 1 - if(current < 0 || current + key.length > builder.length) break // may be able to be removed if bound checked in startsWith ? - if(!builder.startsWith(key, current, false)) continue - - builder.replace(current - 1, current + key.length, replacement) - current = current - 1 + replacement.length - } - } - - return builder.toString() + return default.get(key) ?: key } /* diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt index d06f9aba..d6054ba2 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt @@ -7,7 +7,6 @@ import java.io.File import java.io.InputStreamReader import java.util.logging.Level - class Language(private val id: String, private val default: Boolean = false) { private val resourcePath: String diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt new file mode 100644 index 00000000..be4b8f41 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt @@ -0,0 +1,128 @@ +package xyz.alexcrea.cuanvil.lang + +import io.delilaheve.CustomAnvil +import net.kyori.adventure.text.Component +import org.bukkit.command.CommandSender +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.sendPaperMessage +import xyz.alexcrea.cuanvil.util.MiniMessageUtil +import java.util.logging.Level +import kotlin.math.min + +interface MessageLike { + + fun log(vararg params: Any) + + fun send(destination: CommandSender, vararg params: Any) +} + +enum class MessageType { + DEFAULT, + WARNING, + ERROR, +} + +open class Message(val key: String, vararg val params: String) : MessageLike { + + protected fun replaceParameters(stb: StringBuilder, vararg values: Any) { + // replace all placeholder thingy %key -> value + + for(i in 0 until min(params.size, values.size)) { + val key = params[i] + val replacement = values[i].toString() + + var current = 0 + while(true) { + current = stb.indexOf('%', current) + 1 + if(current < 0 || current + key.length > stb.length) break // may be able to be removed if bound checked in startsWith ? + if(!stb.startsWith(key, current, false)) continue + + stb.replace(current - 1, current + key.length, replacement) + current = current - 1 + replacement.length + } + } + } + + fun unformatted(vararg params: Any): String { + val translated = Lang.getTranslated(key) + if(params.isEmpty()) return translated + + val stb = StringBuilder(translated) + replaceParameters(stb, *params) + return stb.toString() + } + + fun formatted(vararg params: Any): Component { + val unformatted = unformatted(*params) + + return MiniMessageUtil.mm.deserialize(unformatted) + } + + override fun log(vararg params: Any) { + val text = unformatted(*params) + + CustomAnvil.instance.logger.info(text) + } + + override fun send(destination: CommandSender, vararg params: Any) { + val message = formatted(*params) + if(!destination.sendPaperMessage(message)) + destination.sendMessage(MiniMessageUtil.legacy_mm.serialize(message)) + } +} + +class WarningMessage(key: String, vararg params: String) : Message("warning.$key", *params) { + + override fun log(vararg params: Any) { + val text = unformatted(*params) + + CustomAnvil.instance.logger.warning(text) + } + +} + +class ErrorMessage(key: String, vararg params: String) : Message("error.$key", *params) { + + override fun log(vararg params: Any) { + val text = unformatted(*params) + + CustomAnvil.logError(text) + } + + fun log(e: Throwable, vararg params: Any, level: Level = Level.SEVERE, track: Boolean = true) { + val text = unformatted(*params) + + CustomAnvil.logError(text, e, track, level) + } +} + +class MultiLineMessage(type: MessageType, baseKey: String, count: Int, vararg params: String) : MessageLike { + + private val messages = ArrayList() + + init { + for(i in 1 until count + 1) { + val message = createNew(type, "$baseKey.$i", *params) + messages.add(message) + } + } + + private fun createNew(type: MessageType, key: String, vararg params: String): MessageLike { + return when(type) { + MessageType.DEFAULT -> Message(key, *params) + MessageType.WARNING -> WarningMessage(key, *params) + MessageType.ERROR -> ErrorMessage(key, *params) + } + } + + override fun log(vararg params: Any) { + for(message in messages) { + message.log(*params) + } + } + + override fun send(destination: CommandSender, vararg params: Any) { + for(message in messages) { + message.send(destination, *params) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Msg.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Msg.kt new file mode 100644 index 00000000..7823f79d --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Msg.kt @@ -0,0 +1,4 @@ +package xyz.alexcrea.cuanvil.lang + +object Msg { +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgError.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgError.kt new file mode 100644 index 00000000..6e5e26fb --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgError.kt @@ -0,0 +1,26 @@ +package xyz.alexcrea.cuanvil.lang + +object MsgError { + + /* + * ----------------- + * Load and reload + * ----------------- + */ + val LOAD_UPDATE_CHECK_FAIL = ErrorMessage("load.update.check-fail") + val LOAD_LEGACY_FAILED = ErrorMessage("load.legacy.failed") + val LOAD_COMMAND_REGISTER = ErrorMessage("load.command-register") + val LOAD_COMPATIBILITY = ErrorMessage("load.compatibility") + val LOAD_LISTENERS = ErrorMessage("load.listeners") + val LOAD_ENCHANT_SYSTEM = ErrorMessage("load.enchant-system") + val LOAD_NON_DEFAULT_CONFIG = ErrorMessage("load.non-default-config") + + val RELOAD_FAIL = ErrorMessage("reload.resource.fail", "path") + val RELOAD_HARD_FAIL = ErrorMessage("reload.resource.hardfail") + + /* + * ---------- + * Commands + * ---------- + */ +} diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt new file mode 100644 index 00000000..aa7af304 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt @@ -0,0 +1,17 @@ +package xyz.alexcrea.cuanvil.lang + +object MsgWarning { + + /* + * --------------- + * Load and reload + * --------------- + */ + val LOAD_UPDATE_AVAILABLE = WarningMessage("load.update.available", "version") + + val LOAD_LEGACY_OLD_NAME = MultiLineMessage(MessageType.WARNING, "load.legacy.old-name", 2) + val LOAD_LEGACY_SPIGOT = MultiLineMessage(MessageType.WARNING, "load.legacy.spigot", 2) + val LOAD_LEGACY_SPIGOT_OLD = MultiLineMessage(MessageType.WARNING, "load.legacy.spigot", 2) + + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt index 1763db56..88004112 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MetricsUtil.kt @@ -74,8 +74,8 @@ object MetricsUtil { lastError = e } - fun trackError(message: String) { - ERROR_TRACKER?.trackError(message) + fun trackError(message: String, cause: Throwable? = null) { + trackError(RuntimeException(message, cause)) } } diff --git a/src/main/resources/lang/en.yml b/src/main/resources/lang/en.yml index d466dd53..b0c96009 100644 --- a/src/main/resources/lang/en.yml +++ b/src/main/resources/lang/en.yml @@ -1,4 +1,5 @@ name: English +last-updated: 2.1.0 warning: load: @@ -27,3 +28,38 @@ error: resource: fail: "Resource %path Could not be loaded or reloaded." hard-fail: "Disabling plugin." + +command: + shared: + no-diag-permission: "You do not have permission to diagnostic this server" + # I try to avoid using & for color but this is for a bungee text component + hover-copy: "§7Click to copy" + warning: + missing-subcmd: "Need to specify a subcommand. for example %example1 or %example2" + root: + warning: + unknown-sub: "Invalid subcommand. run `%command help` to see available commands" + error: + generic: "Error running this command" + debug: + description: "Used to toggle debug logs and retrieve them" + log-cleared: "Log Cleared" + toggled: "Debug toggled to %type" + # I try to avoid using & for color but this is for a bungee text component + copy: "§aClick to copy log data" + data: + header: "Debug Log data:" + line-count: "Found %count lines" + warning: + unspecified-type: "Need to specify which type of debug to toggle: \"default\" or \"verbose\"" + no-log: "No log to show ? make sure you tried with debug log toggled (%command)" + diagnostic: + description: "Basic diagnostic of this plugin" + had-error: "There was an error running the diagnostic" + # I try to avoid using & for color but this is for a bungee text component + copy: "§aClick to copy diagnostic data" + config: + description: "Used to edit the configuration of the plugin" + + warning: + legacy-name: "/ca gui has been moved to /ca config" \ No newline at end of file From 35e0b34ecf386566b9e35ec3f0b91136bf15b3f2 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sat, 15 Aug 2026 05:15:11 +0200 Subject: [PATCH 11/14] finished adding command text to trans file --- src/main/kotlin/io/delilaheve/CustomAnvil.kt | 5 +- .../alexcrea/cuanvil/command/CASubCommand.kt | 3 +- .../cuanvil/command/CustomAnvilCommand.kt | 7 +- .../cuanvil/command/DebugToggleExecutor.kt | 68 +++++++++-------- .../cuanvil/command/DiagnosticExecutor.kt | 17 +++-- .../cuanvil/command/EditConfigExecutor.kt | 49 ++++++------ .../cuanvil/command/EnchantExecutor.kt | 54 +++++++------- .../alexcrea/cuanvil/command/HelpExecutor.kt | 31 ++++---- .../cuanvil/command/ReloadExecutor.kt | 34 +++++---- .../xyz/alexcrea/cuanvil/lang/Message.kt | 57 +++++++++++--- .../xyz/alexcrea/cuanvil/lang/MsgCommand.kt | 74 +++++++++++++++++++ .../kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt | 6 ++ .../xyz/alexcrea/cuanvil/lang/MsgWarning.kt | 25 +++++-- .../alexcrea/cuanvil/util/ComponentUtil.kt | 14 ++++ src/main/resources/lang/en.yml | 43 +++++++++-- 15 files changed, 334 insertions(+), 153 deletions(-) create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt diff --git a/src/main/kotlin/io/delilaheve/CustomAnvil.kt b/src/main/kotlin/io/delilaheve/CustomAnvil.kt index df000bce..7ff46191 100644 --- a/src/main/kotlin/io/delilaheve/CustomAnvil.kt +++ b/src/main/kotlin/io/delilaheve/CustomAnvil.kt @@ -1,6 +1,7 @@ package io.delilaheve import io.delilaheve.util.ConfigOptions +import net.kyori.adventure.text.Component import org.bukkit.Bukkit import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.plugin.java.JavaPlugin @@ -76,7 +77,7 @@ open class CustomAnvil : JavaPlugin() { var latestVer: String? = null // Debug - val debugStorageQueue = ArrayDeque() + val debugStorageQueue = ArrayDeque() private fun addToLogQueue(message: String) { if(debugStorageQueue.size >= 200) { @@ -84,7 +85,7 @@ open class CustomAnvil : JavaPlugin() { debugStorageQueue.removeFirst() } - debugStorageQueue.addLast(message) + debugStorageQueue.addLast(Component.text(message)) } /** diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt index ede87e9a..ec893559 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt @@ -3,6 +3,7 @@ package xyz.alexcrea.cuanvil.command import org.bukkit.command.Command import org.bukkit.command.CommandSender import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry +import xyz.alexcrea.cuanvil.lang.MessageLike interface CASubCommand { @@ -21,7 +22,7 @@ interface CASubCommand { list: MutableList ) - fun description(): String + fun description(): MessageLike fun allEnchantmentsByName(): Collection { val names = mutableSetOf() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCommand.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCommand.kt index 1cae583f..ef4a3f41 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCommand.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CustomAnvilCommand.kt @@ -6,6 +6,7 @@ import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.command.TabCompleter +import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.util.MetricsUtil class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter { @@ -57,15 +58,15 @@ class CustomAnvilCommand(plugin: CustomAnvil) : CommandExecutor, TabCompleter { } if (subcmd == null || !subcmd.allowed(sender)) { - sender.sendMessage("Invalid subcommand. run `$cmdstr help` to see available commands") + MsgCommand.ROOT_UNKNOWN_SUBCOMMAND.send(sender, cmdstr) return true } try { return subcmd.executeCommand(sender, cmd, subcmdStr, newargs) } catch (e: Throwable) { - MetricsUtil.trackError(e) - sender.sendMessage("§cError running this command") + CustomAnvil.logError("Error running /$cmdstr ${args.joinToString(" ")}", e) + MsgCommand.ROOT_ERROR_SUBCOMMAND.send(sender) return false } } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt index 302ff782..c0c4862f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt @@ -6,16 +6,17 @@ import net.md_5.bungee.api.chat.ClickEvent import net.md_5.bungee.api.chat.HoverEvent import net.md_5.bungee.api.chat.TextComponent import net.md_5.bungee.api.chat.hover.content.Text -import org.bukkit.ChatColor import org.bukkit.command.Command import org.bukkit.command.CommandSender import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.command.DiagnosticExecutor.Companion.NO_DIAG_PERM +import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.MsgCommand +import xyz.alexcrea.cuanvil.util.MiniMessageUtil class DebugToggleExecutor : CASubCommand { - override fun description(): String { - return "Used to toggle debug logs and retrieve it" + override fun description(): MessageLike { + return MsgCommand.DEBUG_DESCRIPTION } override fun allowed(sender: CommandSender): Boolean { @@ -26,18 +27,18 @@ class DebugToggleExecutor : CASubCommand { sender: CommandSender, cmd: Command, cmdstr: String, - args: Array + args: Array, ): Boolean { - if (!allowed(sender)) { - sender.sendMessage(NO_DIAG_PERM) + if(!allowed(sender)) { + MsgCommand.SHARED_NO_DIAG_PERM.send(sender) return false } - if (args.isEmpty()) { - sender.sendMessage("Need to specify a subcommand: \"toggle\" or \"get\"") + if(args.isEmpty()) { + MsgCommand.SHARED_MISSING_SUBCOMMAND.send(sender) return true } - when (args[0].lowercase()) { + when(args[0].lowercase()) { "toggle" -> executeToggle(sender, args) "get" -> executeGet(sender) "get-and-clear" -> { @@ -47,52 +48,57 @@ class DebugToggleExecutor : CASubCommand { "clear" -> { CustomAnvil.debugStorageQueue.clear() - sender.sendMessage("Log Cleared") + MsgCommand.DEBUG_LOG_CLEARED.send(sender) } - else -> return false + else -> { + MsgCommand.SHARED_UNKNOWN_SUB_COMMAND.send(sender) + return false + } } return true } private fun executeToggle(sender: CommandSender, args: Array) { - if (args.size < 2) { - sender.sendMessage("Need to specify which type of debug to toggle: \"default\" or \"verbose\"") + if(args.size < 2) { + MsgCommand.DEBUG_WARNING_UNSPECIFIED_TYPE.send(sender) return } - when (args[1].lowercase()) { + when(args[1].lowercase()) { "default" -> { ConfigOptions.OVERRIDE_DEBUG_LOG = !ConfigOptions.debugLog - sender.sendMessage("Debug toggle to: ${ConfigOptions.debugLog}") + MsgCommand.DEBUG_TOGGLED.send(sender, ConfigOptions.debugLog) } "verbose" -> { ConfigOptions.OVERRIDE_VERBOSE_DEBUG_LOG = !ConfigOptions.verboseDebugLog - sender.sendMessage("Debug toggle to: ${ConfigOptions.verboseDebugLog}") + MsgCommand.DEBUG_TOGGLED.send(sender, ConfigOptions.debugLog) } - else -> sender.sendMessage("Invalid debug type: ${args[1]}") + else -> MsgCommand.DEBUG_WARNING_INVALID_TYPE.send(sender, ConfigOptions.debugLog) } - } private fun executeGet(sender: CommandSender) { - val stb = StringBuilder("Debug Log data:") - if (CustomAnvil.debugStorageQueue.isEmpty()) { - sender.sendMessage("No log to show ? make sure you tried with debug log toggled (/ca debug toggle)") + if(CustomAnvil.debugStorageQueue.isEmpty()) { + MsgCommand.DEBUG_WARNING_NO_LOG.send(sender, "/ca debug toggle") return } - stb.append("\nFound ${CustomAnvil.debugStorageQueue.size} lines\n") - for (log in CustomAnvil.debugStorageQueue) { - stb.append('\n').append(log) + val stb = StringBuilder(MsgCommand.DEBUG_DATA_HEADER.unformatted()).append(' ') + stb.append(MsgCommand.DEBUG_DATA_LINE_COUNT.unformatted(CustomAnvil.debugStorageQueue.size)) + for(log in CustomAnvil.debugStorageQueue) { + stb.append('\n').append(MiniMessageUtil.plain_text_mm.serialize(log)) } - if (sender is Player) { - val message = TextComponent(ChatColor.GREEN.toString() + "Click to copy log data") + if(sender is Player) { + val message = TextComponent(MsgCommand.DEBUG_COPY.legacy()) message.clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, stb.toString()) - message.hoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT, Text("§7Click to copy")) + message.hoverEvent = HoverEvent( + HoverEvent.Action.SHOW_TEXT, + Text(MsgCommand.SHARED_HOVER_COPY.legacy()) + ) sender.spigot().sendMessage(message); } else { @@ -101,12 +107,12 @@ class DebugToggleExecutor : CASubCommand { } override fun tabCompleter(sender: CommandSender, args: Array, list: MutableList) { - if (!allowed(sender)) return + if(!allowed(sender)) return list.addAll( - when (args.size) { + when(args.size) { 1 -> listOf("toggle", "get", "get-and-clear", "clear") - 2 -> when (args[0].lowercase()) { + 2 -> when(args[0].lowercase()) { "toggle" -> listOf("default", "verbose") else -> listOf() } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt index 4998f14d..b015fde0 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt @@ -6,7 +6,6 @@ import net.md_5.bungee.api.chat.HoverEvent import net.md_5.bungee.api.chat.TextComponent import net.md_5.bungee.api.chat.hover.content.Text import org.bukkit.Bukkit -import org.bukkit.ChatColor import org.bukkit.Material import org.bukkit.command.Command import org.bukkit.command.CommandSender @@ -25,15 +24,17 @@ import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.packet.NoPacketManager import xyz.alexcrea.cuanvil.dependency.packet.ProtocoLibWrapper import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry +import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener import xyz.alexcrea.cuanvil.util.MetricsUtil import java.util.* import java.util.stream.Collectors +@Suppress("UnstableApiUsage") class DiagnosticExecutor : CASubCommand { companion object { - const val NO_DIAG_PERM = "You do not have permission to diagnostic this server" fun fetchNMSType(): String { val packetManager = DependencyManager.packetManager @@ -101,7 +102,7 @@ class DiagnosticExecutor : CASubCommand { args: Array ): Boolean { if (!allowed(sender)) { - sender.sendMessage(NO_DIAG_PERM) + MsgCommand.SHARED_NO_DIAG_PERM.send(sender) return false } @@ -122,11 +123,11 @@ class DiagnosticExecutor : CASubCommand { if (sender is HumanEntity) { if (hasError) - sender.sendMessage(ChatColor.RED.toString() + "There was an error running the diagnostic") - val message = TextComponent(ChatColor.GREEN.toString() + "Click to copy diagnostic data") + MsgCommand.DIAGNOSTIC_ERROR_GENERIC.send(sender) + val message = TextComponent(MsgCommand.DIAGNOSTIC_COPY.legacy()) message.clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, stb.toString()) - message.hoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT, Text("§7Click to copy")) + message.hoverEvent = HoverEvent(HoverEvent.Action.SHOW_TEXT, Text(MsgCommand.SHARED_HOVER_COPY.legacy())) sender.spigot().sendMessage(message) } else { @@ -213,8 +214,8 @@ class DiagnosticExecutor : CASubCommand { return this.name + " v" + this.description.version } - override fun description(): String { - return "Basic diagnostic of this plugin" + override fun description(): MessageLike { + return MsgCommand.DIAGNOSTIC_DESCRIPTION } private fun pluginListDiag(sender: CommandSender, stb: StringBuilder) { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt index 79151cd3..0fc522d2 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt @@ -11,6 +11,8 @@ import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.config.global.EnchantConfigGui import xyz.alexcrea.cuanvil.gui.config.global.ItemConfigGui import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions +import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.util.MaterialUtil.customType import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir @@ -20,42 +22,38 @@ class EditConfigExecutor : CASubCommand { return sender.hasPermission(CustomAnvil.editConfigPermission) } - override fun description(): String { - return "Gui to edit the plugin's config" + override fun description(): MessageLike { + return MsgCommand.CONFIG_DESCRIPTION } override fun executeCommand( sender: CommandSender, cmd: Command, cmdstr: String, - args: Array + args: Array, ): Boolean { - if (sender !is HumanEntity) return false + if(sender !is HumanEntity) return false - if (!allowed(sender)) { + if(!allowed(sender)) { sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM) return false } - if (PlatformUtil.isFolia) { - sender.sendMessage("§cIt look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia.") - sender.sendMessage("§eIt is may come in a future version.") - sender.sendMessage("") - sender.sendMessage("§eCurrently you need to edit manually the config or copy from another server (spigot or better)") - sender.sendMessage("§eThen /ca reload after config file is edited") + if(PlatformUtil.isFolia) { + MsgCommand.CONFIG_FOLIA_ISSUE.send(sender) return false } - if ("gui".equals(cmdstr, ignoreCase = true)) { - sender.sendMessage("§c/ca gui has been moved to /ca config") + if("gui".equals(cmdstr, ignoreCase = true)) { + MsgCommand.CONFIG_LEGACY_NAME_WARNING.send(sender) } - if (args.isEmpty()) + if(args.isEmpty()) processOpen(sender) - else when (args[0].lowercase()) { + else when(args[0].lowercase()) { "open" -> processOpen(sender) "enchant" -> processEnchant(sender, args) "item" -> processItem(sender) - else -> sender.sendMessage("Unknown subcommand \"${args[0]}\"") + else -> MsgCommand.SHARED_UNKNOWN_SUB_COMMAND.send(sender) } return true @@ -63,31 +61,30 @@ class EditConfigExecutor : CASubCommand { private fun processEnchant(sender: HumanEntity, args: Array) { val enchantToFilter: Set - if (args.size <= 1) { + if(args.size <= 1) { val item = sender.inventory.itemInMainHand enchantToFilter = EnchantmentApi.getEnchantments(item).keys - if (enchantToFilter.isEmpty()) { - sender.sendMessage("No enchantment found in the item you are holding") + if(enchantToFilter.isEmpty()) { + MsgCommand.CONFIG_ENCHANTMENT_NO_IN_HAND.send(sender) return } } else { enchantToFilter = HashSet(EnchantmentApi.getByName(args[1].lowercase())) - if (enchantToFilter.isEmpty()) { - sender.sendMessage("No enchantment found with the name \"${args[1]}\"") + if(enchantToFilter.isEmpty()) { + MsgCommand.CONFIG_ENCHANTMENT_NO_NAME.send(sender, args[1]) return } } EnchantConfigGui(enchantToFilter).show(sender) - } private fun processItem(sender: HumanEntity) { val item = sender.inventory.itemInMainHand - if (item.isAir) { - sender.sendMessage("Cannot configure the item in hand") + if(item.isAir) { + MsgCommand.CONFIG_CANNOT_CONFIGURE_WARNING.send(sender) return } @@ -104,10 +101,10 @@ class EditConfigExecutor : CASubCommand { override fun tabCompleter(sender: CommandSender, args: Array, list: MutableList) { list.addAll( - when (args.size) { + when(args.size) { 1 -> listOf("item", "enchant", "open") 2 -> { - when (args[0].lowercase()) { + when(args[0].lowercase()) { "enchant" -> allEnchantmentsByName() else -> listOf() } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EnchantExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EnchantExecutor.kt index 654df1a8..46b256f3 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EnchantExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EnchantExecutor.kt @@ -10,6 +10,8 @@ import org.bukkit.command.CommandSender import org.bukkit.entity.HumanEntity import xyz.alexcrea.cuanvil.api.EnchantmentApi import xyz.alexcrea.cuanvil.enchant.CAEnchantment +import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir class EnchantExecutor : CASubCommand { @@ -19,74 +21,74 @@ class EnchantExecutor : CASubCommand { return sender.hasPermission(CustomAnvil.giveEnchantmentPermission) } - override fun description(): String { - return "Allows to set enchantment to holden item" + override fun description(): MessageLike { + return MsgCommand.ENCHANT_DESCRIPTION } override fun executeCommand( sender: CommandSender, cmd: Command, cmdstr: String, - args: Array + args: Array, ): Boolean { - if (sender !is HumanEntity) return true + if(sender !is HumanEntity) return true - if (!allowed(sender)) { - sender.sendMessage("No permission to execute this command") + if(!allowed(sender)) { + MsgCommand.SHARED_NO_PERMISSION.send(sender) return true } - when (args.size) { + when(args.size) { 0 -> { - sender.sendMessage("Missing enchantment parameter") + MsgCommand.ENCHANT_MISSING_PARAMETER_WARNING.send(sender) return true } } val enchant = firstEnchantment(args[0]) - if (enchant == null) { - sender.sendMessage("Enchantment not found: ${args[0]}") + if(enchant == null) { + MsgCommand.ENCHANT_NOT_FOUND_WARNING.send(sender, args[0]) return true } - val level = if (args.size > 1) + val level = if(args.size > 1) args[1].toIntOrNull()?.coerceIn(0, ConfigOptions.ENCHANT_LIMIT) else 1 - if (level == null) { - sender.sendMessage("Invalid number: ${args[1]}") + if(level == null) { + MsgCommand.ENCHANT_MALFORMED_NUMBER_WARNING.send(sender, args[1]) return true } val inHand = sender.inventory.itemInMainHand - if (inHand.isAir) { - sender.sendMessage("Cannot enchant this item") + if(inHand.isAir) { + MsgCommand.ENCHANT_CANNOT_ENCHANT_WARNING.send(sender) return true } - if (level == 0) { + if(level == 0) { enchant.removeFrom(inHand) - if (inHand.isEnchantedBook() && EnchantmentApi.getEnchantments(inHand).isEmpty()) + if(inHand.isEnchantedBook() && EnchantmentApi.getEnchantments(inHand).isEmpty()) inHand.type = Material.BOOK - sender.sendMessage("${enchant.prettyName} removed") + MsgCommand.ENCHANT_REMOVE.send(sender, enchant.prettyName) } else { - if (Material.BOOK == inHand.type) + if(Material.BOOK == inHand.type) inHand.type = Material.ENCHANTED_BOOK enchant.addEnchantmentUnsafe(inHand, level) - sender.sendMessage("${enchant.prettyName} set to level $level") + MsgCommand.ENCHANT_SET.send(sender, enchant.prettyName, level) } return true } override fun tabCompleter(sender: CommandSender, args: Array, list: MutableList) { - if (sender !is HumanEntity) return + if(sender !is HumanEntity) return list.addAll( - when (args.size) { + when(args.size) { 1 -> allEnchantmentsByName() 2 -> findEnchantmentLevels(sender, args[0]) @@ -97,19 +99,19 @@ class EnchantExecutor : CASubCommand { private fun findEnchantmentLevels( sender: HumanEntity, - name: String + name: String, ): Collection { val enchant = firstEnchantment(name) ?: return listOf() val limit = ConfigOptions.enchantLimit(enchant) val result = mutableListOf() - for (i in 1 until limit + 1) { + for(i in 1 until limit + 1) { result.add(i.toString()) } val inHand = sender.inventory.itemInMainHand - if (enchant.isEnchantmentPresent(inHand)) + if(enchant.isEnchantmentPresent(inHand)) result.add("0") return result @@ -117,7 +119,7 @@ class EnchantExecutor : CASubCommand { private fun firstEnchantment(name: String): CAEnchantment? { val enchants = EnchantmentApi.getByName(name.lowercase()) - if (!enchants.isEmpty()) + if(!enchants.isEmpty()) return enchants.iterator().next() return EnchantmentApi.getByKey(NamespacedKey.fromString(name)) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt index c6c4d08c..1f669ac5 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt @@ -1,29 +1,38 @@ package xyz.alexcrea.cuanvil.command import com.google.common.collect.ImmutableMap +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.TextComponent import org.bukkit.command.Command import org.bukkit.command.CommandSender +import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.MsgCommand +import xyz.alexcrea.cuanvil.util.ComponentUtil.send class HelpExecutor : CASubCommand { + override fun description(): MessageLike { + return MsgCommand.HELP_DESCRIPTION + } + lateinit var commands: ImmutableMap override fun executeCommand( sender: CommandSender, cmd: Command, cmdstr: String, - args: Array + args: Array, ): Boolean { + var text = MsgCommand.HELP_HEADER.formatted() + for((key, cmd) in commands) { + if(!cmd.allowed(sender)) continue - val stb = StringBuilder("List of available commands:") - for ((key, cmd) in commands) { - if (!cmd.allowed(sender)) continue - - stb.append("\n- $key: ").append(cmd.description()) + text = text.appendNewline() + .append(Component.text("- $key: ")) + .append(cmd.description().formatted()) } - sender.sendMessage(stb.toString()) - + text.send(sender) return true } @@ -34,12 +43,8 @@ class HelpExecutor : CASubCommand { override fun tabCompleter( sender: CommandSender, args: Array, - list: MutableList + list: MutableList, ) { } - override fun description(): String { - return "Help command" - } - } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt index bc9a80be..f9d91ace 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt @@ -9,29 +9,35 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.gui.config.global.* import xyz.alexcrea.cuanvil.lang.Lang +import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.update.UpdateHandler class ReloadExecutor : CASubCommand { + override fun description(): MessageLike { + return MsgCommand.RELOAD_DESCRIPTION + } + override fun executeCommand( sender: CommandSender, cmd: Command, cmdstr: String, - args: Array + args: Array, ): Boolean { - if (!allowed(sender)) { - sender.sendMessage("§cYou do not have permission to reload the config") + if(!allowed(sender)) { + MsgCommand.SHARED_NO_PERMISSION.send(sender) return false } - sender.sendMessage("§eReloading config...") + MsgCommand.RELOAD_START.send(sender) val hardfail = args.isNotEmpty() && ("hard".equals(args[0], true)) val commandSuccess = commandBody(hardfail) - if (commandSuccess) { - sender.sendMessage("§aConfig reloaded !") + if(commandSuccess) { + MsgCommand.RELOAD_SUCCESS.send(sender) } else { - sender.sendMessage("§cConfig was not able to be reloaded...") - if (hardfail) { - sender.sendMessage("§4Hard fail, plugin disabled") + MsgCommand.RELOAD_FAIL.send(sender) + if(hardfail) { + MsgCommand.RELOAD_HARD_FAIL.send(sender) } } return commandSuccess @@ -44,20 +50,16 @@ class ReloadExecutor : CASubCommand { override fun tabCompleter( sender: CommandSender, args: Array, - list: MutableList + list: MutableList, ) { } - override fun description(): String { - return "Reload the configuration of this plugin" - } - /** * Execute the command, return true if success or false otherwise */ private fun commandBody(hardfail: Boolean): Boolean { try { - if (!ConfigHolder.reloadAllFromDisk(hardfail)) return false + if(!ConfigHolder.reloadAllFromDisk(hardfail)) return false // reload language config Lang.reload() @@ -83,7 +85,7 @@ class ReloadExecutor : CASubCommand { Bukkit.getServer().pluginManager.callEvent(configReadyEvent) return true - } catch (e: Exception) { + } catch(e: Exception) { e.printStackTrace() return false } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt index be4b8f41..53b3dce5 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt @@ -3,7 +3,7 @@ package xyz.alexcrea.cuanvil.lang import io.delilaheve.CustomAnvil import net.kyori.adventure.text.Component import org.bukkit.command.CommandSender -import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.sendPaperMessage +import xyz.alexcrea.cuanvil.util.ComponentUtil.send import xyz.alexcrea.cuanvil.util.MiniMessageUtil import java.util.logging.Level import kotlin.math.min @@ -13,18 +13,28 @@ interface MessageLike { fun log(vararg params: Any) fun send(destination: CommandSender, vararg params: Any) + + fun unformatted(vararg params: Any): String + + fun formatted(vararg params: Any): Component + + fun legacy(vararg params: Any): String { + val formated = formatted(*params) + return MiniMessageUtil.legacy_mm.serialize(formated) + } } enum class MessageType { - DEFAULT, - WARNING, - ERROR, + DEFAULT, WARNING, ERROR, COMMAND, UI, } open class Message(val key: String, vararg val params: String) : MessageLike { protected fun replaceParameters(stb: StringBuilder, vararg values: Any) { // replace all placeholder thingy %key -> value + if(params.size != values.size) { + CustomAnvil.log("Wrong number of argument for parameter for key $key (${params.size}/${values.size})") + } for(i in 0 until min(params.size, values.size)) { val key = params[i] @@ -33,7 +43,7 @@ open class Message(val key: String, vararg val params: String) : MessageLike { var current = 0 while(true) { current = stb.indexOf('%', current) + 1 - if(current < 0 || current + key.length > stb.length) break // may be able to be removed if bound checked in startsWith ? + if(current <= 0 || current + key.length > stb.length) break // may be able to be removed if bound checked in startsWith ? if(!stb.startsWith(key, current, false)) continue stb.replace(current - 1, current + key.length, replacement) @@ -42,16 +52,16 @@ open class Message(val key: String, vararg val params: String) : MessageLike { } } - fun unformatted(vararg params: Any): String { + override fun unformatted(vararg params: Any): String { val translated = Lang.getTranslated(key) - if(params.isEmpty()) return translated + if(params.isEmpty() && this.params.isEmpty()) return translated val stb = StringBuilder(translated) replaceParameters(stb, *params) return stb.toString() } - fun formatted(vararg params: Any): Component { + override fun formatted(vararg params: Any): Component { val unformatted = unformatted(*params) return MiniMessageUtil.mm.deserialize(unformatted) @@ -64,9 +74,7 @@ open class Message(val key: String, vararg val params: String) : MessageLike { } override fun send(destination: CommandSender, vararg params: Any) { - val message = formatted(*params) - if(!destination.sendPaperMessage(message)) - destination.sendMessage(MiniMessageUtil.legacy_mm.serialize(message)) + formatted(*params).send(destination) } } @@ -95,6 +103,10 @@ class ErrorMessage(key: String, vararg params: String) : Message("error.$key", * } } + +class CommandMessage(key: String, vararg params: String) : Message("command.$key", *params) +class UIMessage(key: String, vararg params: String) : Message("ui.$key", *params) + class MultiLineMessage(type: MessageType, baseKey: String, count: Int, vararg params: String) : MessageLike { private val messages = ArrayList() @@ -111,6 +123,8 @@ class MultiLineMessage(type: MessageType, baseKey: String, count: Int, vararg pa MessageType.DEFAULT -> Message(key, *params) MessageType.WARNING -> WarningMessage(key, *params) MessageType.ERROR -> ErrorMessage(key, *params) + MessageType.COMMAND -> CommandMessage(key, *params) + MessageType.UI -> UIMessage(key, *params) } } @@ -125,4 +139,25 @@ class MultiLineMessage(type: MessageType, baseKey: String, count: Int, vararg pa message.send(destination, *params) } } + + override fun unformatted(vararg params: Any): String { + val stb = StringBuilder() + stb.append(messages[0].unformatted(*params)) + + for(i in 1 until messages.size) { + stb.append('\n').append(messages[i].unformatted(*params)) + } + + return stb.toString() + } + + override fun formatted(vararg params: Any): Component { + val component = messages[0].formatted(*params) + + for(i in 1 until messages.size) { + component.appendNewline().append(messages[i].formatted(*params)) + } + + return component + } } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt new file mode 100644 index 00000000..fb2d882b --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt @@ -0,0 +1,74 @@ +package xyz.alexcrea.cuanvil.lang + +import xyz.alexcrea.cuanvil.lang.CommandMessage as Message + +object MsgCommand { + + fun multiLine(basekey: String, count: Int): MultiLineMessage { + return MultiLineMessage( + MessageType.COMMAND, basekey, count + ) + } + + // Root + val ROOT_UNKNOWN_SUBCOMMAND = Message("root.warning.unknown-sub", "command") + val ROOT_ERROR_SUBCOMMAND = Message("root.error.generic") + + // Shared + val SHARED_NO_DIAG_PERM = Message("shared.no-diag-permission") + val SHARED_HOVER_COPY = Message("shared.hover-copy") + val SHARED_MISSING_SUBCOMMAND = Message("shared.warning.missing-subcmd", "example1", "example2") + val SHARED_UNKNOWN_SUB_COMMAND = Message("shared.unknown-subcmd", "command") + val SHARED_NO_PERMISSION = Message("shared.no-permission") + + // Debug + val DEBUG_DESCRIPTION = Message("debug.description") + val DEBUG_LOG_CLEARED = Message("debug.log-cleared") + val DEBUG_TOGGLED = Message("debug.toggled", "type") + val DEBUG_COPY = Message("debug.copy") + + val DEBUG_DATA_HEADER = Message("debug.data.header") + val DEBUG_DATA_LINE_COUNT = Message("debug.data.line-count", "count") + + val DEBUG_WARNING_UNSPECIFIED_TYPE = Message("debug.warning.unspecified-type") + val DEBUG_WARNING_INVALID_TYPE = Message("debug.warning.invalid-type", "type") + val DEBUG_WARNING_NO_LOG = Message("debug.warning.no-log", "command") + + // Diagnostic + val DIAGNOSTIC_DESCRIPTION = Message("diagnostic.description") + val DIAGNOSTIC_ERROR_GENERIC = Message("diagnostic.had-error") + val DIAGNOSTIC_COPY = Message("diagnostic.copy") + + // Config + val CONFIG_DESCRIPTION = Message("config.description") + val CONFIG_LEGACY_NAME_WARNING = Message("config.warning.legacy-name") + val CONFIG_FOLIA_ISSUE = multiLine("config.folia-issue", 5) + + val CONFIG_ENCHANTMENT_NO_IN_HAND = Message("config.enchantment.no_hand") + val CONFIG_ENCHANTMENT_NO_NAME = Message("config.enchantment.no_name", "name") + + val CONFIG_CANNOT_CONFIGURE_WARNING = Message("config.warning.cannot_configure") + + // Enchant + val ENCHANT_DESCRIPTION = Message("enchant.description") + val ENCHANT_REMOVE = Message("enchant.remove.", "name") + val ENCHANT_SET = Message("enchant.set.", "name", "level") + + val ENCHANT_MISSING_PARAMETER_WARNING = Message("enchant.warning.missing_parameter") + val ENCHANT_NOT_FOUND_WARNING = Message("enchant.warning.not_found", "path") + val ENCHANT_MALFORMED_NUMBER_WARNING = Message("enchant.warning.malformed_number", "num") + val ENCHANT_CANNOT_ENCHANT_WARNING = Message("enchant.warning.cannot_enchant") + + // Help + val HELP_DESCRIPTION = Message("help.description") + val HELP_HEADER = Message("help.header") + + // Reload + val RELOAD_DESCRIPTION = Message("reload.description") + val RELOAD_START = Message("reload.start") + val RELOAD_SUCCESS = Message("reload.success") + val RELOAD_FAIL = Message("reload.fail") + val RELOAD_HARD_FAIL = Message("reload.hard-fail") + +} + diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt new file mode 100644 index 00000000..bb1c807b --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt @@ -0,0 +1,6 @@ +package xyz.alexcrea.cuanvil.lang + +object MsgUI { + + +} \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt index aa7af304..f58dd814 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt @@ -1,17 +1,26 @@ package xyz.alexcrea.cuanvil.lang +import xyz.alexcrea.cuanvil.lang.WarningMessage as Message + object MsgWarning { + fun multiLine(basekey: String, count: Int): MultiLineMessage { + return MultiLineMessage( + MessageType.WARNING, + basekey, + count + ) + } + /* - * --------------- - * Load and reload - * --------------- + * ----------------- + * Load and reload + * ----------------- */ - val LOAD_UPDATE_AVAILABLE = WarningMessage("load.update.available", "version") - - val LOAD_LEGACY_OLD_NAME = MultiLineMessage(MessageType.WARNING, "load.legacy.old-name", 2) - val LOAD_LEGACY_SPIGOT = MultiLineMessage(MessageType.WARNING, "load.legacy.spigot", 2) - val LOAD_LEGACY_SPIGOT_OLD = MultiLineMessage(MessageType.WARNING, "load.legacy.spigot", 2) + val LOAD_UPDATE_AVAILABLE = Message("load.update.available", "version") + val LOAD_LEGACY_OLD_NAME = multiLine("load.legacy.old-name", 2) + val LOAD_LEGACY_SPIGOT = multiLine("load.legacy.spigot", 2) + val LOAD_LEGACY_SPIGOT_OLD = multiLine("load.legacy.spigot", 2) } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt new file mode 100644 index 00000000..884675be --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt @@ -0,0 +1,14 @@ +package xyz.alexcrea.cuanvil.util + +import net.kyori.adventure.text.Component +import org.bukkit.command.CommandSender +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.sendPaperMessage + +object ComponentUtil { + + fun Component.send(destination: CommandSender) { + if(!destination.sendPaperMessage(this)) + destination.sendMessage(MiniMessageUtil.legacy_mm.serialize(this)) + } + +} \ No newline at end of file diff --git a/src/main/resources/lang/en.yml b/src/main/resources/lang/en.yml index b0c96009..cfd9ce17 100644 --- a/src/main/resources/lang/en.yml +++ b/src/main/resources/lang/en.yml @@ -32,8 +32,9 @@ error: command: shared: no-diag-permission: "You do not have permission to diagnostic this server" - # I try to avoid using & for color but this is for a bungee text component - hover-copy: "§7Click to copy" + hover-copy: "Click to copy" + unknown-subcmd: "Unknown subcommand %command" + no-permission: "No permission to execute this command" warning: missing-subcmd: "Need to specify a subcommand. for example %example1 or %example2" root: @@ -45,21 +46,47 @@ command: description: "Used to toggle debug logs and retrieve them" log-cleared: "Log Cleared" toggled: "Debug toggled to %type" - # I try to avoid using & for color but this is for a bungee text component - copy: "§aClick to copy log data" + copy: "Click to copy log data" data: header: "Debug Log data:" line-count: "Found %count lines" warning: unspecified-type: "Need to specify which type of debug to toggle: \"default\" or \"verbose\"" + invalid-type: "Invalid debug type \"%type\"" no-log: "No log to show ? make sure you tried with debug log toggled (%command)" diagnostic: description: "Basic diagnostic of this plugin" had-error: "There was an error running the diagnostic" - # I try to avoid using & for color but this is for a bungee text component - copy: "§aClick to copy diagnostic data" + copy: "Click to copy diagnostic data" config: description: "Used to edit the configuration of the plugin" - + folia-issue: + 1: "It look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia." + 2: "It is may come in a future version." + 3: "" + 4: "Currently you need to edit manually the config or copy from another server (spigot or better)" + 5: "Then /ca reload after config file is edited" + enchantment: + no_hand: "No enchantment found in the item you are holding" + no_name: "No enchantment found with the name %name" warning: - legacy-name: "/ca gui has been moved to /ca config" \ No newline at end of file + legacy-name: "/ca gui has been moved to /ca config" + cannot_configure: "Cannot configure the item in hand" + enchant: + description: "Allows to set enchantment to holden item" + warning: + missing_parameter: "Missing enchantment parameter" + not_found: "Enchantment not found: %path" + malformed_number: "Invalid number: %num" + cannot_enchant: "Cannot enchant this item" + removed: "%name removed" + set: "%name set to level %level" + help: + description: "Help command" + header: "List of available commands:" + reload: + description: "Reload the configuration of this plugin" + start: "Reloading config..." + success: "Config reloaded !" + fail: "Config was not able to be reloaded..." + hard-fail: "Hard fail, plugin disabled" \ No newline at end of file From 8a00cc1f929afe510838b6ab9818f27f210a3060 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sat, 15 Aug 2026 16:15:49 +0200 Subject: [PATCH 12/14] rework multiline --- .../alexcrea/cuanvil/anvil/AnvilMergeLogic.kt | 4 +- .../alexcrea/cuanvil/command/CASubCommand.kt | 4 +- .../cuanvil/command/DebugToggleExecutor.kt | 8 +- .../cuanvil/command/DiagnosticExecutor.kt | 4 +- .../cuanvil/command/EditConfigExecutor.kt | 4 +- .../cuanvil/command/EnchantExecutor.kt | 4 +- .../alexcrea/cuanvil/command/HelpExecutor.kt | 7 +- .../cuanvil/command/ReloadExecutor.kt | 4 +- .../kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt | 8 + .../xyz/alexcrea/cuanvil/lang/Language.kt | 5 + .../xyz/alexcrea/cuanvil/lang/Message.kt | 170 ++++++++---------- .../xyz/alexcrea/cuanvil/lang/MsgCommand.kt | 8 +- .../xyz/alexcrea/cuanvil/lang/MsgWarning.kt | 14 +- .../cuanvil/listener/AnvilResultListener.kt | 3 +- .../alexcrea/cuanvil/util/ComponentUtil.kt | 21 ++- .../alexcrea/cuanvil/util/MiniMessageUtil.kt | 5 - .../cuanvil/util/anvil/AnvilColorUtil.kt | 13 +- .../cuanvil/util/anvil/AnvilLoreEditUtil.kt | 5 +- 18 files changed, 147 insertions(+), 144 deletions(-) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt index a1c411a3..7d1b745c 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt @@ -22,6 +22,8 @@ import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog import xyz.alexcrea.cuanvil.enchant.CAEnchantment import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe import xyz.alexcrea.cuanvil.util.CasedStringUtil +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializeLegacy +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir import xyz.alexcrea.cuanvil.util.MiniMessageUtil @@ -151,7 +153,7 @@ object AnvilMergeLogic { ) if (component != null) { - renameText = MiniMessageUtil.legacy_mm.serialize(component) + renameText = component.serializeLegacy() sumCost += ConfigOptions.useOfColorCost useColor = true diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt index ec893559..e8d7f825 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/CASubCommand.kt @@ -3,7 +3,7 @@ package xyz.alexcrea.cuanvil.command import org.bukkit.command.Command import org.bukkit.command.CommandSender import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry -import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.Message interface CASubCommand { @@ -22,7 +22,7 @@ interface CASubCommand { list: MutableList ) - fun description(): MessageLike + fun description(): Message fun allEnchantmentsByName(): Collection { val names = mutableSetOf() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt index c0c4862f..4ed7e0be 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt @@ -9,13 +9,13 @@ import net.md_5.bungee.api.chat.hover.content.Text import org.bukkit.command.Command import org.bukkit.command.CommandSender import org.bukkit.entity.Player -import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.Message import xyz.alexcrea.cuanvil.lang.MsgCommand -import xyz.alexcrea.cuanvil.util.MiniMessageUtil +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain class DebugToggleExecutor : CASubCommand { - override fun description(): MessageLike { + override fun description(): Message { return MsgCommand.DEBUG_DESCRIPTION } @@ -88,7 +88,7 @@ class DebugToggleExecutor : CASubCommand { val stb = StringBuilder(MsgCommand.DEBUG_DATA_HEADER.unformatted()).append(' ') stb.append(MsgCommand.DEBUG_DATA_LINE_COUNT.unformatted(CustomAnvil.debugStorageQueue.size)) for(log in CustomAnvil.debugStorageQueue) { - stb.append('\n').append(MiniMessageUtil.plain_text_mm.serialize(log)) + stb.append('\n').append(log.serializePlain()) } if(sender is Player) { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt index b015fde0..0644a6fa 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DiagnosticExecutor.kt @@ -24,7 +24,7 @@ import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.packet.NoPacketManager import xyz.alexcrea.cuanvil.dependency.packet.ProtocoLibWrapper import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry -import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.Message import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener import xyz.alexcrea.cuanvil.util.MetricsUtil @@ -214,7 +214,7 @@ class DiagnosticExecutor : CASubCommand { return this.name + " v" + this.description.version } - override fun description(): MessageLike { + override fun description(): Message { return MsgCommand.DIAGNOSTIC_DESCRIPTION } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt index 0fc522d2..50bd186f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt @@ -11,7 +11,7 @@ import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.config.global.EnchantConfigGui import xyz.alexcrea.cuanvil.gui.config.global.ItemConfigGui import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions -import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.Message import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.util.MaterialUtil.customType import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir @@ -22,7 +22,7 @@ class EditConfigExecutor : CASubCommand { return sender.hasPermission(CustomAnvil.editConfigPermission) } - override fun description(): MessageLike { + override fun description(): Message { return MsgCommand.CONFIG_DESCRIPTION } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EnchantExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EnchantExecutor.kt index 46b256f3..d39acb3b 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EnchantExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EnchantExecutor.kt @@ -10,7 +10,7 @@ import org.bukkit.command.CommandSender import org.bukkit.entity.HumanEntity import xyz.alexcrea.cuanvil.api.EnchantmentApi import xyz.alexcrea.cuanvil.enchant.CAEnchantment -import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.Message import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir @@ -21,7 +21,7 @@ class EnchantExecutor : CASubCommand { return sender.hasPermission(CustomAnvil.giveEnchantmentPermission) } - override fun description(): MessageLike { + override fun description(): Message { return MsgCommand.ENCHANT_DESCRIPTION } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt index 1f669ac5..4d5c23de 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/HelpExecutor.kt @@ -2,16 +2,15 @@ package xyz.alexcrea.cuanvil.command import com.google.common.collect.ImmutableMap import net.kyori.adventure.text.Component -import net.kyori.adventure.text.TextComponent import org.bukkit.command.Command import org.bukkit.command.CommandSender -import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.Message import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.util.ComponentUtil.send class HelpExecutor : CASubCommand { - override fun description(): MessageLike { + override fun description(): Message { return MsgCommand.HELP_DESCRIPTION } @@ -23,7 +22,7 @@ class HelpExecutor : CASubCommand { cmdstr: String, args: Array, ): Boolean { - var text = MsgCommand.HELP_HEADER.formatted() + var text = MsgCommand.HELP_HEADER.formatted().first() for((key, cmd) in commands) { if(!cmd.allowed(sender)) continue diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt index f9d91ace..f5b92b62 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/ReloadExecutor.kt @@ -9,13 +9,13 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.gui.config.global.* import xyz.alexcrea.cuanvil.lang.Lang -import xyz.alexcrea.cuanvil.lang.MessageLike +import xyz.alexcrea.cuanvil.lang.Message import xyz.alexcrea.cuanvil.lang.MsgCommand import xyz.alexcrea.cuanvil.update.UpdateHandler class ReloadExecutor : CASubCommand { - override fun description(): MessageLike { + override fun description(): Message { return MsgCommand.RELOAD_DESCRIPTION } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt index db8a2b29..18be75f6 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Lang.kt @@ -1,6 +1,7 @@ package xyz.alexcrea.cuanvil.lang import io.delilaheve.CustomAnvil +import org.bukkit.configuration.ConfigurationSection import xyz.alexcrea.cuanvil.config.ConfigHolder object Lang { @@ -27,6 +28,13 @@ object Lang { return default.get(key) ?: key } + fun getSection(key: String): ConfigurationSection? { + val value = lang.getSection(key) + if(value != null) return value + + return default.getSection(key) + } + /* * Config Options & get */ diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt index d6054ba2..0a008bf0 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Language.kt @@ -1,6 +1,7 @@ package xyz.alexcrea.cuanvil.lang import io.delilaheve.CustomAnvil +import org.bukkit.configuration.ConfigurationSection import org.bukkit.configuration.file.FileConfiguration import org.bukkit.configuration.file.YamlConfiguration import java.io.File @@ -50,6 +51,10 @@ class Language(private val id: String, private val default: Boolean = false) { return conf.getString(key) } + fun getSection(key: String): ConfigurationSection? { + return conf.getConfigurationSection(key) + } + val name: String get() = conf.getString("name", id)!! } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt index 53b3dce5..b7f38551 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt @@ -3,32 +3,15 @@ package xyz.alexcrea.cuanvil.lang import io.delilaheve.CustomAnvil import net.kyori.adventure.text.Component import org.bukkit.command.CommandSender +import org.bukkit.configuration.ConfigurationSection import xyz.alexcrea.cuanvil.util.ComponentUtil.send +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializeLegacy +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain import xyz.alexcrea.cuanvil.util.MiniMessageUtil import java.util.logging.Level import kotlin.math.min -interface MessageLike { - - fun log(vararg params: Any) - - fun send(destination: CommandSender, vararg params: Any) - - fun unformatted(vararg params: Any): String - - fun formatted(vararg params: Any): Component - - fun legacy(vararg params: Any): String { - val formated = formatted(*params) - return MiniMessageUtil.legacy_mm.serialize(formated) - } -} - -enum class MessageType { - DEFAULT, WARNING, ERROR, COMMAND, UI, -} - -open class Message(val key: String, vararg val params: String) : MessageLike { +open class Message(val key: String, vararg val params: String) { protected fun replaceParameters(stb: StringBuilder, vararg values: Any) { // replace all placeholder thingy %key -> value @@ -52,7 +35,7 @@ open class Message(val key: String, vararg val params: String) : MessageLike { } } - override fun unformatted(vararg params: Any): String { + private fun unformattedMonoline(vararg params: Any): String { val translated = Lang.getTranslated(key) if(params.isEmpty() && this.params.isEmpty()) return translated @@ -61,19 +44,71 @@ open class Message(val key: String, vararg val params: String) : MessageLike { return stb.toString() } - override fun formatted(vararg params: Any): Component { - val unformatted = unformatted(*params) + private fun unformattedMultiline(section: ConfigurationSection, vararg params: Any): String { + val stb = StringBuilder() - return MiniMessageUtil.mm.deserialize(unformatted) + for(key in section.getKeys(false)) { + if(!section.isString(key)) continue + if(!stb.isEmpty()) stb.append('\n') + + stb.append(section.getString(key)) + } + + replaceParameters(stb, *params) + return stb.toString() } - override fun log(vararg params: Any) { - val text = unformatted(*params) + fun unformatted(vararg params: Any): String { + val section = Lang.getSection(key) + if(section != null) return unformattedMultiline(section, *params) - CustomAnvil.instance.logger.info(text) + return unformattedMonoline(*params) } - override fun send(destination: CommandSender, vararg params: Any) { + private fun formattedMultiline(section: ConfigurationSection, vararg params: Any): List { + val result = ArrayList() + + for(key in section.getKeys(false)) { + if(!section.isString(key)) continue + + val stb = StringBuilder(section.getString(key)) + replaceParameters(stb, *params) + + result.add(MiniMessageUtil.mm.deserialize(stb.toString())) + } + + return result + } + + fun formatted(vararg params: Any): List { + val section = Lang.getSection(key) + if(section != null) return formattedMultiline(section, *params) + + val translated = unformattedMonoline(key, *params) + + return listOf(MiniMessageUtil.mm.deserialize(translated)) + } + + fun legacy(vararg params: Any): String { + val formated = formatted(*params) + + val stb = StringBuilder() + for(component in formated) { + if(!stb.isEmpty()) stb.append('\n') + stb.append(component.serializeLegacy()) + } + return stb.toString() + } + + open fun log(vararg params: Any) { + val texts = formatted(*params) + + for(component in texts) { + CustomAnvil.instance.logger.info(component.serializePlain()) + } + } + + open fun send(destination: CommandSender, vararg params: Any) { formatted(*params).send(destination) } } @@ -81,83 +116,32 @@ open class Message(val key: String, vararg val params: String) : MessageLike { class WarningMessage(key: String, vararg params: String) : Message("warning.$key", *params) { override fun log(vararg params: Any) { - val text = unformatted(*params) + val texts = formatted(*params) - CustomAnvil.instance.logger.warning(text) + for(component in texts) { + CustomAnvil.instance.logger.warning(component.serializePlain()) + } } - } class ErrorMessage(key: String, vararg params: String) : Message("error.$key", *params) { override fun log(vararg params: Any) { - val text = unformatted(*params) + val texts = formatted(*params) - CustomAnvil.logError(text) + for(component in texts) { + CustomAnvil.logError(component.serializePlain()) + } } fun log(e: Throwable, vararg params: Any, level: Level = Level.SEVERE, track: Boolean = true) { - val text = unformatted(*params) + val texts = formatted(*params) - CustomAnvil.logError(text, e, track, level) + for(component in texts) { + CustomAnvil.logError(component.serializePlain(), e, track, level) + } } } - class CommandMessage(key: String, vararg params: String) : Message("command.$key", *params) -class UIMessage(key: String, vararg params: String) : Message("ui.$key", *params) - -class MultiLineMessage(type: MessageType, baseKey: String, count: Int, vararg params: String) : MessageLike { - - private val messages = ArrayList() - - init { - for(i in 1 until count + 1) { - val message = createNew(type, "$baseKey.$i", *params) - messages.add(message) - } - } - - private fun createNew(type: MessageType, key: String, vararg params: String): MessageLike { - return when(type) { - MessageType.DEFAULT -> Message(key, *params) - MessageType.WARNING -> WarningMessage(key, *params) - MessageType.ERROR -> ErrorMessage(key, *params) - MessageType.COMMAND -> CommandMessage(key, *params) - MessageType.UI -> UIMessage(key, *params) - } - } - - override fun log(vararg params: Any) { - for(message in messages) { - message.log(*params) - } - } - - override fun send(destination: CommandSender, vararg params: Any) { - for(message in messages) { - message.send(destination, *params) - } - } - - override fun unformatted(vararg params: Any): String { - val stb = StringBuilder() - stb.append(messages[0].unformatted(*params)) - - for(i in 1 until messages.size) { - stb.append('\n').append(messages[i].unformatted(*params)) - } - - return stb.toString() - } - - override fun formatted(vararg params: Any): Component { - val component = messages[0].formatted(*params) - - for(i in 1 until messages.size) { - component.appendNewline().append(messages[i].formatted(*params)) - } - - return component - } -} \ No newline at end of file +class UIMessage(key: String, vararg params: String) : Message("ui.$key", *params) \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt index fb2d882b..2eed326b 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgCommand.kt @@ -4,12 +4,6 @@ import xyz.alexcrea.cuanvil.lang.CommandMessage as Message object MsgCommand { - fun multiLine(basekey: String, count: Int): MultiLineMessage { - return MultiLineMessage( - MessageType.COMMAND, basekey, count - ) - } - // Root val ROOT_UNKNOWN_SUBCOMMAND = Message("root.warning.unknown-sub", "command") val ROOT_ERROR_SUBCOMMAND = Message("root.error.generic") @@ -42,7 +36,7 @@ object MsgCommand { // Config val CONFIG_DESCRIPTION = Message("config.description") val CONFIG_LEGACY_NAME_WARNING = Message("config.warning.legacy-name") - val CONFIG_FOLIA_ISSUE = multiLine("config.folia-issue", 5) + val CONFIG_FOLIA_ISSUE = Message("config.folia-issue") val CONFIG_ENCHANTMENT_NO_IN_HAND = Message("config.enchantment.no_hand") val CONFIG_ENCHANTMENT_NO_NAME = Message("config.enchantment.no_name", "name") diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt index f58dd814..90eafa56 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/MsgWarning.kt @@ -4,14 +4,6 @@ import xyz.alexcrea.cuanvil.lang.WarningMessage as Message object MsgWarning { - fun multiLine(basekey: String, count: Int): MultiLineMessage { - return MultiLineMessage( - MessageType.WARNING, - basekey, - count - ) - } - /* * ----------------- * Load and reload @@ -19,8 +11,8 @@ object MsgWarning { */ val LOAD_UPDATE_AVAILABLE = Message("load.update.available", "version") - val LOAD_LEGACY_OLD_NAME = multiLine("load.legacy.old-name", 2) - val LOAD_LEGACY_SPIGOT = multiLine("load.legacy.spigot", 2) - val LOAD_LEGACY_SPIGOT_OLD = multiLine("load.legacy.spigot", 2) + val LOAD_LEGACY_OLD_NAME = Message("load.legacy.old-name") + val LOAD_LEGACY_SPIGOT = Message("load.legacy.spigot") + val LOAD_LEGACY_SPIGOT_OLD = Message("load.legacy.spigot-old") } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt index 386a920b..5f192c51 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt @@ -30,6 +30,7 @@ import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentDisplayName import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain import xyz.alexcrea.cuanvil.util.CustomRecipeUtil import xyz.alexcrea.cuanvil.util.MaterialUtil.isAir import xyz.alexcrea.cuanvil.util.MiniMessageUtil @@ -536,7 +537,7 @@ class AnvilResultListener : Listener { if (bookPage.isNotEmpty()) bookPage.append('\n') if (it == null) return@forEach - bookPage.append(MiniMessageUtil.plain_text_mm.serialize(it)) + bookPage.append(it.serializePlain()) } val resultPage = bookPage.toString() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt index 884675be..2d9ec351 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/ComponentUtil.kt @@ -8,7 +8,26 @@ object ComponentUtil { fun Component.send(destination: CommandSender) { if(!destination.sendPaperMessage(this)) - destination.sendMessage(MiniMessageUtil.legacy_mm.serialize(this)) + destination.sendMessage(this.serializeLegacy()) } + fun List.send(destination: CommandSender) { + for(component in this) + component.send(destination) + } + + fun Component.serializeMM(): String { + return MiniMessageUtil.mm.serialize(this) + } + fun Component.serializeMMColor(): String { + return MiniMessageUtil.color_only_mm.serialize(this) + } + fun Component.serializeLegacy(): String { + return MiniMessageUtil.legacy_mm.serialize(this) + } + fun Component.serializePlain(): String { + return MiniMessageUtil.plain_text_mm.serialize(this) + } + + } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt index c33cb9c5..6780049f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt @@ -25,9 +25,4 @@ object MiniMessageUtil { val legacy_mm = LegacyComponentSerializer.legacySection() val plain_text_mm = PlainTextComponentSerializer.plainText() - // Keeping track of this as most use of this can be replaced later on v2 with pure component alternative - fun fromLegacy(legacyText: String): TextComponent { - return legacy_mm.deserialize(legacyText) - } - } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilColorUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilColorUtil.kt index 9564b2e9..44ae8faf 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilColorUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilColorUtil.kt @@ -3,6 +3,9 @@ package xyz.alexcrea.cuanvil.util.anvil import io.delilaheve.util.ConfigOptions import net.kyori.adventure.text.Component import org.bukkit.permissions.Permissible +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializeLegacy +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializeMM +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain import xyz.alexcrea.cuanvil.util.MiniMessageUtil import java.util.regex.Matcher import java.util.regex.Pattern @@ -103,10 +106,10 @@ object AnvilColorUtil { var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr) if (permission.canUseMinimessage) { // we dance with formats here - val toMinimessage = MiniMessageUtil.mm.serialize(result) + val toMinimessage = result.serializeMM() val hackySolution = toMinimessage.replace("\\<", "<") val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution) - val asPlain = MiniMessageUtil.plain_text_mm.serialize(fromMinimessage) + val asPlain = fromMinimessage.serializePlain() if (previousStr != asPlain) { useColor = true @@ -145,8 +148,8 @@ object AnvilColorUtil { ): String? { if (!permission.allowed() || component == null) return null - val transformed = MiniMessageUtil.mm.serialize(component) - val plainTransform = MiniMessageUtil.plain_text_mm.serialize(component) + val transformed = component.serializeMM() + val plainTransform = component.serializePlain() if (transformed == plainTransform) return null if (permission.onlyMinimessage()) { return transformed @@ -154,7 +157,7 @@ object AnvilColorUtil { // smol dance so we transform the component that may contain other tag into only decoration & color for legacy val coloredMessage = MiniMessageUtil.color_only_mm.deserialize(transformed) - val legacyMessage = StringBuilder(MiniMessageUtil.legacy_mm.serialize(coloredMessage)) + val legacyMessage = StringBuilder(coloredMessage.serializeLegacy()) // Reverse hex pattern if (permission.canUseHexColor) { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilLoreEditUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilLoreEditUtil.kt index a021b468..ad827458 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilLoreEditUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilLoreEditUtil.kt @@ -10,6 +10,7 @@ import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.LoreEditResult import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentLore +import xyz.alexcrea.cuanvil.util.ComponentUtil.serializePlain import xyz.alexcrea.cuanvil.util.MiniMessageUtil import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil import xyz.alexcrea.cuanvil.util.config.LoreEditType @@ -320,7 +321,7 @@ object AnvilLoreEditUtil { hasUndidColor = true result = clearedLine } else { - result = MiniMessageUtil.plain_text_mm.serialize(line) + result = line.serializePlain() } lines[index] = MiniMessageUtil.plain_text_mm.deserialize(result) @@ -354,7 +355,7 @@ object AnvilLoreEditUtil { result = clearedLine } else { // Remove extra tags - result = MiniMessageUtil.plain_text_mm.serialize(coloredComponent) + result = coloredComponent.serializePlain() } line.set(MiniMessageUtil.plain_text_mm.deserialize(result)) From 6e61ac815ff95e17ad411c98bba010a51c64f06c Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sat, 15 Aug 2026 21:38:57 +0200 Subject: [PATCH 13/14] fix small translation issue --- .../kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt | 2 +- src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt index 4ed7e0be..5c7bfee6 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/DebugToggleExecutor.kt @@ -35,7 +35,7 @@ class DebugToggleExecutor : CASubCommand { } if(args.isEmpty()) { - MsgCommand.SHARED_MISSING_SUBCOMMAND.send(sender) + MsgCommand.SHARED_MISSING_SUBCOMMAND.send(sender, "\"toggle\"", "\"get\"") return true } when(args[0].lowercase()) { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt index b7f38551..9c1dd596 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/lang/Message.kt @@ -84,7 +84,7 @@ open class Message(val key: String, vararg val params: String) { val section = Lang.getSection(key) if(section != null) return formattedMultiline(section, *params) - val translated = unformattedMonoline(key, *params) + val translated = unformattedMonoline(*params) return listOf(MiniMessageUtil.mm.deserialize(translated)) } From fda211fe5b36f863bfb1db97f0934ac9780e3a9e Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 16 Aug 2026 07:26:08 +0200 Subject: [PATCH 14/14] progress on translation system --- .../gui/config/ask/ConfirmActionGui.java | 5 +++-- .../gui/config/ask/SelectItemTypeGui.java | 3 ++- .../list/MappedElementListConfigGui.java | 6 ++--- .../config/list/MappedGuiListConfigGui.java | 7 +++--- .../config/list/UnitRepairElementListGui.java | 5 +++-- .../elements/GroupConfigSubSettingGui.java | 3 ++- .../settings/MaterialSelectSettingGui.java | 3 ++- .../settings/WorkPenaltyTypeSettingGui.java | 3 ++- .../cuanvil/gui/util/GuiGlobalActions.java | 9 ++++---- .../cuanvil/command/CustomAnvilCommand.kt | 1 - .../cuanvil/command/EditConfigExecutor.kt | 4 ++-- .../cuanvil/dependency/DependencyManager.kt | 9 +++----- .../xyz/alexcrea/cuanvil/lang/Message.kt | 2 +- .../kotlin/xyz/alexcrea/cuanvil/lang/MsgUI.kt | 15 +++++++++++++ .../xyz/alexcrea/cuanvil/lang/MsgWarning.kt | 2 ++ src/main/resources/lang/en.yml | 22 ++++++++++++++++++- 16 files changed, 69 insertions(+), 30 deletions(-) diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java index 58396638..0b5a08e7 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/ConfirmActionGui.java @@ -11,6 +11,7 @@ import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.lang.MsgUI; import xyz.alexcrea.cuanvil.util.MetricsUtil; import java.util.Arrays; @@ -33,7 +34,7 @@ public class ConfirmActionGui extends AbstractAskGui { if (!player.hasPermission(CustomAnvil.editConfigPermission)) { player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); + MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player); return; } @@ -47,7 +48,7 @@ public class ConfirmActionGui extends AbstractAskGui { } if (!success) { - event.getWhoClicked().sendMessage("§cAction could not be completed. "); + MsgUI.INSTANCE.getCONFIRM_ACTION_FAILED().send(player); } backOnConfirm.show(player); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java index 66411bd4..f0369e6d 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/ask/SelectItemTypeGui.java @@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalItems; import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant; +import xyz.alexcrea.cuanvil.lang.MsgUI; import xyz.alexcrea.cuanvil.util.MaterialUtil; import java.util.Arrays; @@ -36,7 +37,7 @@ public class SelectItemTypeGui extends AbstractAskGui { if (!player.hasPermission(CustomAnvil.editConfigPermission)) { player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); + MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player); return; } diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java index 9b6c6100..7bfffdf8 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedElementListConfigGui.java @@ -10,6 +10,7 @@ import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.config.MainConfigGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; +import xyz.alexcrea.cuanvil.lang.MsgUI; import java.util.Arrays; import java.util.HashMap; @@ -52,13 +53,12 @@ public abstract class MappedElementListConfigGui extends ElementListConfig // check permission if (!player.hasPermission(CustomAnvil.editConfigPermission)) { player.closeInventory(); - player.sendMessage(GuiGlobalActions.NO_EDIT_PERM); + MsgUI.INSTANCE.getSHARED_CONFIG_NO_EDIT_PERM().send(player); return; } player.closeInventory(); - player.sendMessage("§eWrite the " + genericDisplayedName() + " name you want to create in the chat.\n" + - "§eOr write §ccancel §eto go back to " + genericDisplayedName() + " config menu"); + MsgUI.INSTANCE.getELEMENT_LIST_INSTRUCTION_NEW().send(player, genericDisplayedName()); CustomAnvil.Companion.getChatListener().setListenedCallback(player, prepareCreateItemConsumer(player)); diff --git a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java index 8180694e..d25d6e72 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java +++ b/src/main/java/xyz/alexcrea/cuanvil/gui/config/list/MappedGuiListConfigGui.java @@ -8,6 +8,7 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.jetbrains.annotations.NotNull; import xyz.alexcrea.cuanvil.gui.config.list.elements.ElementMappedToListGui; import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions; +import xyz.alexcrea.cuanvil.lang.MsgUI; import xyz.alexcrea.cuanvil.util.LazyValue; import java.util.Locale; @@ -69,13 +70,13 @@ public abstract class MappedGuiListConfigGuiReloading config..." success: "Config reloaded !" fail: "Config was not able to be reloaded..." - hard-fail: "Hard fail, plugin disabled" \ No newline at end of file + hard-fail: "Hard fail, plugin disabled" + +config-ui: + shared: + no-permission: "You do not have permission to edit the config" + confirm-action: + fail: "Action could not be completed." + element-list: + instruction-new: + 1: "Write the %type name you want to create in the chat." + 2: "Or write cancel to go back to %type config menu" + cancelled-new: "%type creation cancelled..." + duplicated-new: "Please enter a %type name that do not already exist..." + unit-repair: + element: + title: "Select item to be repaired." + description: + 1: "Click here with an item to set the item" + 2: "You like to be repaired by %name" + cannot-damage-new: "This item can't be damaged, so it can't be repaired." + same-type-new: "Item can't repair something of the same type." \ No newline at end of file