diff --git a/gradle.properties b/gradle.properties index a060b0a..57276d4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.20.1+build.10 loader_version=0.16.8 # Mod Properties -mod_version=1.16.4 +mod_version=1.17.0 maven_group=cc.reconnected archives_base_name=rcc-server diff --git a/src/main/java/cc/reconnected/server/RccServer.java b/src/main/java/cc/reconnected/server/RccServer.java index 21dbd82..802acf4 100644 --- a/src/main/java/cc/reconnected/server/RccServer.java +++ b/src/main/java/cc/reconnected/server/RccServer.java @@ -19,8 +19,12 @@ import net.kyori.adventure.platform.fabric.FabricServerAudiences; import net.kyori.adventure.text.Component; import net.luckperms.api.LuckPerms; import net.luckperms.api.LuckPermsProvider; +import net.minecraft.network.message.MessageType; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Identifier; import net.minecraft.util.WorldSavePath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,6 +56,8 @@ public class RccServer implements ModInitializer { return luckPerms; } + public static MinecraftServer server; + private volatile FabricServerAudiences adventure; public FabricServerAudiences adventure() { @@ -62,11 +68,14 @@ public class RccServer implements ModInitializer { return ret; } + public static final RegistryKey CHAT_TYPE = RegistryKey.of(RegistryKeys.MESSAGE_TYPE, new Identifier(MOD_ID, "chat")); + @Override public void onInitialize() { LOGGER.info("Starting rcc-server"); ServerLifecycleEvents.SERVER_STARTING.register(server -> { + RccServer.server = server; state.register(server.getSavePath(WorldSavePath.ROOT).resolve("data").resolve(RccServer.MOD_ID)); this.adventure = FabricServerAudiences.of(server); }); diff --git a/src/main/java/cc/reconnected/server/RccServerConfigModel.java b/src/main/java/cc/reconnected/server/RccServerConfigModel.java index c826280..21d8e5b 100644 --- a/src/main/java/cc/reconnected/server/RccServerConfigModel.java +++ b/src/main/java/cc/reconnected/server/RccServerConfigModel.java @@ -3,8 +3,7 @@ package cc.reconnected.server; import io.wispforest.owo.config.annotation.Config; import io.wispforest.owo.config.annotation.Nest; -import java.util.ArrayList; -import java.util.List; +import java.util.*; @Config(name = "rcc-server-config", wrapperName = "RccServerConfig") public class RccServerConfigModel { @@ -32,6 +31,12 @@ public class RccServerConfigModel { @Nest public AutoRestart autoRestart = new AutoRestart(); + @Nest + public CustomNameConfig customName = new CustomNameConfig(); + + @Nest + public CustomChatFormat customChatFormat = new CustomChatFormat(); + public static class HttpApi { public boolean enableHttpApi = true; public int httpPort = 25581; @@ -106,4 +111,21 @@ public class RccServerConfigModel { 1 )); } + + public static class CustomNameConfig { + public LinkedHashMap formats = new LinkedHashMap<>(Map.of( + "admin", "", + "default", "" + )); + } + + public static class CustomChatFormat { + public boolean enableMarkdown = true; + public String chatFormat = ": "; + public String emoteFormat = "\uD83D\uDC64 "; + public String joinFormat = "+ joined!"; + public String joinRenamedFormat = "+ joined! (Previously known as )"; + public String leaveFormat = "- left!"; + public String deathFormat = "\u2620 "; + } } diff --git a/src/main/java/cc/reconnected/server/core/CustomNameFormat.java b/src/main/java/cc/reconnected/server/core/CustomNameFormat.java new file mode 100644 index 0000000..88c9d51 --- /dev/null +++ b/src/main/java/cc/reconnected/server/core/CustomNameFormat.java @@ -0,0 +1,43 @@ +package cc.reconnected.server.core; + +import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; +import eu.pb4.placeholders.api.PlaceholderContext; +import eu.pb4.placeholders.api.Placeholders; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.luckperms.api.model.group.Group; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.MutableText; + +public class CustomNameFormat { + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + public static MutableText getNameForPlayer(ServerPlayerEntity player) { + var formats = RccServer.CONFIG.customName.formats().entrySet(); + var lp = RccServer.getInstance().luckPerms(); + var playerContext = PlaceholderContext.of(player); + + var user = lp.getPlayerAdapter(ServerPlayerEntity.class).getUser(player); + + var groups = user.getInheritedGroups(user.getQueryOptions()).stream().map(Group::getName).toList(); + + String format = null; + for (var entry : formats) { + if (groups.contains(entry.getKey())) { + format = entry.getValue(); + break; + } + } + + if (format == null) { + format = ""; + } + + var displayName = miniMessage.deserialize(format, TagResolver.resolver( + Placeholder.parsed("username", player.getGameProfile().getName()) + )); + + return Placeholders.parseText(Components.toText(displayName), playerContext).copy(); + } +} diff --git a/src/main/java/cc/reconnected/server/core/customChat/CustomChatMessage.java b/src/main/java/cc/reconnected/server/core/customChat/CustomChatMessage.java new file mode 100644 index 0000000..92af65e --- /dev/null +++ b/src/main/java/cc/reconnected/server/core/customChat/CustomChatMessage.java @@ -0,0 +1,41 @@ +package cc.reconnected.server.core.customChat; + +import cc.reconnected.server.RccServer; +import cc.reconnected.server.parser.MarkdownParser; +import cc.reconnected.server.util.Components; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.minecraft.network.message.MessageType; +import net.minecraft.network.message.SignedMessage; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +public class CustomChatMessage { + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + + public static void sendChatMessage(ServerPlayerEntity receiver, SignedMessage message, MessageType.Parameters params) { + var playerUuid = message.link().sender(); + var player = RccServer.server.getPlayerManager().getPlayer(playerUuid); + + Text messageText; + if (RccServer.CONFIG.customChatFormat.enableMarkdown()) { + messageText = MarkdownParser.defaultParser.parseNode(message.getSignedContent()).toText(); + } else { + messageText = message.getContent(); + } + + var component = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.chatFormat(), TagResolver.resolver( + Placeholder.component("display_name", player.getDisplayName()), + Placeholder.component("message", messageText) + )); + + var text = Components.toText(component); + + var msgType = RccServer.server.getRegistryManager().get(RegistryKeys.MESSAGE_TYPE).getOrThrow(RccServer.CHAT_TYPE); + var newParams = new MessageType.Parameters(msgType, text, null); + + receiver.networkHandler.sendChatMessage(message, newParams); + } +} diff --git a/src/main/java/cc/reconnected/server/core/customChat/CustomConnectionMessage.java b/src/main/java/cc/reconnected/server/core/customChat/CustomConnectionMessage.java new file mode 100644 index 0000000..3bdb9a1 --- /dev/null +++ b/src/main/java/cc/reconnected/server/core/customChat/CustomConnectionMessage.java @@ -0,0 +1,41 @@ +package cc.reconnected.server.core.customChat; + +import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +public class CustomConnectionMessage { + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + + public static Text onJoin(ServerPlayerEntity player) { + var joinMessage = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.joinFormat(), + TagResolver.resolver( + Placeholder.component("display_name", player.getDisplayName()) + )); + + return Components.toText(joinMessage); + } + + public static Text onJoinRenamed(ServerPlayerEntity player, String previousName) { + var joinMessage = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.joinRenamedFormat(), + TagResolver.resolver( + Placeholder.component("display_name", player.getDisplayName()), + Placeholder.component("previous_name", Text.of(previousName)) + )); + + return Components.toText(joinMessage); + } + + public static Text onLeave(ServerPlayerEntity player) { + var leaveMessage = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.leaveFormat(), + TagResolver.resolver( + Placeholder.component("display_name", player.getDisplayName()) + )); + + return Components.toText(leaveMessage); + } +} diff --git a/src/main/java/cc/reconnected/server/core/customChat/CustomDeathMessage.java b/src/main/java/cc/reconnected/server/core/customChat/CustomDeathMessage.java new file mode 100644 index 0000000..caef5bc --- /dev/null +++ b/src/main/java/cc/reconnected/server/core/customChat/CustomDeathMessage.java @@ -0,0 +1,24 @@ +package cc.reconnected.server.core.customChat; + +import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.minecraft.entity.damage.DamageTracker; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +public class CustomDeathMessage { + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + + public static Text onDeath(ServerPlayerEntity player, DamageTracker instance) { + var deathMessage = instance.getDeathMessage(); + var deathComponent = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.deathFormat(), + TagResolver.resolver( + Placeholder.component("death_message", deathMessage) + )); + + return Components.toText(deathComponent); + } +} diff --git a/src/main/java/cc/reconnected/server/core/customChat/CustomEmoteMessage.java b/src/main/java/cc/reconnected/server/core/customChat/CustomEmoteMessage.java new file mode 100644 index 0000000..be95383 --- /dev/null +++ b/src/main/java/cc/reconnected/server/core/customChat/CustomEmoteMessage.java @@ -0,0 +1,41 @@ +package cc.reconnected.server.core.customChat; + +import cc.reconnected.server.RccServer; +import cc.reconnected.server.parser.MarkdownParser; +import cc.reconnected.server.util.Components; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.minecraft.network.message.MessageType; +import net.minecraft.network.message.SignedMessage; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +public class CustomEmoteMessage { + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + + public static void sendEmoteMessage(ServerPlayerEntity receiver, SignedMessage message, MessageType.Parameters params) { + var playerUuid = message.link().sender(); + var player = RccServer.server.getPlayerManager().getPlayer(playerUuid); + + Text messageText; + if (RccServer.CONFIG.customChatFormat.enableMarkdown()) { + messageText = MarkdownParser.defaultParser.parseNode(message.getSignedContent()).toText(); + } else { + messageText = message.getContent(); + } + + var component = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.emoteFormat(), TagResolver.resolver( + Placeholder.component("display_name", player.getDisplayName()), + Placeholder.component("message", messageText) + )); + + var text = Components.toText(component); + + var msgType = RccServer.server.getRegistryManager().get(RegistryKeys.MESSAGE_TYPE).getOrThrow(RccServer.CHAT_TYPE); + var newParams = new MessageType.Parameters(msgType, text, null); + + receiver.networkHandler.sendChatMessage(message, newParams); + } +} diff --git a/src/main/java/cc/reconnected/server/core/customChat/CustomSentMessage.java b/src/main/java/cc/reconnected/server/core/customChat/CustomSentMessage.java new file mode 100644 index 0000000..1627420 --- /dev/null +++ b/src/main/java/cc/reconnected/server/core/customChat/CustomSentMessage.java @@ -0,0 +1,36 @@ +package cc.reconnected.server.core.customChat; + +import cc.reconnected.server.RccServer; +import net.minecraft.network.message.MessageType; +import net.minecraft.network.message.SentMessage; +import net.minecraft.network.message.SignedMessage; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +public record CustomSentMessage(SignedMessage message) implements SentMessage { + + @Override + public Text getContent() { + return this.message.getContent(); + } + + @Override + public void send(ServerPlayerEntity receiver, boolean filterMaskEnabled, MessageType.Parameters params) { + SignedMessage signedMessage = this.message.withFilterMaskEnabled(filterMaskEnabled); + RccServer.LOGGER.info("Message params type: {}", params.type().chat().translationKey()); + if (!signedMessage.isFullyFiltered()) { + switch (params.type().chat().translationKey()) { + case "chat.type.text": + CustomChatMessage.sendChatMessage(receiver, message, params); + break; + case "chat.type.emote": + CustomEmoteMessage.sendEmoteMessage(receiver, message, params); + break; + default: + receiver.networkHandler.sendChatMessage(this.message, params); + break; + } + } + } + +} diff --git a/src/main/java/cc/reconnected/server/mixin/PlayerEntityMixin.java b/src/main/java/cc/reconnected/server/mixin/PlayerEntityMixin.java new file mode 100644 index 0000000..412098b --- /dev/null +++ b/src/main/java/cc/reconnected/server/mixin/PlayerEntityMixin.java @@ -0,0 +1,33 @@ +package cc.reconnected.server.mixin; + +import cc.reconnected.server.core.CustomNameFormat; +import com.mojang.authlib.GameProfile; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PlayerEntity.class) +public abstract class PlayerEntityMixin { + @Shadow + private MutableText addTellClickEvent(MutableText component) { + return null; + } + + @Shadow + public abstract Text getName(); + + @Shadow + public abstract GameProfile getGameProfile(); + + @Inject(method = "getDisplayName", at = @At("HEAD"), cancellable = true) + public void getDisplayName(CallbackInfoReturnable cir) { + var name = CustomNameFormat.getNameForPlayer((ServerPlayerEntity) (Object) this); + cir.setReturnValue(addTellClickEvent(name)); + } +} diff --git a/src/main/java/cc/reconnected/server/mixin/PlayerManagerMixin.java b/src/main/java/cc/reconnected/server/mixin/PlayerManagerMixin.java new file mode 100644 index 0000000..49f7c25 --- /dev/null +++ b/src/main/java/cc/reconnected/server/mixin/PlayerManagerMixin.java @@ -0,0 +1,42 @@ +package cc.reconnected.server.mixin; + +import cc.reconnected.server.core.customChat.CustomConnectionMessage; +import net.minecraft.network.ClientConnection; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableTextContent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(PlayerManager.class) +public class PlayerManagerMixin { + @Unique + private ServerPlayerEntity rccServer$player = null; + + @Inject(method="onPlayerConnect", at = @At("HEAD")) + private void rccServer$onJoin(ClientConnection connection, ServerPlayerEntity player, CallbackInfo ci) { + rccServer$player = player; + } + + @Inject(method="onPlayerConnect", at = @At("RETURN")) + private void rccServer$onJoinReturn(ClientConnection connection, ServerPlayerEntity player, CallbackInfo ci) { + rccServer$player = null; + } + + @ModifyArg(method = "onPlayerConnect", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")) + public Text rccServer$getPlayerJoinMessage(Text message) { + var ogText = (TranslatableTextContent) message.getContent(); + var args = ogText.getArgs(); + + if (args.length == 1) { + return CustomConnectionMessage.onJoin(rccServer$player); + } else { + return CustomConnectionMessage.onJoinRenamed(rccServer$player, (String) args[1]); + } + } +} diff --git a/src/main/java/cc/reconnected/server/mixin/RegistryLoaderMixin.java b/src/main/java/cc/reconnected/server/mixin/RegistryLoaderMixin.java new file mode 100644 index 0000000..a8b5f55 --- /dev/null +++ b/src/main/java/cc/reconnected/server/mixin/RegistryLoaderMixin.java @@ -0,0 +1,36 @@ +package cc.reconnected.server.mixin; + +import cc.reconnected.server.RccServer; +import com.mojang.datafixers.util.Pair; +import net.minecraft.network.message.MessageType; +import net.minecraft.registry.*; +import net.minecraft.resource.ResourceManager; +import net.minecraft.text.Decoration; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.List; +import java.util.Map; + +@Mixin(RegistryLoader.class) +public class RegistryLoaderMixin { + + @Inject(method = "load(Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/registry/DynamicRegistryManager;Ljava/util/List;)Lnet/minecraft/registry/DynamicRegistryManager$Immutable;", at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 0, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILEXCEPTION) + private static void rccServer$load(ResourceManager resourceManager, DynamicRegistryManager baseRegistryManager, List> entries, + CallbackInfoReturnable cir, Map _unused, List, Object>> list) { + for (var pair : list) { + var registry = pair.getFirst(); + if(registry.getKey().equals(RegistryKeys.MESSAGE_TYPE)) { + Registry.register((Registry) registry, RccServer.CHAT_TYPE, + new MessageType( + Decoration.ofChat("%s"), + Decoration.ofChat("%s") + )); + } + } + } + +} diff --git a/src/main/java/cc/reconnected/server/mixin/SentMessageMixin.java b/src/main/java/cc/reconnected/server/mixin/SentMessageMixin.java new file mode 100644 index 0000000..d26b131 --- /dev/null +++ b/src/main/java/cc/reconnected/server/mixin/SentMessageMixin.java @@ -0,0 +1,23 @@ +package cc.reconnected.server.mixin; + +import cc.reconnected.server.core.customChat.CustomSentMessage; +import net.minecraft.network.message.SentMessage; +import net.minecraft.network.message.SignedMessage; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(SentMessage.class) +public interface SentMessageMixin { + + @Inject(method = "of", at = @At("HEAD"), cancellable = true) + private static void rccServer$of(SignedMessage message, CallbackInfoReturnable cir) { + + if(message.isSenderMissing()) { + cir.setReturnValue(new SentMessage.Profileless(message.getContent())); + } else { + cir.setReturnValue(new CustomSentMessage(message)); + } + } +} diff --git a/src/main/java/cc/reconnected/server/mixin/ServerPlayNetworkManagerMixin.java b/src/main/java/cc/reconnected/server/mixin/ServerPlayNetworkManagerMixin.java index dcf140a..cf47672 100644 --- a/src/main/java/cc/reconnected/server/mixin/ServerPlayNetworkManagerMixin.java +++ b/src/main/java/cc/reconnected/server/mixin/ServerPlayNetworkManagerMixin.java @@ -1,16 +1,20 @@ package cc.reconnected.server.mixin; import cc.reconnected.server.RccServer; +import cc.reconnected.server.core.customChat.CustomConnectionMessage; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableTextContent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.EnumSet; @@ -24,9 +28,6 @@ public abstract class ServerPlayNetworkManagerMixin { @Shadow public ServerPlayerEntity player; - @Shadow - public abstract void sendPacket(Packet packet); - @Inject(method = "tick", at = @At("TAIL")) private void rccServer$updatePlayerList(CallbackInfo ci) { if(RccServer.CONFIG.customTabList.enableTabList()) { @@ -35,5 +36,8 @@ public abstract class ServerPlayNetworkManagerMixin { } } - + @ModifyArg(method = "onDisconnected", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")) + private Text rccServer$getPlayerLeaveMessage(Text message) { + return CustomConnectionMessage.onLeave(this.player); + } } diff --git a/src/main/java/cc/reconnected/server/mixin/ServerPlayerEntityMixin.java b/src/main/java/cc/reconnected/server/mixin/ServerPlayerEntityMixin.java index c798bf0..12c98dc 100644 --- a/src/main/java/cc/reconnected/server/mixin/ServerPlayerEntityMixin.java +++ b/src/main/java/cc/reconnected/server/mixin/ServerPlayerEntityMixin.java @@ -1,16 +1,19 @@ package cc.reconnected.server.mixin; import cc.reconnected.server.RccServer; +import cc.reconnected.server.core.customChat.CustomDeathMessage; import eu.pb4.placeholders.api.PlaceholderContext; import eu.pb4.placeholders.api.Placeholders; import eu.pb4.placeholders.api.parsers.NodeParser; import eu.pb4.placeholders.api.parsers.TextParserV1; +import net.minecraft.entity.damage.DamageTracker; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ServerPlayerEntity.class) @@ -27,4 +30,10 @@ public class ServerPlayerEntityMixin { callback.setReturnValue(text); } } + + @Redirect(method = "onDeath", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/damage/DamageTracker;getDeathMessage()Lnet/minecraft/text/Text;")) + private Text rccServer$getDeathMessage(DamageTracker instance) { + var player = (ServerPlayerEntity) (Object) this; + return CustomDeathMessage.onDeath(player, instance); + } } diff --git a/src/main/java/cc/reconnected/server/util/Components.java b/src/main/java/cc/reconnected/server/util/Components.java index f622527..ae8cd2b 100644 --- a/src/main/java/cc/reconnected/server/util/Components.java +++ b/src/main/java/cc/reconnected/server/util/Components.java @@ -6,6 +6,7 @@ import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; +import net.minecraft.text.MutableText; import net.minecraft.text.Text; public class Components { @@ -19,7 +20,7 @@ public class Components { .clickEvent(ClickEvent.runCommand(command)); } - public static Text toText(Component component) { + public static MutableText toText(Component component) { var json = JSONComponentSerializer.json().serialize(component); return Text.Serializer.fromJson(json); } diff --git a/src/main/resources/rcc-server.mixins.json b/src/main/resources/rcc-server.mixins.json index b7f77c1..1e6a1e3 100644 --- a/src/main/resources/rcc-server.mixins.json +++ b/src/main/resources/rcc-server.mixins.json @@ -4,12 +4,17 @@ "package": "cc.reconnected.server.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "ServerPlayNetworkManagerMixin" ], "client": [], "server": [ "MessageCommandMixin", - "ServerPlayerEntityMixin" + "PlayerEntityMixin", + "RegistryLoaderMixin", + "SentMessageMixin", + "ServerPlayerEntityMixin", + "ServerPlayNetworkManagerMixin", + "PlayerManagerMixin" + ], "injectors": { "defaultRequire": 1