From e04cfaaf938d4a933761d5cf84c54ffa303cc6f5 Mon Sep 17 00:00:00 2001 From: JFronny Date: Fri, 28 Jul 2023 14:57:14 +0200 Subject: [PATCH] fix: support disabling Advanced.async on server --- .../gitlab/jfronny/googlechat/GoogleChat.java | 5 +- .../googlechat/server/GoogleChatServer.java | 56 ++++++++++--------- .../server/TranslatableContainer.java | 32 +++++++++++ 3 files changed, 66 insertions(+), 27 deletions(-) create mode 100644 src/main/java/io/gitlab/jfronny/googlechat/server/TranslatableContainer.java diff --git a/src/main/java/io/gitlab/jfronny/googlechat/GoogleChat.java b/src/main/java/io/gitlab/jfronny/googlechat/GoogleChat.java index b8975a3..dd7b81d 100644 --- a/src/main/java/io/gitlab/jfronny/googlechat/GoogleChat.java +++ b/src/main/java/io/gitlab/jfronny/googlechat/GoogleChat.java @@ -4,7 +4,9 @@ import io.gitlab.jfronny.commons.cache.FixedSizeMap; import io.gitlab.jfronny.commons.log.Logger; import io.gitlab.jfronny.libjf.translate.api.Language; import io.gitlab.jfronny.libjf.translate.api.TranslateService; +import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.text.*; import java.util.*; @@ -15,6 +17,7 @@ public class GoogleChat implements ModInitializer { public static final String MOD_ID = "google-chat"; public static final Logger LOGGER = Logger.forName(MOD_ID); public static TranslateService TRANSLATE_SERVICE; + private static final boolean IS_SERVER = FabricLoader.getInstance().getEnvironmentType() == EnvType.SERVER; private static final Map s2ct = new FixedSizeMap<>(GoogleChatConfig.Advanced.cacheSize); private static final Map c2st = new FixedSizeMap<>(GoogleChatConfig.Advanced.cacheSize); @@ -146,7 +149,7 @@ public class GoogleChat implements ModInitializer { } private static V computeIfAbsent2(Map map, K key, Function compute) { - if (!GoogleChatConfig.Advanced.async) return map.computeIfAbsent(key, compute); + if (!GoogleChatConfig.Advanced.async && !IS_SERVER) return map.computeIfAbsent(key, compute); synchronized (map) { if (map.containsKey(key)) return map.get(key); V value = compute.apply(key); diff --git a/src/main/java/io/gitlab/jfronny/googlechat/server/GoogleChatServer.java b/src/main/java/io/gitlab/jfronny/googlechat/server/GoogleChatServer.java index 78a46f8..ffc5fb0 100644 --- a/src/main/java/io/gitlab/jfronny/googlechat/server/GoogleChatServer.java +++ b/src/main/java/io/gitlab/jfronny/googlechat/server/GoogleChatServer.java @@ -1,44 +1,48 @@ package io.gitlab.jfronny.googlechat.server; -import io.gitlab.jfronny.googlechat.*; +import io.gitlab.jfronny.googlechat.GoogleChatConfig; +import io.gitlab.jfronny.googlechat.TranslationDirection; import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.message.v1.ServerMessageDecoratorEvent; +import net.minecraft.network.message.MessageDecorator; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; import java.util.concurrent.CompletableFuture; -import static io.gitlab.jfronny.libjf.LibJf.LOGGER; - -public class GoogleChatServer implements DedicatedServerModInitializer { +public class GoogleChatServer implements DedicatedServerModInitializer, MessageDecorator { @Override public void onInitializeServer() { // Default phase is executed between CONTENT and STYLING // Perform translation there instead of during CONTENT to better support other mods (such as chat-transform) // If this causes an incompatibility, I'll add my own phase - ServerMessageDecoratorEvent.EVENT.register(Event.DEFAULT_PHASE, (sender, originalMessage) -> { - CompletableFuture futureMessage = CompletableFuture.completedFuture(originalMessage); - if (!GoogleChatConfig.General.enabled) return futureMessage; // fast fallthrough - if (sender != null) { // Client messages should first be translated to the server language - if (TranslationDirection.C2S.hasTarget()) { - if (TranslationDirection.S2C.hasTarget()) { - // Do not translate back and forth - return futureMessage; - } + ServerMessageDecoratorEvent.EVENT.register(Event.DEFAULT_PHASE, this); + } + + @Override + public CompletableFuture decorate(@Nullable ServerPlayerEntity sender, Text original) { + final CompletableFuture future = CompletableFuture.completedFuture(original); + if (!GoogleChatConfig.General.enabled) return future; + return GoogleChatConfig.Advanced.async + ? decorate(sender, new TranslatableContainer.Async(future)).text() + : CompletableFuture.completedFuture(decorate(sender, new TranslatableContainer.Sync(original)).text()); + } + + private > T decorate(@Nullable ServerPlayerEntity sender, T original) { + T message = original; + if (sender != null) { // Client messages should first be translated to the server language + if (TranslationDirection.C2S.hasTarget()) { + if (TranslationDirection.S2C.hasTarget()) { + // Do not translate back and forth + return message; } - futureMessage = futureMessage.thenApplyAsync(msg -> { - var translated = GoogleChat.translateIfNeeded(msg, TranslationDirection.C2S, true); - if (GoogleChatConfig.Advanced.debugLogs) LOGGER.info("Applied C2S translation from " + msg + " to " + translated); - return translated; - }); } - // All messages should be translated to the client language before sending - futureMessage = futureMessage.thenApplyAsync(msg -> { - var translated = GoogleChat.translateIfNeeded(msg, TranslationDirection.S2C, true); - if (GoogleChatConfig.Advanced.debugLogs) LOGGER.info("Applied S2C translation from " + msg + " to " + translated); - return translated; - }); - return futureMessage; - }); + message = message.translate(TranslationDirection.C2S); + } + // All messages should be translated to the client language before sending + message = message.translate(TranslationDirection.S2C); + return message; } } diff --git a/src/main/java/io/gitlab/jfronny/googlechat/server/TranslatableContainer.java b/src/main/java/io/gitlab/jfronny/googlechat/server/TranslatableContainer.java new file mode 100644 index 0000000..7a66145 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/googlechat/server/TranslatableContainer.java @@ -0,0 +1,32 @@ +package io.gitlab.jfronny.googlechat.server; + +import io.gitlab.jfronny.googlechat.*; +import net.minecraft.text.Text; + +import java.util.concurrent.CompletableFuture; + +import static io.gitlab.jfronny.libjf.LibJf.LOGGER; + +public sealed interface TranslatableContainer> { + S translate(TranslationDirection direction); + + record Sync(Text text) implements TranslatableContainer { + @Override + public Sync translate(TranslationDirection direction) { + return new Sync(translateAndLog(text, direction)); + } + } + + record Async(CompletableFuture text) implements TranslatableContainer, Async> { + @Override + public Async translate(TranslationDirection direction) { + return new Async(text.thenApplyAsync(msg -> translateAndLog(msg, direction))); + } + } + + static Text translateAndLog(final Text source, final TranslationDirection direction) { + var translated = GoogleChat.translateIfNeeded(source, direction, true); + if (GoogleChatConfig.Advanced.debugLogs) LOGGER.info("Applied C2S translation from " + source + " to " + translated); + return translated; + } +}