From 498a6b4409ee91ec6a987641db148c1d7844b973 Mon Sep 17 00:00:00 2001 From: Jonn Date: Wed, 5 Feb 2025 17:25:22 +0900 Subject: [PATCH 1/3] Move most lagstat strings to messages.properties. --- emulinker/src/main/i18n/messages.properties | 14 ++++++++++ .../controller/v086/action/GameChatAction.kt | 26 +++++++++++++------ .../org/emulinker/util/CustomUserStrings.kt | 3 +-- .../main/java/org/emulinker/util/EmuLang.kt | 18 ------------- .../main/java/org/emulinker/util/EmuUtil.kt | 25 +++++++++++++++++- 5 files changed, 57 insertions(+), 29 deletions(-) diff --git a/emulinker/src/main/i18n/messages.properties b/emulinker/src/main/i18n/messages.properties index 67532f7d7..69ab535ac 100644 --- a/emulinker/src/main/i18n/messages.properties +++ b/emulinker/src/main/i18n/messages.properties @@ -169,3 +169,17 @@ GameOwnerCommandAction.AutoFireChangeDeniedInGame=All players must drop the game KailleraServerImpl.TweetPendingAnnouncement=Posting a tweet in {0,number,integer} seconds. Type \"/stop\" to disable. KailleraServerImpl.TweetCloseMessage=(opponent found) KailleraServerImpl.CanceledPendingTweet=Canceled pending tweet. + +Lagstat.GameNotLaggy=The game does not appear to be significantly laggy. +Lagstat.LagstatReset=LagStat has been reset! +! Error message displayed if you run /lagstat too early after the game starts. +Lagstat.LagstatNotReady=Wait a minute or so after the game starts to run lagstat. +! Example: Total lag over the last 1.0m: 0.02s +Lagstat.TotalGameLagSummary=Total lag over the last {}: {} +! Example: Recommendation: nue should try playing on 2f. Enter 25 in the ping spoof field when joining. If lag continues, run /lagstat again. +Lagstat.LagReductionRecommendation=Recommendation: {} should try playing on {number,integer}f. Enter {number,integer} in the ping spoof field when joining. If lag continues, run /lagstat again. + +! Measurement of seconds. Examples: 0.03s, 1s +Time.SecondsAbbreviation={number}s +! Measurement of minutes. Examples: 0.5m, 1m +Time.MinutesAbbreviation={number}m diff --git a/emulinker/src/main/java/org/emulinker/kaillera/controller/v086/action/GameChatAction.kt b/emulinker/src/main/java/org/emulinker/kaillera/controller/v086/action/GameChatAction.kt index 7cb743348..064b1e04f 100644 --- a/emulinker/src/main/java/org/emulinker/kaillera/controller/v086/action/GameChatAction.kt +++ b/emulinker/src/main/java/org/emulinker/kaillera/controller/v086/action/GameChatAction.kt @@ -22,9 +22,11 @@ import org.emulinker.kaillera.model.event.GameChatEvent import org.emulinker.kaillera.model.exception.ActionException import org.emulinker.kaillera.model.exception.GameChatException import org.emulinker.kaillera.model.impl.KailleraGameImpl +import org.emulinker.util.EmuLang import org.emulinker.util.EmuLang.getStringOrNull import org.emulinker.util.EmuUtil.min import org.emulinker.util.EmuUtil.threadSleep +import org.emulinker.util.EmuUtil.toLocalizedString import org.emulinker.util.EmuUtil.toMillisDouble import org.emulinker.util.EmuUtil.toSecondDoublePrecisionString @@ -464,23 +466,26 @@ class GameChatAction( game.chat(clientHandler.user, message.message) // Note: This was duplicated from GameOwnerCommandAction. if (!game.startTimeout) { - game.announce("Wait a minute or so after the game starts to run lagstat.") + game.announce(EmuLang.getString("Lagstat.LagstatNotReady")) return } val lagstatDuration = min(flags.lagstatDuration, clock.now() - game.lastLagReset) val lagstatDurationAsString = if (lagstatDuration < 1.minutes) { - lagstatDuration.toString(SECONDS) + lagstatDuration.toLocalizedString(SECONDS) } else { - lagstatDuration.toString(MINUTES, 1) + lagstatDuration.toLocalizedString(MINUTES, 1) } val gameLag = (game.totalDriftNs - (game.totalDriftCache.getDelayedValue() ?: 0)) .nanoseconds .absoluteValue game.announce( - "Total lag over the last ${lagstatDurationAsString}: " + - gameLag.toSecondDoublePrecisionString() + EmuLang.getString( + "Lagstat.TotalGameLagSummary", + lagstatDurationAsString, + gameLag.toSecondDoublePrecisionString(), + ) ) game.announce( "Lag definitively caused by players: " + @@ -516,11 +521,16 @@ class GameChatAction( .milliseconds game.announce( - "Recommendation: ${laggiestPlayer.name} should try playing on $targetFrameDelay frames. Enter ${suggestedFakePing.toMillisDouble().roundToInt()} in the ping spoof field when joining. If lag continues, run /lagstat again." + EmuLang.getString( + "Lagstat.LagReductionRecommendation", + laggiestPlayer.name, + targetFrameDelay, + suggestedFakePing.toMillisDouble().roundToInt(), + ) ) } } else { - game.announce("The game does not appear to be significantly laggy.") + game.announce(EmuLang.getString("Lagstat.GameNotLaggy")) } } } else if (message.message == "/lagreset") { @@ -529,7 +539,7 @@ class GameChatAction( player.resetLag() } game.resetLag() - game.announce("LagStat has been reset!") + game.announce("Lagstat.LagstatReset") } else if ( message.message.startsWith("/fps ") && message.message.removePrefix("/fps ").toDoubleOrNull() != null && diff --git a/emulinker/src/main/java/org/emulinker/util/CustomUserStrings.kt b/emulinker/src/main/java/org/emulinker/util/CustomUserStrings.kt index 2b008b580..76b318b6a 100644 --- a/emulinker/src/main/java/org/emulinker/util/CustomUserStrings.kt +++ b/emulinker/src/main/java/org/emulinker/util/CustomUserStrings.kt @@ -2,13 +2,12 @@ package org.emulinker.util import java.lang.Exception import java.text.MessageFormat -import java.util.Locale import java.util.ResourceBundle object CustomUserStrings { private const val BUNDLE_NAME = "language" - private val RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME, Locale.ENGLISH) + private val RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME) /* public static void reload() diff --git a/emulinker/src/main/java/org/emulinker/util/EmuLang.kt b/emulinker/src/main/java/org/emulinker/util/EmuLang.kt index 569e81289..864d70cf5 100644 --- a/emulinker/src/main/java/org/emulinker/util/EmuLang.kt +++ b/emulinker/src/main/java/org/emulinker/util/EmuLang.kt @@ -13,24 +13,6 @@ object EmuLang { private val logger = FluentLogger.forEnclosingClass() - /* - public static void reload() - { - try - { - Class klass = RESOURCE_BUNDLE.getClass().getSuperclass(); - Field field = klass.getDeclaredField("cacheList"); - field.setAccessible(true); - sun.misc.SoftCache cache = (sun.misc.SoftCache)field.get(null); - cache.clear(); - } - catch(Exception e) - { - - } - } - */ - fun hasString(key: String): Boolean { if (RESOURCE_BUNDLE.containsKey(key)) { try { diff --git a/emulinker/src/main/java/org/emulinker/util/EmuUtil.kt b/emulinker/src/main/java/org/emulinker/util/EmuUtil.kt index bfe58a358..9cbadc935 100644 --- a/emulinker/src/main/java/org/emulinker/util/EmuUtil.kt +++ b/emulinker/src/main/java/org/emulinker/util/EmuUtil.kt @@ -18,6 +18,7 @@ import kotlin.system.measureNanoTime import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.minutes +import kotlin.time.DurationUnit import kotlin.time.DurationUnit.MINUTES import kotlin.time.DurationUnit.SECONDS import kotlinx.datetime.Instant @@ -304,6 +305,28 @@ object EmuUtil { ) } + /** + * Similar to [Duration.toString()] except localized to the language. + * + * For example: 5s in English and 5秒 in Japanese. + */ + fun Duration.toLocalizedString(unit: DurationUnit, decimals: Int = 0): String = + when (unit) { + DurationUnit.NANOSECONDS, + DurationUnit.MICROSECONDS, + DurationUnit.MILLISECONDS, + DurationUnit.HOURS, + DurationUnit.DAYS -> TODO("Unit $unit not yet supported") + SECONDS -> { + val number = this.toString(unit, decimals).removeSuffix("s") + EmuLang.getString("Time.SecondsAbbreviation", number) + } + MINUTES -> { + val number = this.toString(unit, decimals).removeSuffix("m") + EmuLang.getString("Time.MinutesAbbreviation", number) + } + } + // TODO(nue): Get rid of this after it's confirmed it can be safely removed. /** NOOP placeholder for a function that _used to_ call [Thread.sleep]. */ @Deprecated( @@ -327,5 +350,5 @@ object EmuUtil { this.inWholeNanoseconds / 1.milliseconds.inWholeNanoseconds.toDouble() fun Duration.toSecondDoublePrecisionString() = - if (this < 1.minutes) toString(SECONDS, 2) else toString(MINUTES, 1) + if (this < 1.minutes) toLocalizedString(SECONDS, 2) else toLocalizedString(MINUTES, 1) } From 88b0f95bfe543b190f3c2102a277eddcdddd8f81 Mon Sep 17 00:00:00 2001 From: Jonn Date: Wed, 5 Feb 2025 18:26:15 +0900 Subject: [PATCH 2/3] Fix localization issues --- .gitignore | 1 + .idea/encodings.xml | 3 +- emulinker/src/main/i18n/messages.properties | 10 ++--- .../controller/v086/action/GameChatAction.kt | 2 +- .../main/java/org/emulinker/util/EmuUtil.kt | 41 +++++++++++-------- 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 3d1ae53c9..eb1c2cabf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Compiled class file build/ emulinker/build/ +emulinker/bin/ target/ *.class diff --git a/.idea/encodings.xml b/.idea/encodings.xml index f6c9781f9..16912547e 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,8 +1,7 @@ - + - \ No newline at end of file diff --git a/emulinker/src/main/i18n/messages.properties b/emulinker/src/main/i18n/messages.properties index 69ab535ac..3f312a9de 100644 --- a/emulinker/src/main/i18n/messages.properties +++ b/emulinker/src/main/i18n/messages.properties @@ -171,15 +171,15 @@ KailleraServerImpl.TweetCloseMessage=(opponent found) KailleraServerImpl.CanceledPendingTweet=Canceled pending tweet. Lagstat.GameNotLaggy=The game does not appear to be significantly laggy. -Lagstat.LagstatReset=LagStat has been reset! +Lagstat.LagstatReset=LagStat has been reset\! ! Error message displayed if you run /lagstat too early after the game starts. Lagstat.LagstatNotReady=Wait a minute or so after the game starts to run lagstat. ! Example: Total lag over the last 1.0m: 0.02s -Lagstat.TotalGameLagSummary=Total lag over the last {}: {} +Lagstat.TotalGameLagSummary=Total lag over the last {0}\: {1} ! Example: Recommendation: nue should try playing on 2f. Enter 25 in the ping spoof field when joining. If lag continues, run /lagstat again. -Lagstat.LagReductionRecommendation=Recommendation: {} should try playing on {number,integer}f. Enter {number,integer} in the ping spoof field when joining. If lag continues, run /lagstat again. +Lagstat.LagReductionRecommendation=Recommendation\: {0} should try playing on {1,number,integer}f. Enter {2,number,integer} in the ping spoof field when joining. If lag continues, run /lagstat again. ! Measurement of seconds. Examples: 0.03s, 1s -Time.SecondsAbbreviation={number}s +Time.SecondsAbbreviation={0}s ! Measurement of minutes. Examples: 0.5m, 1m -Time.MinutesAbbreviation={number}m +Time.MinutesAbbreviation={0}m diff --git a/emulinker/src/main/java/org/emulinker/kaillera/controller/v086/action/GameChatAction.kt b/emulinker/src/main/java/org/emulinker/kaillera/controller/v086/action/GameChatAction.kt index 064b1e04f..7a0c03d25 100644 --- a/emulinker/src/main/java/org/emulinker/kaillera/controller/v086/action/GameChatAction.kt +++ b/emulinker/src/main/java/org/emulinker/kaillera/controller/v086/action/GameChatAction.kt @@ -539,7 +539,7 @@ class GameChatAction( player.resetLag() } game.resetLag() - game.announce("Lagstat.LagstatReset") + game.announce(EmuLang.getString("Lagstat.LagstatReset")) } else if ( message.message.startsWith("/fps ") && message.message.removePrefix("/fps ").toDoubleOrNull() != null && diff --git a/emulinker/src/main/java/org/emulinker/util/EmuUtil.kt b/emulinker/src/main/java/org/emulinker/util/EmuUtil.kt index 9cbadc935..7d51f1d13 100644 --- a/emulinker/src/main/java/org/emulinker/util/EmuUtil.kt +++ b/emulinker/src/main/java/org/emulinker/util/EmuUtil.kt @@ -19,8 +19,7 @@ import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.minutes import kotlin.time.DurationUnit -import kotlin.time.DurationUnit.MINUTES -import kotlin.time.DurationUnit.SECONDS +import kotlin.time.DurationUnit.* import kotlinx.datetime.Instant import kotlinx.datetime.TimeZone import kotlinx.datetime.format.DateTimeComponents @@ -310,22 +309,32 @@ object EmuUtil { * * For example: 5s in English and 5秒 in Japanese. */ - fun Duration.toLocalizedString(unit: DurationUnit, decimals: Int = 0): String = - when (unit) { - DurationUnit.NANOSECONDS, - DurationUnit.MICROSECONDS, - DurationUnit.MILLISECONDS, - DurationUnit.HOURS, - DurationUnit.DAYS -> TODO("Unit $unit not yet supported") - SECONDS -> { - val number = this.toString(unit, decimals).removeSuffix("s") - EmuLang.getString("Time.SecondsAbbreviation", number) + fun Duration.toLocalizedString(unit: DurationUnit, decimals: Int = 0): String { + val unitSuffix = + when (unit) { + NANOSECONDS -> "ns" + MICROSECONDS -> "us" + MILLISECONDS -> "ms" + SECONDS -> "s" + MINUTES -> "m" + HOURS -> "h" + DAYS -> "d" } - MINUTES -> { - val number = this.toString(unit, decimals).removeSuffix("m") - EmuLang.getString("Time.MinutesAbbreviation", number) + + val i18nTemplate = + when (unit) { + NANOSECONDS, + MICROSECONDS, + MILLISECONDS, + HOURS, + DAYS -> TODO("Unit $unit not yet supported") + SECONDS -> "Time.SecondsAbbreviation" + MINUTES -> "Time.MinutesAbbreviation" } - } + + val number = this.toString(unit, decimals).removeSuffix(unitSuffix) + return EmuLang.getString(i18nTemplate, number) + } // TODO(nue): Get rid of this after it's confirmed it can be safely removed. /** NOOP placeholder for a function that _used to_ call [Thread.sleep]. */ From ed66cb2044be9f426291f7f419c21b71e1977659 Mon Sep 17 00:00:00 2001 From: Jonn Date: Wed, 5 Feb 2025 18:36:35 +0900 Subject: [PATCH 3/3] Fix formatting issue --- emulinker/src/main/i18n/messages_ja.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/emulinker/src/main/i18n/messages_ja.properties b/emulinker/src/main/i18n/messages_ja.properties index 95ecc4588..ecf0661c8 100644 --- a/emulinker/src/main/i18n/messages_ja.properties +++ b/emulinker/src/main/i18n/messages_ja.properties @@ -175,11 +175,11 @@ Lagstat.LagstatReset=LagStat has been reset\! ! Error message displayed if you run /lagstat too early after the game starts. Lagstat.LagstatNotReady=Wait a minute or so after the game starts to run lagstat. ! Example: Total lag over the last 1.0m: 0.02s -Lagstat.TotalGameLagSummary=Total lag over the last {}\: {} +Lagstat.TotalGameLagSummary=Total lag over the last {0}\: {1} ! Example: Recommendation: nue should try playing on 2f. Enter 25 in the ping spoof field when joining. If lag continues, run /lagstat again. -Lagstat.LagReductionRecommendation=Recommendation\: {} should try playing on {number,integer}f. Enter {number,integer} in the ping spoof field when joining. If lag continues, run /lagstat again. +Lagstat.LagReductionRecommendation=Recommendation\: {0} should try playing on {1,number,integer}f. Enter {2,number,integer} in the ping spoof field when joining. If lag continues, run /lagstat again. ! Measurement of seconds. Examples: 0.03s, 1s -Time.SecondsAbbreviation={number}s +Time.SecondsAbbreviation={0}s ! Measurement of minutes. Examples: 0.5m, 1m -Time.MinutesAbbreviation={number}m +Time.MinutesAbbreviation={0}m