diff --git a/build.gradle b/build.gradle index 090b6f3..af69cfe 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ dependencies { //modRuntimeOnly("io.gitlab.jfronny.libjf:libjf-devutil-v0:${project.jfapi_version}") - modImplementation "com.terraformersmc:modmenu:4.0.0-beta.4" + modImplementation "com.terraformersmc:modmenu:4.0.5" // Compat fix include modImplementation(fabricApi.module("fabric-command-api-v2", project.fabric_version)) diff --git a/gradle.properties b/gradle.properties index 738038b..240fd70 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,16 +1,16 @@ # https://fabricmc.net/develop/ -minecraft_version=1.19 +minecraft_version=1.19.1 yarn_mappings=build.1 -loader_version=0.14.6 +loader_version=0.14.8 maven_group=io.gitlab.jfronny archives_base_name=GoogleChat -jfapi_version=2.9.0 -fabric_version=0.55.1+1.19 +jfapi_version=2.10.0 +fabric_version=0.58.5+1.19.1 -modrinth_id=Hd7ZLKRk -modrinth_required_dependencies=WKwQAwke -modrinth_optional_dependencies=mOgUt4GM +modrinth_id=google-chat +modrinth_required_dependencies=libjf +modrinth_optional_dependencies=modmenu curseforge_id=574331 curseforge_required_dependencies=libjf curseforge_optional_dependencies=modmenu \ No newline at end of file diff --git a/src/main/java/io/gitlab/jfronny/googlechat/mixin/ChatScreenMixin.java b/src/client/java/io/gitlab/jfronny/googlechat/mixin/ChatScreenMixin.java similarity index 100% rename from src/main/java/io/gitlab/jfronny/googlechat/mixin/ChatScreenMixin.java rename to src/client/java/io/gitlab/jfronny/googlechat/mixin/ChatScreenMixin.java diff --git a/src/main/java/io/gitlab/jfronny/googlechat/mixin/ClientPlayerEntityMixin.java b/src/client/java/io/gitlab/jfronny/googlechat/mixin/ClientPlayerEntityMixin.java similarity index 100% rename from src/main/java/io/gitlab/jfronny/googlechat/mixin/ClientPlayerEntityMixin.java rename to src/client/java/io/gitlab/jfronny/googlechat/mixin/ClientPlayerEntityMixin.java diff --git a/src/client/java/io/gitlab/jfronny/googlechat/mixin/MessageHandlerMixin.java b/src/client/java/io/gitlab/jfronny/googlechat/mixin/MessageHandlerMixin.java new file mode 100644 index 0000000..03d51da --- /dev/null +++ b/src/client/java/io/gitlab/jfronny/googlechat/mixin/MessageHandlerMixin.java @@ -0,0 +1,35 @@ +package io.gitlab.jfronny.googlechat.mixin; + +import io.gitlab.jfronny.googlechat.GoogleChat; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.client.gui.hud.MessageIndicator; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.client.network.message.MessageHandler; +import net.minecraft.network.message.*; +import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.*; + +import java.time.Instant; + +@Mixin(MessageHandler.class) +public class MessageHandlerMixin { + @Redirect(method = "processChatMessageInternal(Lnet/minecraft/network/message/MessageType$Parameters;Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/text/Text;Lnet/minecraft/client/network/PlayerListEntry;ZLjava/time/Instant;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V")) + void googlechat$injectAddMessage(ChatHud instance, Text message, @Nullable MessageSignatureData signature, @Nullable MessageIndicator indicator, MessageType.Parameters args$params, SignedMessage args$message, Text args$decorated, @Nullable PlayerListEntry args$senderEntry, boolean args$onlyShowSecureChat, Instant args$receptionTimestamp) { + MinecraftClient mc = MinecraftClient.getInstance(); + if (mc != null && mc.player != null && args$senderEntry != null && !args$senderEntry.getProfile().getId().equals(mc.player.getUuid())) + message = googlechat$translate(message); + instance.addMessage(message, signature, indicator); + } + + @Redirect(method = "processProfilelessMessage(Lnet/minecraft/network/message/MessageType$Parameters;Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/text/Text;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;addMessage(Lnet/minecraft/text/Text;)V")) + void googlechat$injectAddMessage(ChatHud instance, Text message) { + instance.addMessage(googlechat$translate(message)); + } + + private Text googlechat$translate(Text message) { + return GoogleChat.translateIfNeeded(message, GoogleChat.Direction.S2C, true); + } +} diff --git a/src/main/resources/GoogleChat.mixins.json b/src/client/resources/google-chat.client.mixins.json similarity index 87% rename from src/main/resources/GoogleChat.mixins.json rename to src/client/resources/google-chat.client.mixins.json index 19e2b1e..8320acf 100644 --- a/src/main/resources/GoogleChat.mixins.json +++ b/src/client/resources/google-chat.client.mixins.json @@ -6,7 +6,7 @@ "client": [ "ChatScreenMixin", "ClientPlayerEntityMixin", - "ClientPlayNetworkHandlerMixin" + "MessageHandlerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/java/io/gitlab/jfronny/googlechat/CacheKey.java b/src/main/java/io/gitlab/jfronny/googlechat/CacheKey.java deleted file mode 100644 index 8a159e6..0000000 --- a/src/main/java/io/gitlab/jfronny/googlechat/CacheKey.java +++ /dev/null @@ -1,4 +0,0 @@ -package io.gitlab.jfronny.googlechat; - -public record CacheKey(String sourceText, String sourceLangId, String targetLangId) { -} diff --git a/src/main/java/io/gitlab/jfronny/googlechat/FixedSizeCache.java b/src/main/java/io/gitlab/jfronny/googlechat/FixedSizeCache.java deleted file mode 100644 index dcf1773..0000000 --- a/src/main/java/io/gitlab/jfronny/googlechat/FixedSizeCache.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.gitlab.jfronny.googlechat; - -import java.util.*; - -public class FixedSizeCache extends LinkedHashMap { - private final int maxSize; - - public FixedSizeCache(int size) { - super(size + 2, 1F); - this.maxSize = size; - } - - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > maxSize; - } -} diff --git a/src/main/java/io/gitlab/jfronny/googlechat/GoogleChat.java b/src/main/java/io/gitlab/jfronny/googlechat/GoogleChat.java index 1a28e15..ce59d80 100644 --- a/src/main/java/io/gitlab/jfronny/googlechat/GoogleChat.java +++ b/src/main/java/io/gitlab/jfronny/googlechat/GoogleChat.java @@ -5,7 +5,6 @@ import io.gitlab.jfronny.libjf.translate.api.*; import net.fabricmc.api.*; import net.fabricmc.fabric.api.message.v1.*; import net.fabricmc.loader.api.*; -import net.minecraft.client.*; import net.minecraft.text.*; import java.util.*; @@ -15,24 +14,26 @@ public class GoogleChat implements ModInitializer { public static final String MOD_ID = "google-chat"; public static final Logger LOGGER = Logger.forName(MOD_ID); public static final TranslateService TRANSLATE_SERVICE = TranslateService.getConfigured(); - private static final FixedSizeCache TRANSLATION_CACHE = new FixedSizeCache<>(126); @Override public void onInitialize() { ServerMessageDecoratorEvent.EVENT.register(ServerMessageDecoratorEvent.CONTENT_PHASE, (sender, message) -> { - if (sender != null) // Client messages should first be translated to the server language + Text original; + if (sender != null) { // Client messages should first be translated to the server language + if (hasTarget(Direction.C2S) && hasTarget(Direction.S2C)) // Do not translate back and forth + return CompletableFuture.completedFuture(message); + original = message; message = translateIfNeeded(message, Direction.C2S, true); + LOGGER.info("Applied C2S translation from " + original + " to " + message); + } // All messages should be translated to the client language before sending + original = message; message = translateIfNeeded(message, Direction.S2C, true); + LOGGER.info("Applied S2C translation from " + original + " to " + message); return CompletableFuture.completedFuture(message); }); } - public static boolean isSelf(UUID sender) { - MinecraftClient mc = MinecraftClient.getInstance(); - return mc == null || mc.player == null || sender.equals(mc.player.getUuid()); - } - public static Text translateIfNeeded(Text source, Direction direction, boolean respectRegex) { if (shouldSkipOutright(direction)) return source; String sourceString = toString(source); @@ -49,7 +50,7 @@ public class GoogleChat implements ModInitializer { if (source.getContent() instanceof TranslatableTextContent tx) { Object[] args = tx.getArgs(); args = Arrays.copyOf(args, args.length); - // We're not translating TranslatableText but want potential keys + // We're not translating TranslatableText, but are translating arguments for (int i = 0; i < args.length; i++) { args[i] = args[i] instanceof Text tx1 ? translateIfNeeded(tx1, direction, false) : args[i] instanceof String tx1 ? translateIfNeeded(tx1, direction, false) @@ -81,19 +82,17 @@ public class GoogleChat implements ModInitializer { return style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverText)); } - public static String translateIfNeeded(String source, Direction direction, boolean respectRegex) { + public static String translateIfNeeded(String source, Direction direction, boolean respectRegex) { if (shouldSkipOutright(direction)) return source; if (respectRegex && failsRegex(source, direction)) return source; - TranslateService svc = (TranslateService) GoogleChat.TRANSLATE_SERVICE; // Generics bypass - TLang sourceLang = svc.parseLang(direction == Direction.C2S ? GoogleChatConfig.clientLanguage : GoogleChatConfig.serverLanguage); - TLang targetLang = svc.parseLang(direction == Direction.C2S ? GoogleChatConfig.serverLanguage : GoogleChatConfig.clientLanguage); - CacheKey key = new CacheKey(source, sourceLang.getIdentifier(), targetLang.getIdentifier()); - if (TRANSLATION_CACHE.containsKey(key)) return TRANSLATION_CACHE.get(key); + // Ignore generics since this is apparently not something java supports + @SuppressWarnings("rawtypes") TranslateService svc = GoogleChat.TRANSLATE_SERVICE; + Language sourceLang = svc.parseLang(direction == Direction.C2S ? GoogleChatConfig.clientLanguage : GoogleChatConfig.serverLanguage); + Language targetLang = svc.parseLang(direction == Direction.C2S ? GoogleChatConfig.serverLanguage : GoogleChatConfig.clientLanguage); try { - String translated = svc.translate(source, sourceLang, targetLang); - TRANSLATION_CACHE.put(key, translated); - return translated; + //noinspection unchecked + return svc.translate(source, sourceLang, targetLang); } catch (TranslateException e) { LOGGER.error("Could not translate text: " + source, e); return source; @@ -107,12 +106,14 @@ public class GoogleChat implements ModInitializer { } private static boolean shouldSkipOutright(Direction direction) { - if (!GoogleChatConfig.enabled) return true; - Language clientLang = TRANSLATE_SERVICE.parseLang(GoogleChatConfig.clientLanguage); - Language serverLang = TRANSLATE_SERVICE.parseLang(GoogleChatConfig.serverLanguage); - if (direction == Direction.S2C && clientLang.getIdentifier().equals("auto")) return true; - if (direction == Direction.C2S && serverLang.getIdentifier().equals("auto")) return true; - return false; + return !GoogleChatConfig.enabled || !hasTarget(direction); + } + + private static boolean hasTarget(Direction direction) { + return TRANSLATE_SERVICE.parseLang(switch (direction) { + case C2S -> GoogleChatConfig.serverLanguage; + case S2C -> GoogleChatConfig.clientLanguage; + }).getIdentifier().equals("auto"); } public enum Direction { diff --git a/src/main/java/io/gitlab/jfronny/googlechat/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/io/gitlab/jfronny/googlechat/mixin/ClientPlayNetworkHandlerMixin.java deleted file mode 100644 index 39d14dc..0000000 --- a/src/main/java/io/gitlab/jfronny/googlechat/mixin/ClientPlayNetworkHandlerMixin.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.gitlab.jfronny.googlechat.mixin; - -import io.gitlab.jfronny.googlechat.*; -import net.minecraft.client.gui.hud.*; -import net.minecraft.client.network.*; -import net.minecraft.network.message.*; -import net.minecraft.text.*; -import org.spongepowered.asm.mixin.*; -import org.spongepowered.asm.mixin.injection.*; - -@Mixin(ClientPlayNetworkHandler.class) -public class ClientPlayNetworkHandlerMixin { - @Redirect(method = "handleMessage(Lnet/minecraft/network/message/MessageType;Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/network/message/MessageSender;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;onChatMessage(Lnet/minecraft/network/message/MessageType;Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSender;)V")) - private void googlechat$interceptChatMessage(InGameHud hud, MessageType type, Text message, MessageSender sender) { - if (!GoogleChat.isSelf(sender.uuid())) - message = GoogleChat.translateIfNeeded(message, GoogleChat.Direction.S2C, true); - hud.onChatMessage(type, message, sender); - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 704b703..182fca0 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -14,11 +14,16 @@ "main": ["io.gitlab.jfronny.googlechat.GoogleChat"] }, "mixins": [ - "GoogleChat.mixins.json" + { + "config": "google-chat.client.mixins.json", + "environment": "client" + } ], "depends": { "fabricloader": ">=0.12.12", - "minecraft": "*" + "minecraft": "*", + "libjf-config-v0": "*", + "libjf-translate-v1": "*" }, "custom": { "libjf:config": {