diff --git a/build.gradle.kts b/build.gradle.kts index 5fee651..2df4c11 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,6 +7,9 @@ plugins { dependencies { modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v1:${prop("libjf_version")}") + include(modImplementation(fabricApi.module("fabric-message-api-v1", prop("fabric_version")))!!) + include(modImplementation(fabricApi.module("fabric-command-api-v2", prop("fabric_version")))!!) + modImplementation(fabricApi.module("fabric-networking-api-v1", prop("fabric_version"))) // Dev env modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny-v1:${prop("libjf_version")}") diff --git a/src/client/java/io/gitlab/jfronny/chattransform/ChatTransform.java b/src/client/java/io/gitlab/jfronny/chattransform/ChatTransform.java deleted file mode 100644 index dc9c301..0000000 --- a/src/client/java/io/gitlab/jfronny/chattransform/ChatTransform.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.gitlab.jfronny.chattransform; - -import io.gitlab.jfronny.commons.log.Logger; -import net.fabricmc.api.ClientModInitializer; - -public class ChatTransform implements ClientModInitializer { - public static final Logger LOG = Logger.forName("chat-transform"); - - @Override - public void onInitializeClient() { - LOG.info("Loaded chat-transform"); - } -} diff --git a/src/client/java/io/gitlab/jfronny/chattransform/ITextFieldWidget.java b/src/client/java/io/gitlab/jfronny/chattransform/client/ITextFieldWidget.java similarity index 69% rename from src/client/java/io/gitlab/jfronny/chattransform/ITextFieldWidget.java rename to src/client/java/io/gitlab/jfronny/chattransform/client/ITextFieldWidget.java index 3690188..d893074 100644 --- a/src/client/java/io/gitlab/jfronny/chattransform/ITextFieldWidget.java +++ b/src/client/java/io/gitlab/jfronny/chattransform/client/ITextFieldWidget.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.chattransform; +package io.gitlab.jfronny.chattransform.client; public interface ITextFieldWidget { void chattransform$activate(); diff --git a/src/client/java/io/gitlab/jfronny/chattransform/Substitution.java b/src/client/java/io/gitlab/jfronny/chattransform/client/Substitution.java similarity index 84% rename from src/client/java/io/gitlab/jfronny/chattransform/Substitution.java rename to src/client/java/io/gitlab/jfronny/chattransform/client/Substitution.java index 82cecc7..a52b4a3 100644 --- a/src/client/java/io/gitlab/jfronny/chattransform/Substitution.java +++ b/src/client/java/io/gitlab/jfronny/chattransform/client/Substitution.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.chattransform; +package io.gitlab.jfronny.chattransform.client; public record Substitution(int start, int end, long time) { public Substitution(int start, int end) { diff --git a/src/client/java/io/gitlab/jfronny/chattransform/TransformStart.java b/src/client/java/io/gitlab/jfronny/chattransform/client/TransformStart.java similarity index 96% rename from src/client/java/io/gitlab/jfronny/chattransform/TransformStart.java rename to src/client/java/io/gitlab/jfronny/chattransform/client/TransformStart.java index 2987f83..ca23da3 100644 --- a/src/client/java/io/gitlab/jfronny/chattransform/TransformStart.java +++ b/src/client/java/io/gitlab/jfronny/chattransform/client/TransformStart.java @@ -1,4 +1,4 @@ -package io.gitlab.jfronny.chattransform; +package io.gitlab.jfronny.chattransform.client; public class TransformStart { private boolean available = false; diff --git a/src/client/java/io/gitlab/jfronny/chattransform/client/mixin/ChatScreenMixin.java b/src/client/java/io/gitlab/jfronny/chattransform/client/mixin/ChatScreenMixin.java new file mode 100644 index 0000000..a7c9315 --- /dev/null +++ b/src/client/java/io/gitlab/jfronny/chattransform/client/mixin/ChatScreenMixin.java @@ -0,0 +1,27 @@ +package io.gitlab.jfronny.chattransform.client.mixin; + +import io.gitlab.jfronny.chattransform.*; +import io.gitlab.jfronny.chattransform.client.ITextFieldWidget; +import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.client.gui.widget.TextFieldWidget; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ChatScreen.class) +public abstract class ChatScreenMixin { + @Shadow protected TextFieldWidget chatField; + + @Inject(at = @At("RETURN"), method = "init()V") + void init(CallbackInfo ci) { + if (Cfg.Client.mode == Cfg.Mode.Live) ((ITextFieldWidget) chatField).chattransform$activate(); + } + + @Redirect(method = "keyPressed(III)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/TextFieldWidget;getText()Ljava/lang/String;")) + String finalizeTransforms(TextFieldWidget instance) { + String text = ((ITextFieldWidget) chatField).chattransform$finalize(); + if (Cfg.Client.mode == Cfg.Mode.OnSend) text = ChatTransform.transform(text); + return text; + } +} diff --git a/src/client/java/io/gitlab/jfronny/chattransform/mixin/TextFieldWidgetMixin.java b/src/client/java/io/gitlab/jfronny/chattransform/client/mixin/TextFieldWidgetMixin.java similarity index 98% rename from src/client/java/io/gitlab/jfronny/chattransform/mixin/TextFieldWidgetMixin.java rename to src/client/java/io/gitlab/jfronny/chattransform/client/mixin/TextFieldWidgetMixin.java index 9e73e45..eb55f5a 100644 --- a/src/client/java/io/gitlab/jfronny/chattransform/mixin/TextFieldWidgetMixin.java +++ b/src/client/java/io/gitlab/jfronny/chattransform/client/mixin/TextFieldWidgetMixin.java @@ -1,8 +1,8 @@ -package io.gitlab.jfronny.chattransform.mixin; +package io.gitlab.jfronny.chattransform.client.mixin; import io.gitlab.jfronny.chattransform.*; +import io.gitlab.jfronny.chattransform.client.*; import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ClickableWidget; import net.minecraft.client.gui.widget.TextFieldWidget; diff --git a/src/client/java/io/gitlab/jfronny/chattransform/mixin/ChatScreenMixin.java b/src/client/java/io/gitlab/jfronny/chattransform/mixin/ChatScreenMixin.java deleted file mode 100644 index 9dea623..0000000 --- a/src/client/java/io/gitlab/jfronny/chattransform/mixin/ChatScreenMixin.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.gitlab.jfronny.chattransform.mixin; - -import io.gitlab.jfronny.chattransform.Cfg; -import io.gitlab.jfronny.chattransform.ITextFieldWidget; -import net.minecraft.client.gui.screen.ChatScreen; -import net.minecraft.client.gui.widget.TextFieldWidget; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.*; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.*; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -@Mixin(ChatScreen.class) -public abstract class ChatScreenMixin { - @Shadow protected TextFieldWidget chatField; - - @Inject(at = @At("RETURN"), method = "init()V") - void init(CallbackInfo ci) { - if (Cfg.mode == Cfg.Mode.Live) ((ITextFieldWidget) chatField).chattransform$activate(); - } - - @Redirect(method = "keyPressed(III)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/TextFieldWidget;getText()Ljava/lang/String;")) - String finalizeTransforms(TextFieldWidget instance) { - String str = ((ITextFieldWidget) chatField).chattransform$finalize(); - if (Cfg.mode == Cfg.Mode.OnSend) { - for (Map.Entry e : Cfg.substitutions - .entrySet() - .stream() - .collect(Collectors.groupingBy(s -> s.getKey().length())) - .entrySet() - .stream() - .sorted(Map.Entry.>>comparingByKey().reversed()) - .map(Map.Entry::getValue) - .flatMap(Collection::stream) - .toList()) { - str = str.replaceAll(Pattern.quote(e.getKey()), e.getValue()); - } - } - return str; - } -} diff --git a/src/client/resources/assets/chat-transform/lang/en_us.json b/src/client/resources/assets/chat-transform/lang/en_us.json index 953c8f6..dde0aca 100644 --- a/src/client/resources/assets/chat-transform/lang/en_us.json +++ b/src/client/resources/assets/chat-transform/lang/en_us.json @@ -2,10 +2,20 @@ "chat-transform.jfconfig.title": "Chat-Transform", "chat-transform.jfconfig.substitutions": "Substitutions", "chat-transform.jfconfig.substitutions.tooltip": "The substitutions to perform on text sent in the chat. See the presets for examples", - "chat-transform.jfconfig.mode": "Mode", - "chat-transform.jfconfig.mode.tooltip": "When to perform replacements", - "chat-transform.jfconfig.visualize": "Visualize", - "chat-transform.jfconfig.visualize.tooltip": "Visualize transformations as you type in live mode", + "chat-transform.jfconfig.client.title": "Client Settings", + "chat-transform.jfconfig.client.mode": "Mode", + "chat-transform.jfconfig.client.mode.tooltip": "When to perform replacements", "chat-transform.jfconfig.enum.Mode.Live": "Live", - "chat-transform.jfconfig.enum.Mode.OnSend": "On Send" + "chat-transform.jfconfig.enum.Mode.OnSend": "On Send", + "chat-transform.jfconfig.client.visualize": "Visualize", + "chat-transform.jfconfig.client.visualize.tooltip": "Visualize transformations as you type in live mode", + "chat-transform.jfconfig.server.title": "Server Settings", + "chat-transform.jfconfig.server.messageOnFirstConnect": "Message on first connect", + "chat-transform.jfconfig.server.messageOnFirstConnect.tooltip": "Whether to send a chat message to players about chat-transform when they first connect", + "chat-transform.jfconfig.server.playerStates": "Player States", + "chat-transform.jfconfig.server.playerStates.tooltip": "For which players messages should be transformed", + "chat-transform.jfconfig.server.playerConfigurable": "Player Configurable", + "chat-transform.jfconfig.server.playerConfigurable.tooltip": "Whether players should be able to toggle chat transformation", + "chat-transform.jfconfig.server.defaultEnable": "Default Enable", + "chat-transform.jfconfig.server.defaultEnable.tooltip": "Whether players' chat should be transformed by default" } \ No newline at end of file diff --git a/src/client/resources/chat-transform.client.mixins.json b/src/client/resources/chat-transform.client.mixins.json index 426ff91..987e296 100644 --- a/src/client/resources/chat-transform.client.mixins.json +++ b/src/client/resources/chat-transform.client.mixins.json @@ -1,7 +1,7 @@ { "required": true, "minVersion": "0.8", - "package": "io.gitlab.jfronny.chattransform.mixin", + "package": "io.gitlab.jfronny.chattransform.client.mixin", "compatibilityLevel": "JAVA_17", "client": [ "ChatScreenMixin", diff --git a/src/main/java/io/gitlab/jfronny/chattransform/Cfg.java b/src/main/java/io/gitlab/jfronny/chattransform/Cfg.java new file mode 100644 index 0000000..10fe8c0 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/chattransform/Cfg.java @@ -0,0 +1,78 @@ +package io.gitlab.jfronny.chattransform; + +import io.gitlab.jfronny.commons.serialize.gson.api.v1.Ignore; +import io.gitlab.jfronny.libjf.config.api.v1.*; + +import java.util.*; + +@JfConfig +public class Cfg { + @Entry public static Map substitutions = Map.of(); + + @Category + public static class Client { + @Entry public static Mode mode = Mode.Live; + @Entry public static boolean visualize = true; + } + + @Category + public static class Server { + @Entry public static boolean messageOnFirstConnect = true; + @Entry public static Map playerStates = new HashMap<>(); + @Entry public static boolean playerConfigurable = true; + @Entry public static boolean defaultEnable = true; + } + + public enum Mode { + Live, OnSend + } + + @Preset + public static void owo() { + substitutions = new LinkedHashMap<>(); + substitutions.put("r", "w"); + substitutions.put("l", "w"); + substitutions.put("R", "W"); + substitutions.put("L", "W"); + substitutions.put("no", "nu"); + substitutions.put("has", "haz"); + substitutions.put("have", "haz"); + substitutions.put("you", "uu"); + substitutions.put("the ", "da "); + substitutions.put("The ", "Da "); + } + + @Preset + public static void demonstrationPurposesOnly() { + substitutions = new LinkedHashMap<>(); + substitutions.put("chat-transform", "Chat-Transform (this mod)"); + substitutions.put(":tm:", "™"); + substitutions.put("(c)", "©"); + } + + @Ignore private static final char[] consonants = "bcdfghjklmprstwz".toCharArray(); + + @Preset + public static void katakana() { + substitutions = new LinkedHashMap<>(); + substitutions.put("-", "ー"); + for (char c : consonants) { + substitutions.put("" + c + c, "ッ" + c); + } + substitutions.put("nn", "ン"); + JapaneseMap.fromTable(JapaneseMap.katakanaTable, substitutions::put); + System.out.println("katakana " + substitutions); + } + + @Preset + public static void hiragana() { + substitutions = new LinkedHashMap<>(); + substitutions.put("-", "ー"); + for (char c : consonants) { + substitutions.put("" + c + c, "っ" + c); + } + substitutions.put("nn", "ん"); + JapaneseMap.fromTable(JapaneseMap.hiraganaTable, substitutions::put); + System.out.println("hiragana " + substitutions); + } +} diff --git a/src/main/java/io/gitlab/jfronny/chattransform/ChatTransform.java b/src/main/java/io/gitlab/jfronny/chattransform/ChatTransform.java new file mode 100644 index 0000000..73cb843 --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/chattransform/ChatTransform.java @@ -0,0 +1,28 @@ +package io.gitlab.jfronny.chattransform; + +import io.gitlab.jfronny.commons.log.Logger; + +import java.util.*; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class ChatTransform { + public static final String MOD_ID = "chat-transform"; + public static final Logger LOG = Logger.forName(MOD_ID); + + public static String transform(String text) { + for (Map.Entry e : Cfg.substitutions + .entrySet() + .stream() + .collect(Collectors.groupingBy(s -> s.getKey().length())) + .entrySet() + .stream() + .sorted(Map.Entry.>>comparingByKey().reversed()) + .map(Map.Entry::getValue) + .flatMap(Collection::stream) + .toList()) { + text = text.replaceAll(Pattern.quote(e.getKey()), e.getValue()); + } + return text; + } +} diff --git a/src/client/java/io/gitlab/jfronny/chattransform/Cfg.java b/src/main/java/io/gitlab/jfronny/chattransform/JapaneseMap.java similarity index 56% rename from src/client/java/io/gitlab/jfronny/chattransform/Cfg.java rename to src/main/java/io/gitlab/jfronny/chattransform/JapaneseMap.java index d849d9b..d7ffb54 100644 --- a/src/client/java/io/gitlab/jfronny/chattransform/Cfg.java +++ b/src/main/java/io/gitlab/jfronny/chattransform/JapaneseMap.java @@ -1,45 +1,9 @@ package io.gitlab.jfronny.chattransform; -import io.gitlab.jfronny.commons.serialize.gson.api.v1.Ignore; -import io.gitlab.jfronny.libjf.config.api.v1.*; +import java.util.function.BiConsumer; -import java.util.LinkedHashMap; -import java.util.Map; - -@JfConfig -public class Cfg { - @Entry public static Map substitutions = Map.of(); - @Entry public static Mode mode = Mode.Live; - @Entry public static boolean visualize = true; - - public enum Mode { - Live, OnSend - } - - @Preset - public static void owo() { - substitutions = new LinkedHashMap<>(); - substitutions.put("r", "w"); - substitutions.put("l", "w"); - substitutions.put("R", "W"); - substitutions.put("L", "W"); - substitutions.put("no", "nu"); - substitutions.put("has", "haz"); - substitutions.put("have", "haz"); - substitutions.put("you", "uu"); - substitutions.put("the ", "da "); - substitutions.put("The ", "Da "); - } - - @Preset - public static void demonstrationPurposesOnly() { - substitutions = new LinkedHashMap<>(); - substitutions.put("chat-transform", "Chat-Transform (this mod)"); - substitutions.put(":tm:", "™"); - substitutions.put("(c)", "©"); - } - - @Ignore private static final String katakanaTable = """ +public class JapaneseMap { + public static final String katakanaTable = """ a i u e o n ア イ ウ エ オ ン x ァ ィ ゥ ェ ォ @@ -72,7 +36,7 @@ public class Cfg { py ピャ ピュ ピョ v ゔ"""; - @Ignore private static final String hiraganaTable = """ + public static final String hiraganaTable = """ a i u e o n あ い う え お ん x ぁ ぃ ぅ ぇ ぉ @@ -105,9 +69,7 @@ public class Cfg { py ぴゃ ぴゅ ぴょ v ゔ"""; - @Ignore private static final char[] consonants = "bcdfghjklmprstwz".toCharArray(); - - private static void fromTable(String table) { + public static void fromTable(String table, BiConsumer target) { String[] rows = table.split("\n"); String[] colNames = rows[0].split("\t"); for (int i = 1; i < rows.length; i++) { @@ -120,34 +82,10 @@ public class Cfg { String[] kanas = kana.split("/"); for (String singleKana : kanas) { if (!singleKana.isEmpty()) { - substitutions.put(value, singleKana); + target.accept(value, singleKana); } } } } } - - @Preset - public static void katakana() { - substitutions = new LinkedHashMap<>(); - substitutions.put("-", "ー"); - for (char c : consonants) { - substitutions.put("" + c + c, "ッ" + c); - } - substitutions.put("nn", "ン"); - fromTable(katakanaTable); - System.out.println("katakana " + substitutions); - } - - @Preset - public static void hiragana() { - substitutions = new LinkedHashMap<>(); - substitutions.put("-", "ー"); - for (char c : consonants) { - substitutions.put("" + c + c, "っ" + c); - } - substitutions.put("nn", "ん"); - fromTable(hiraganaTable); - System.out.println("hiragana " + substitutions); - } } diff --git a/src/main/java/io/gitlab/jfronny/chattransform/server/ChatTransformServer.java b/src/main/java/io/gitlab/jfronny/chattransform/server/ChatTransformServer.java new file mode 100644 index 0000000..bbc7b2a --- /dev/null +++ b/src/main/java/io/gitlab/jfronny/chattransform/server/ChatTransformServer.java @@ -0,0 +1,143 @@ +package io.gitlab.jfronny.chattransform.server; + +import com.mojang.brigadier.Command; +import io.gitlab.jfronny.chattransform.Cfg; +import io.gitlab.jfronny.chattransform.ChatTransform; +import io.gitlab.jfronny.libjf.config.api.v1.ConfigInstance; +import net.fabricmc.api.DedicatedServerModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.message.v1.ServerMessageDecoratorEvent; +import net.fabricmc.fabric.api.networking.v1.ServerLoginConnectionEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.minecraft.network.packet.s2c.play.ChatMessageS2CPacket; +import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.*; +import org.spongepowered.asm.mixin.Mutable; + +import java.util.Arrays; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +import static net.minecraft.server.command.CommandManager.*; + +public class ChatTransformServer implements DedicatedServerModInitializer { + public static final ConfigInstance CONFIG_INSTANCE = Objects.requireNonNull(ConfigInstance.get(ChatTransform.MOD_ID)); + + @Override + public void onInitializeServer() { + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { + var root = literal(ChatTransform.MOD_ID).executes(context -> { + context.getSource().sendMessage(Text.literal(ChatTransform.MOD_ID + " is " + (get(context.getSource().getPlayer()) ? "enabled" : "disabled") + " for you.")); + return Command.SINGLE_SUCCESS; + }); + root.then(literal("opt-in").requires(src -> Cfg.Server.playerConfigurable).executes(context -> { + if (context.getSource().getPlayer() == null) { + context.getSource().sendError(Text.literal("You are not a player.")); + return Command.SINGLE_SUCCESS; + } + if (get(context.getSource().getPlayer())) { + context.getSource().sendError(Text.literal("You are already opted in to using chat-transform.")); + return Command.SINGLE_SUCCESS; + } + set(context.getSource().getPlayer(), true); + context.getSource().sendMessage(Text.literal("Toggled " + ChatTransform.MOD_ID + " on")); + return Command.SINGLE_SUCCESS; + })); + root.then(literal("opt-out").requires(src -> Cfg.Server.playerConfigurable).executes(context -> { + if (context.getSource().getPlayer() == null) { + context.getSource().sendError(Text.literal("You are not a player.")); + return Command.SINGLE_SUCCESS; + } + if (!get(context.getSource().getPlayer())) { + context.getSource().sendError(Text.literal("You are already opted out of using chat-transform.")); + return Command.SINGLE_SUCCESS; + } + set(context.getSource().getPlayer(), false); + context.getSource().sendMessage(Text.literal("Toggled " + ChatTransform.MOD_ID + " off")); + return Command.SINGLE_SUCCESS; + })); + root.then(literal("reset").requires(src -> Cfg.Server.playerConfigurable).executes(context -> { + if (context.getSource().getPlayer() == null) { + context.getSource().sendError(Text.literal("You are not a player.")); + return Command.SINGLE_SUCCESS; + } + reset(context.getSource().getPlayer()); + context.getSource().sendMessage(Text.literal("Reset " + ChatTransform.MOD_ID + " to " + (Cfg.Server.defaultEnable ? "on" : "off"))); + return Command.SINGLE_SUCCESS; + })); + root.then(literal("reset-all").requires(src -> src.hasPermissionLevel(4)).executes(context -> { + Cfg.Server.playerStates.clear(); + CONFIG_INSTANCE.write(); + context.getSource().sendMessage(Text.literal("Reset all player states")); + return Command.SINGLE_SUCCESS; + })); + dispatcher.register(root); + }); + + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + if (Cfg.Server.messageOnFirstConnect && !has(handler.getPlayer())) { + set(handler.getPlayer(), Cfg.Server.defaultEnable); + MutableText text = Text.literal("This server uses " + ChatTransform.MOD_ID + " to transform messages you send."); + if (Cfg.Server.playerConfigurable) { + text.append(" To turn it " + (Cfg.Server.defaultEnable ? "off" : "on") + ", use "); + String command = "/" + ChatTransform.MOD_ID + " opt-" + (Cfg.Server.defaultEnable ? "out" : "in"); + text.append(Text.literal(command) + .styled(s -> s.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command))) + ); + text.append("."); + } + handler.getPlayer().sendMessage(text); + } + }); + + ServerMessageDecoratorEvent.EVENT.register(ServerMessageDecoratorEvent.CONTENT_PHASE, (sender, message) -> { + return CompletableFuture.completedFuture(sender != null && get(sender) ? transform(message) : message); + }); + } + + private boolean has(ServerPlayerEntity player) { + return Cfg.Server.playerStates.containsKey(player.getUuidAsString()); + } + + private boolean get(ServerPlayerEntity player) { + return Cfg.Server.playerStates.computeIfAbsent(player.getUuidAsString(), k -> Cfg.Server.defaultEnable); + } + + private void set(ServerPlayerEntity player, boolean value) { + Cfg.Server.playerStates.put(player.getUuidAsString(), value); + CONFIG_INSTANCE.write(); + } + + private void reset(ServerPlayerEntity player) { + Cfg.Server.playerStates.remove(player.getUuidAsString()); + CONFIG_INSTANCE.write(); + } + + private Text transform(Text source) { + MutableText result = MutableText.of(transform(source.getContent())) + .setStyle(source.getStyle()); + for (Text sibling : source.getSiblings()) { + result.append(transform(sibling)); + } + return result; + } + + private TextContent transform(TextContent source) { + if (source instanceof TranslatableTextContent tx) { + Object[] args = tx.getArgs(); + args = Arrays.copyOf(args, args.length); + for (int i = 0; i < args.length; i++) { + if (args[i] instanceof Text tx1) args[i] = transform(tx1); + else if (args[i] instanceof TextContent tx1) args[i] = transform(tx1); + else if (args[i] instanceof String tx1) args[i] = ChatTransform.transform(tx1); + else args[i] = args[i]; + } + return new TranslatableTextContent(tx.getKey(), ChatTransform.transform(tx.getFallback()), args); + } else if (source instanceof LiteralTextContent tx) { + return new LiteralTextContent(ChatTransform.transform(tx.string())); + } else { + return source; + } + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 4c66686..c367c23 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -13,9 +13,9 @@ }, "license": "MIT", "icon": "assets/chat-transform/icon.png", - "environment": "client", + "environment": "*", "entrypoints": { - "client": ["io.gitlab.jfronny.chattransform.ChatTransform"], + "server": ["io.gitlab.jfronny.chattransform.server.ChatTransformServer"], "libjf:config": ["io.gitlab.jfronny.chattransform.JFC_Cfg"] }, "mixins": [