From 822a8607565e8940e0f30c17f66791d5b97cc13a Mon Sep 17 00:00:00 2001 From: Alessandro Proto Date: Fri, 8 Nov 2024 19:41:08 +0100 Subject: [PATCH] Merge pull request #8 * WIP * Make most Texts customizable from config. * Minor changes * Remove unused args in commands --- .../java/cc/reconnected/server/RccServer.java | 97 +++++++++----- .../cc/reconnected/server/api/PlayerMeta.java | 5 +- .../server/commands/admin/FlyCommand.java | 7 +- .../server/commands/admin/GodCommand.java | 4 +- .../server/commands/admin/RccCommand.java | 4 +- .../server/commands/admin/RestartCommand.java | 7 +- .../server/commands/admin/TimeBarCommand.java | 7 +- .../commands/home/DeleteHomeCommand.java | 33 +++-- .../server/commands/home/HomeCommand.java | 39 +++--- .../server/commands/home/SetHomeCommand.java | 53 ++++---- .../server/commands/misc/AfkCommand.java | 4 +- .../server/commands/misc/NearCommand.java | 54 +++++--- .../commands/spawn/SetSpawnCommand.java | 4 +- .../server/commands/spawn/SpawnCommand.java | 15 ++- .../{misc => teleport}/BackCommand.java | 21 ++-- .../teleport/TeleportAcceptCommand.java | 64 +++++++--- .../commands/teleport/TeleportAskCommand.java | 57 ++++++--- .../teleport/TeleportAskHereCommand.java | 53 +++++--- .../teleport/TeleportDenyCommand.java | 44 +++++-- .../server/commands/tell/ReplyCommand.java | 19 +-- .../server/commands/tell/TellCommand.java | 99 ++++++++++----- .../commands/warp/DeleteWarpCommand.java | 4 +- .../server/commands/warp/SetWarpCommand.java | 7 +- .../server/commands/warp/WarpCommand.java | 33 ++--- .../cc/reconnected/server/config/Config.java | 118 +++++++++++++++--- .../server/config/ConfigManager.java | 1 - .../reconnected/server/core/AfkTracker.java | 35 ++---- .../reconnected/server/core/AutoRestart.java | 2 +- .../server/core/HttpApiServer.java | 2 +- .../core/customChat/CustomChatMessage.java | 36 +++--- .../customChat/CustomConnectionMessage.java | 39 +++--- .../core/customChat/CustomDeathMessage.java | 20 +-- .../core/customChat/CustomEmoteMessage.java | 23 ++-- .../server/core/customChat/Utils.java | 32 ----- .../server/mixin/SentMessageMixin.java | 2 +- .../reconnected/server/parser/LinkParser.java | 99 +++++++++++++++ .../parser/MarkdownComponentParser.java | 24 ++-- .../server/parser/MarkdownParser.java | 4 +- .../reconnected/server/util/Components.java | 110 ++++++++++++++++ 39 files changed, 865 insertions(+), 416 deletions(-) rename src/main/java/cc/reconnected/server/commands/{misc => teleport}/BackCommand.java (61%) delete mode 100644 src/main/java/cc/reconnected/server/core/customChat/Utils.java create mode 100644 src/main/java/cc/reconnected/server/parser/LinkParser.java diff --git a/src/main/java/cc/reconnected/server/RccServer.java b/src/main/java/cc/reconnected/server/RccServer.java index d7342d4..4ae55a6 100644 --- a/src/main/java/cc/reconnected/server/RccServer.java +++ b/src/main/java/cc/reconnected/server/RccServer.java @@ -2,30 +2,44 @@ package cc.reconnected.server; import cc.reconnected.server.api.events.RccEvents; import cc.reconnected.server.commands.admin.*; -import cc.reconnected.server.commands.home.*; -import cc.reconnected.server.commands.misc.*; -import cc.reconnected.server.commands.spawn.*; -import cc.reconnected.server.commands.teleport.*; -import cc.reconnected.server.commands.tell.*; -import cc.reconnected.server.commands.warp.*; +import cc.reconnected.server.commands.home.DeleteHomeCommand; +import cc.reconnected.server.commands.home.HomeCommand; +import cc.reconnected.server.commands.home.SetHomeCommand; +import cc.reconnected.server.commands.misc.AfkCommand; +import cc.reconnected.server.commands.teleport.BackCommand; +import cc.reconnected.server.commands.misc.NearCommand; +import cc.reconnected.server.commands.spawn.SetSpawnCommand; +import cc.reconnected.server.commands.spawn.SpawnCommand; +import cc.reconnected.server.commands.teleport.TeleportAcceptCommand; +import cc.reconnected.server.commands.teleport.TeleportAskCommand; +import cc.reconnected.server.commands.teleport.TeleportAskHereCommand; +import cc.reconnected.server.commands.teleport.TeleportDenyCommand; +import cc.reconnected.server.commands.tell.ReplyCommand; +import cc.reconnected.server.commands.tell.TellCommand; +import cc.reconnected.server.commands.warp.DeleteWarpCommand; +import cc.reconnected.server.commands.warp.SetWarpCommand; +import cc.reconnected.server.commands.warp.WarpCommand; import cc.reconnected.server.config.Config; import cc.reconnected.server.config.ConfigManager; import cc.reconnected.server.core.*; +import cc.reconnected.server.core.customChat.CustomChatMessage; import cc.reconnected.server.data.StateManager; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; - +import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; 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.network.message.SignedMessage; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKeys; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.WorldSavePath; import org.slf4j.Logger; @@ -84,38 +98,37 @@ public class RccServer implements ModInitializer { ServerLifecycleEvents.SERVER_STOPPED.register(server -> this.adventure = null); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { - RccCommand.register(dispatcher, registryAccess, environment); + RccCommand.register(dispatcher); - AfkCommand.register(dispatcher, registryAccess, environment); + AfkCommand.register(dispatcher); - TellCommand.register(dispatcher, registryAccess, environment); - ReplyCommand.register(dispatcher, registryAccess, environment); + TellCommand.register(dispatcher); + ReplyCommand.register(dispatcher); - TeleportAskCommand.register(dispatcher, registryAccess, environment); - TeleportAskHereCommand.register(dispatcher, registryAccess, environment); - TeleportAcceptCommand.register(dispatcher, registryAccess, environment); - TeleportDenyCommand.register(dispatcher, registryAccess, environment); + TeleportAskCommand.register(dispatcher); + TeleportAskHereCommand.register(dispatcher); + TeleportAcceptCommand.register(dispatcher); + TeleportDenyCommand.register(dispatcher); + BackCommand.register(dispatcher); - BackCommand.register(dispatcher, registryAccess, environment); + FlyCommand.register(dispatcher); + GodCommand.register(dispatcher); - FlyCommand.register(dispatcher, registryAccess, environment); - GodCommand.register(dispatcher, registryAccess, environment); + SetSpawnCommand.register(dispatcher); + SpawnCommand.register(dispatcher); - SetSpawnCommand.register(dispatcher, registryAccess, environment); - SpawnCommand.register(dispatcher, registryAccess, environment); + HomeCommand.register(dispatcher); + SetHomeCommand.register(dispatcher); + DeleteHomeCommand.register(dispatcher); - HomeCommand.register(dispatcher, registryAccess, environment); - SetHomeCommand.register(dispatcher, registryAccess, environment); - DeleteHomeCommand.register(dispatcher, registryAccess, environment); + WarpCommand.register(dispatcher); + SetWarpCommand.register(dispatcher); + DeleteWarpCommand.register(dispatcher); - WarpCommand.register(dispatcher, registryAccess, environment); - SetWarpCommand.register(dispatcher, registryAccess, environment); - DeleteWarpCommand.register(dispatcher, registryAccess, environment); + TimeBarCommand.register(dispatcher); + RestartCommand.register(dispatcher); - TimeBarCommand.register(dispatcher, registryAccess, environment); - RestartCommand.register(dispatcher, registryAccess, environment); - - NearCommand.register(dispatcher, registryAccess, environment); + NearCommand.register(dispatcher); }); AfkTracker.register(); @@ -156,9 +169,31 @@ public class RccServer implements ModInitializer { }); } - public void broadcastMessage(MinecraftServer server, Component message) { + public void broadcastComponent(MinecraftServer server, Component message) { for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) { player.sendMessage(message); } } + + public void broadcast(Text text) { + server.getPlayerManager().broadcast(text, false); + } + + public void sendChatAsPlayer(ServerPlayerEntity player, String message) { + var msgType = server.getRegistryManager().get(RegistryKeys.MESSAGE_TYPE).getOrThrow(MessageType.CHAT); + var signedMessage = SignedMessage.ofUnsigned(player.getUuid(), message); + var pars = new MessageType.Parameters(msgType, Text.of(message), Text.of(message)); + + var allowed = ServerMessageEvents.ALLOW_CHAT_MESSAGE.invoker().allowChatMessage(signedMessage, player, pars); + if (!allowed) + return; + + ServerMessageEvents.CHAT_MESSAGE.invoker().onChatMessage(signedMessage, player, pars); + + var formatted = CustomChatMessage.getFormattedMessage(signedMessage, player); + for (var pl : server.getPlayerManager().getPlayerList()) { + pl.sendMessage(formatted); + } + } + } \ No newline at end of file diff --git a/src/main/java/cc/reconnected/server/api/PlayerMeta.java b/src/main/java/cc/reconnected/server/api/PlayerMeta.java index 6ba57cb..7f7d585 100644 --- a/src/main/java/cc/reconnected/server/api/PlayerMeta.java +++ b/src/main/java/cc/reconnected/server/api/PlayerMeta.java @@ -12,7 +12,10 @@ import org.jetbrains.annotations.Nullable; import java.time.Instant; import java.time.format.DateTimeFormatter; -import java.util.*; +import java.util.Date; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; diff --git a/src/main/java/cc/reconnected/server/commands/admin/FlyCommand.java b/src/main/java/cc/reconnected/server/commands/admin/FlyCommand.java index 83e4bae..77f1a7c 100644 --- a/src/main/java/cc/reconnected/server/commands/admin/FlyCommand.java +++ b/src/main/java/cc/reconnected/server/commands/admin/FlyCommand.java @@ -3,19 +3,18 @@ package cc.reconnected.server.commands.admin; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -import static net.minecraft.server.command.CommandManager.*; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class FlyCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("fly") .requires(Permissions.require("rcc.command.fly", 3)) .executes(context -> { diff --git a/src/main/java/cc/reconnected/server/commands/admin/GodCommand.java b/src/main/java/cc/reconnected/server/commands/admin/GodCommand.java index 64f0c43..14eac18 100644 --- a/src/main/java/cc/reconnected/server/commands/admin/GodCommand.java +++ b/src/main/java/cc/reconnected/server/commands/admin/GodCommand.java @@ -3,9 +3,7 @@ package cc.reconnected.server.commands.admin; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Style; @@ -16,7 +14,7 @@ import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; public class GodCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("god") .requires(Permissions.require("rcc.command.god", 3)) .executes(context -> { diff --git a/src/main/java/cc/reconnected/server/commands/admin/RccCommand.java b/src/main/java/cc/reconnected/server/commands/admin/RccCommand.java index 9e7941a..e2724b8 100644 --- a/src/main/java/cc/reconnected/server/commands/admin/RccCommand.java +++ b/src/main/java/cc/reconnected/server/commands/admin/RccCommand.java @@ -5,15 +5,13 @@ import cc.reconnected.server.api.events.RccEvents; import cc.reconnected.server.config.ConfigManager; import com.mojang.brigadier.CommandDispatcher; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import static net.minecraft.server.command.CommandManager.literal; public class RccCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("rcc") .requires(Permissions.require("rcc.command.rcc", 3)) .then(literal("reload") diff --git a/src/main/java/cc/reconnected/server/commands/admin/RestartCommand.java b/src/main/java/cc/reconnected/server/commands/admin/RestartCommand.java index 79db548..ad9256b 100644 --- a/src/main/java/cc/reconnected/server/commands/admin/RestartCommand.java +++ b/src/main/java/cc/reconnected/server/commands/admin/RestartCommand.java @@ -7,17 +7,16 @@ import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import org.jetbrains.annotations.Nullable; -import static net.minecraft.server.command.CommandManager.*; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class RestartCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("restart") .requires(Permissions.require("rcc.command.restart", 4)) .then(literal("schedule") diff --git a/src/main/java/cc/reconnected/server/commands/admin/TimeBarCommand.java b/src/main/java/cc/reconnected/server/commands/admin/TimeBarCommand.java index e30f389..7712b74 100644 --- a/src/main/java/cc/reconnected/server/commands/admin/TimeBarCommand.java +++ b/src/main/java/cc/reconnected/server/commands/admin/TimeBarCommand.java @@ -9,11 +9,9 @@ import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; import net.minecraft.command.argument.UuidArgumentType; import net.minecraft.entity.boss.BossBar; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.ClickEvent; import net.minecraft.text.HoverEvent; @@ -25,12 +23,13 @@ import java.util.Arrays; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; -import static net.minecraft.server.command.CommandManager.*; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class TimeBarCommand { private static final ConcurrentHashMap runningBars = new ConcurrentHashMap<>(); - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("timebar") .requires(Permissions.require("rcc.command.timebar", 3)) .then(literal("start") diff --git a/src/main/java/cc/reconnected/server/commands/home/DeleteHomeCommand.java b/src/main/java/cc/reconnected/server/commands/home/DeleteHomeCommand.java index 5f3c1fb..7f85b7d 100644 --- a/src/main/java/cc/reconnected/server/commands/home/DeleteHomeCommand.java +++ b/src/main/java/cc/reconnected/server/commands/home/DeleteHomeCommand.java @@ -1,22 +1,23 @@ package cc.reconnected.server.commands.home; import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; +import eu.pb4.placeholders.api.PlaceholderContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; + +import java.util.Map; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; public class DeleteHomeCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("delhome") .requires(Permissions.require("rcc.command.delhome", true)) .executes(context -> execute(context, "home")) @@ -41,23 +42,29 @@ public class DeleteHomeCommand { var player = context.getSource().getPlayer(); var playerState = RccServer.state.getPlayerState(player.getUuid()); var homes = playerState.homes; + var playerContext = PlaceholderContext.of(context.getSource().getPlayer()); + + var placeholders = Map.of( + "home", Text.of(name) + ); if (!homes.containsKey(name)) { - context.getSource().sendFeedback(() -> Text.literal("The home ") - .append(Text.literal(name).formatted(Formatting.GOLD)) - .append(" does not exist!") - .formatted(Formatting.RED), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.home.homeNotFound, + playerContext, + placeholders + ), false); return 1; } homes.remove(name); RccServer.state.savePlayerState(player.getUuid(), playerState); - context.getSource().sendFeedback(() -> Text - .literal("Home ") - .append(Text.literal(name).formatted(Formatting.GOLD)) - .append(" deleted!") - .formatted(Formatting.GREEN), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.home.homeDeleted, + playerContext, + placeholders + ), false); return 1; } diff --git a/src/main/java/cc/reconnected/server/commands/home/HomeCommand.java b/src/main/java/cc/reconnected/server/commands/home/HomeCommand.java index dcdd39c..1b6831f 100644 --- a/src/main/java/cc/reconnected/server/commands/home/HomeCommand.java +++ b/src/main/java/cc/reconnected/server/commands/home/HomeCommand.java @@ -1,21 +1,23 @@ package cc.reconnected.server.commands.home; import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; +import eu.pb4.placeholders.api.PlaceholderContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import static net.minecraft.server.command.CommandManager.*; +import java.util.Map; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class HomeCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("home") .requires(Permissions.require("rcc.command.home", true)) .executes(context -> execute(context, "home")) @@ -40,20 +42,29 @@ public class HomeCommand { var player = context.getSource().getPlayer(); var playerState = RccServer.state.getPlayerState(player.getUuid()); var homes = playerState.homes; + var playerContext = PlaceholderContext.of(context.getSource().getPlayer()); + + var placeholders = Map.of( + "home", Text.of(name) + ); if (!homes.containsKey(name)) { - context.getSource().sendFeedback(() -> Text.literal("The home ") - .append(Text.literal(name).formatted(Formatting.GOLD)) - .append(" does not exist!") - .formatted(Formatting.RED), false); + context.getSource().sendFeedback(() -> + Components.parse( + RccServer.CONFIG.textFormats.commands.home.homeNotFound, + playerContext, + placeholders + ), false); + return 1; } - context.getSource().sendFeedback(() -> Text - .literal("Teleporting to ") - .append(Text.literal(name).formatted(Formatting.GREEN)) - .append("...") - .formatted(Formatting.GOLD), false); + context.getSource().sendFeedback(() -> + Components.parse( + RccServer.CONFIG.textFormats.commands.home.teleporting, + playerContext, + placeholders + ), false); var homePosition = homes.get(name); homePosition.teleport(player); diff --git a/src/main/java/cc/reconnected/server/commands/home/SetHomeCommand.java b/src/main/java/cc/reconnected/server/commands/home/SetHomeCommand.java index ab67031..27cb1c3 100644 --- a/src/main/java/cc/reconnected/server/commands/home/SetHomeCommand.java +++ b/src/main/java/cc/reconnected/server/commands/home/SetHomeCommand.java @@ -7,19 +7,18 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; +import eu.pb4.placeholders.api.PlaceholderContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import static net.minecraft.server.command.CommandManager.*; +import java.util.Map; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class SetHomeCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("sethome") .requires(Permissions.require("rcc.command.sethome", true)) .executes(context -> execute(context, @@ -44,27 +43,38 @@ public class SetHomeCommand { } var player = context.getSource().getPlayer(); var playerState = RccServer.state.getPlayerState(player.getUuid()); - var homes = playerState.homes; + var playerContext = PlaceholderContext.of(player); + + var placeholders = Map.of( + "home", Text.of(name), + "forceSetButton", Components.button( + RccServer.CONFIG.textFormats.commands.home.forceSetLabel, + RccServer.CONFIG.textFormats.commands.home.forceSetHover, + "/sethome " + name + " true" + ) + ); var exists = homes.containsKey(name); if (exists && !forced) { - var text = Component.text("You already have set this home.") - .appendNewline().appendSpace() - .append(Components.makeButton( - Component.text("Force set home", NamedTextColor.GOLD), - Component.text("Click to force set the home"), - "/sethome " + name + " true" - )); + var text = Components.parse( + RccServer.CONFIG.textFormats.commands.home.homeExists, + playerContext, + placeholders + ); - context.getSource().sendFailure(text); + context.getSource().sendFeedback(() -> text, false); return 1; } var maxHomes = RccServer.CONFIG.homes.maxHomes; if(homes.size() >= maxHomes && !exists) { - context.getSource().sendFeedback(() -> Text.literal("You have reached the maximum amount of homes!").formatted(Formatting.RED), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.home.maxHomesReached, + playerContext, + placeholders + ), false); return 1; } @@ -73,10 +83,11 @@ public class SetHomeCommand { RccServer.state.savePlayerState(player.getUuid(), playerState); - context.getSource().sendFeedback(() -> Text.literal("New home ") - .append(Text.literal(name).formatted(Formatting.GOLD)) - .append(" set!") - .formatted(Formatting.GREEN), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.home.homeSetSuccess, + playerContext, + placeholders + ), false); return 1; } diff --git a/src/main/java/cc/reconnected/server/commands/misc/AfkCommand.java b/src/main/java/cc/reconnected/server/commands/misc/AfkCommand.java index c65bd20..904e900 100644 --- a/src/main/java/cc/reconnected/server/commands/misc/AfkCommand.java +++ b/src/main/java/cc/reconnected/server/commands/misc/AfkCommand.java @@ -3,15 +3,13 @@ package cc.reconnected.server.commands.misc; import cc.reconnected.server.core.AfkTracker; import com.mojang.brigadier.CommandDispatcher; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import static net.minecraft.server.command.CommandManager.literal; public class AfkCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("afk") .requires(Permissions.require("rcc.command.afk", true)) .executes(context -> { diff --git a/src/main/java/cc/reconnected/server/commands/misc/NearCommand.java b/src/main/java/cc/reconnected/server/commands/misc/NearCommand.java index a17cf3d..b4f6946 100644 --- a/src/main/java/cc/reconnected/server/commands/misc/NearCommand.java +++ b/src/main/java/cc/reconnected/server/commands/misc/NearCommand.java @@ -1,24 +1,25 @@ package cc.reconnected.server.commands.misc; import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.context.CommandContext; +import eu.pb4.placeholders.api.PlaceholderContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.ArrayList; import java.util.Comparator; +import java.util.Map; -import static net.minecraft.server.command.CommandManager.*; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class NearCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("near") .requires(Permissions.require("rcc.command.near", 2)) .executes(context -> { @@ -41,6 +42,7 @@ public class NearCommand { } private static int execute(CommandContext context, int range, ServerPlayerEntity sourcePlayer) { + var playerContext = PlaceholderContext.of(sourcePlayer); var list = new ArrayList(); var sourcePos = sourcePlayer.getPos(); @@ -48,35 +50,53 @@ public class NearCommand { var targetPos = targetPlayer.getPos(); if (!sourcePlayer.getUuid().equals(targetPlayer.getUuid()) && sourcePos.isInRange(targetPos, range)) { var distance = sourcePos.distanceTo(targetPos); - list.add(new ClosePlayers(targetPlayer.getDisplayName(), distance)); + list.add(new ClosePlayers(targetPlayer, distance)); } }); - if(list.isEmpty()) { - context.getSource().sendFeedback(() -> Text.literal("There is no one near you.").formatted(Formatting.GOLD), false); + if (list.isEmpty()) { + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.near.noOne, + playerContext + ), false); return 1; } list.sort(Comparator.comparingDouble(ClosePlayers::distance)); - var text = Text.empty().append(Text.literal("Nearest players: ").formatted(Formatting.GOLD)); - var comma = Text.literal(", ").formatted(Formatting.GOLD); + var listText = Text.empty(); + var comma = Components.parse(RccServer.CONFIG.textFormats.commands.near.comma); for (int i = 0; i < list.size(); i++) { var player = list.get(i); if (i > 0) { - text = text.append(comma); + listText = listText.append(comma); } - text = text.append(player.displayName) - .append(" ") - .append(Text.literal(String.format("(%.1fm)", player.distance)).formatted(Formatting.GREEN)); + var placeholders = Map.of( + "player", player.player.getDisplayName(), + "distance", Text.of(String.format("%.1fm", player.distance)) + ); + + var targetContext = PlaceholderContext.of(sourcePlayer); + + listText = listText.append(Components.parse( + RccServer.CONFIG.textFormats.commands.near.format, + targetContext, + placeholders + )); } - final var finalText = text; - context.getSource().sendFeedback(() -> finalText, false); + var placeholders = Map.of( + "playerList", (Text) listText + ); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.near.nearestPlayers, + playerContext, + placeholders + ), false); return 1; } - private record ClosePlayers(Text displayName, double distance) { + private record ClosePlayers(ServerPlayerEntity player, double distance) { } } diff --git a/src/main/java/cc/reconnected/server/commands/spawn/SetSpawnCommand.java b/src/main/java/cc/reconnected/server/commands/spawn/SetSpawnCommand.java index 2962ebc..ed9af8a 100644 --- a/src/main/java/cc/reconnected/server/commands/spawn/SetSpawnCommand.java +++ b/src/main/java/cc/reconnected/server/commands/spawn/SetSpawnCommand.java @@ -4,8 +4,6 @@ import cc.reconnected.server.RccServer; import cc.reconnected.server.struct.ServerPosition; import com.mojang.brigadier.CommandDispatcher; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -13,7 +11,7 @@ import net.minecraft.util.Formatting; import static net.minecraft.server.command.CommandManager.literal; public class SetSpawnCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("setspawn") .requires(Permissions.require("rcc.command.setspawn", 3)) .executes(context -> { diff --git a/src/main/java/cc/reconnected/server/commands/spawn/SpawnCommand.java b/src/main/java/cc/reconnected/server/commands/spawn/SpawnCommand.java index df88fa4..61e0c05 100644 --- a/src/main/java/cc/reconnected/server/commands/spawn/SpawnCommand.java +++ b/src/main/java/cc/reconnected/server/commands/spawn/SpawnCommand.java @@ -2,18 +2,17 @@ package cc.reconnected.server.commands.spawn; import cc.reconnected.server.RccServer; import cc.reconnected.server.struct.ServerPosition; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; +import eu.pb4.placeholders.api.PlaceholderContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import static net.minecraft.server.command.CommandManager.literal; public class SpawnCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("spawn") .requires(Permissions.require("rcc.command.spawn", true)) .executes(context -> { @@ -24,14 +23,18 @@ public class SpawnCommand { var player = context.getSource().getPlayer(); var serverState = RccServer.state.getServerState(); + var playerContext = PlaceholderContext.of(player); var spawnPosition = serverState.spawn; - if(spawnPosition == null) { + if (spawnPosition == null) { var server = context.getSource().getServer(); var spawnPos = server.getOverworld().getSpawnPos(); spawnPosition = new ServerPosition(spawnPos.getX(), spawnPos.getY(), spawnPos.getZ(), 0, 0, server.getOverworld()); } - context.getSource().sendFeedback(() -> Text.literal("Teleporting to spawn...").formatted(Formatting.GOLD), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.spawn.teleporting, + playerContext + ), false); spawnPosition.teleport(player); return 1; diff --git a/src/main/java/cc/reconnected/server/commands/misc/BackCommand.java b/src/main/java/cc/reconnected/server/commands/teleport/BackCommand.java similarity index 61% rename from src/main/java/cc/reconnected/server/commands/misc/BackCommand.java rename to src/main/java/cc/reconnected/server/commands/teleport/BackCommand.java index 6038079..538d84d 100644 --- a/src/main/java/cc/reconnected/server/commands/misc/BackCommand.java +++ b/src/main/java/cc/reconnected/server/commands/teleport/BackCommand.java @@ -1,18 +1,18 @@ -package cc.reconnected.server.commands.misc; +package cc.reconnected.server.commands.teleport; +import cc.reconnected.server.RccServer; import cc.reconnected.server.core.BackTracker; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; +import eu.pb4.placeholders.api.PlaceholderContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import static net.minecraft.server.command.CommandManager.literal; public class BackCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("back") .requires(Permissions.require("rcc.command.back", true)) .executes(context -> { @@ -22,14 +22,21 @@ public class BackCommand { } var player = context.getSource().getPlayer(); + var playerContext = PlaceholderContext.of(player); var lastPosition = BackTracker.lastPlayerPositions.get(player.getUuid()); if (lastPosition == null) { - context.getSource().sendFeedback(() -> Text.literal("There is no position to return back to.").formatted(Formatting.RED), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.back.noPosition, + playerContext + ), false); return 1; } - context.getSource().sendFeedback(() -> Text.literal("Teleporting to previous position...").formatted(Formatting.GOLD), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.back.teleporting, + playerContext + ), false); lastPosition.teleport(player); return 1; diff --git a/src/main/java/cc/reconnected/server/commands/teleport/TeleportAcceptCommand.java b/src/main/java/cc/reconnected/server/commands/teleport/TeleportAcceptCommand.java index bf3b4e2..139ff77 100644 --- a/src/main/java/cc/reconnected/server/commands/teleport/TeleportAcceptCommand.java +++ b/src/main/java/cc/reconnected/server/commands/teleport/TeleportAcceptCommand.java @@ -1,21 +1,23 @@ package cc.reconnected.server.commands.teleport; +import cc.reconnected.server.RccServer; import cc.reconnected.server.core.TeleportTracker; import cc.reconnected.server.struct.ServerPosition; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; -import net.minecraft.command.CommandRegistryAccess; +import eu.pb4.placeholders.api.PlaceholderContext; import net.minecraft.command.argument.UuidArgumentType; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.Style; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import static net.minecraft.server.command.CommandManager.*; +import java.util.Map; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class TeleportAcceptCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var node = dispatcher.register(literal("tpaccept") .executes(context -> { if (!context.getSource().isExecutedByPlayer()) { @@ -23,14 +25,18 @@ public class TeleportAcceptCommand { return 1; } - var playerUuid = context.getSource().getPlayer().getUuid(); + var player = context.getSource().getPlayer(); + var playerUuid = player.getUuid(); var playerRequests = TeleportTracker.teleportRequests.get(playerUuid); - + var playerContext = PlaceholderContext.of(player); var request = playerRequests.pollLast(); if (request == null) { - context.getSource().sendFeedback(() -> Text.literal("You have no pending teleport requests.").setStyle(Style.EMPTY.withColor(Formatting.RED)), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.noPending, + playerContext + ), false); return 1; } @@ -45,13 +51,18 @@ public class TeleportAcceptCommand { return 1; } + var player = context.getSource().getPlayer(); var uuid = UuidArgumentType.getUuid(context, "uuid"); - var playerUuid = context.getSource().getPlayer().getUuid(); + var playerUuid = player.getUuid(); var playerRequests = TeleportTracker.teleportRequests.get(playerUuid); + var playerContext = PlaceholderContext.of(player); var request = playerRequests.stream().filter(req -> req.requestId.equals(uuid)).findFirst().orElse(null); if (request == null) { - context.getSource().sendFeedback(() -> Text.literal("This request expired or is no longer available.").setStyle(Style.EMPTY.withColor(Formatting.RED)), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.unavailable, + playerContext + ), false); return 1; } @@ -74,19 +85,40 @@ public class TeleportAcceptCommand { var sourcePlayer = playerManager.getPlayer(request.player); var targetPlayer = playerManager.getPlayer(request.target); + var playerContext = PlaceholderContext.of(player); + if (sourcePlayer == null || targetPlayer == null) { - context.getSource().sendFeedback(() -> Text.literal("The other player is no longer available.").formatted(Formatting.RED), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.playerUnavailable, + playerContext + ), false); return; } if (player.getUuid().equals(request.target)) { + var sourceContext = PlaceholderContext.of(sourcePlayer); // accepted a tpa from other to self - context.getSource().sendFeedback(() -> Text.literal("Teleport request accepted.").formatted(Formatting.GREEN), false); - sourcePlayer.sendMessage(Text.literal("Teleporting...").formatted(Formatting.GOLD), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.requestAcceptedResult, + playerContext + ), false); + sourcePlayer.sendMessage(Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.teleporting, + sourceContext + ), false); } else { + var targetContext = PlaceholderContext.of(targetPlayer); // accepted a tpa from self to other - context.getSource().sendFeedback(() -> Text.literal("Teleporting...").formatted(Formatting.GOLD), false); - targetPlayer.sendMessage(Text.empty().append(player.getDisplayName()).append(Text.literal(" accepted your teleport request.").formatted(Formatting.GREEN)), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.teleporting, + playerContext + ), false); + + targetPlayer.sendMessage(Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.requestAccepted, + targetContext, + Map.of("player", sourcePlayer.getDisplayName()) + ), false); } var targetPosition = new ServerPosition(targetPlayer); diff --git a/src/main/java/cc/reconnected/server/commands/teleport/TeleportAskCommand.java b/src/main/java/cc/reconnected/server/commands/teleport/TeleportAskCommand.java index bb8d217..d0b2447 100644 --- a/src/main/java/cc/reconnected/server/commands/teleport/TeleportAskCommand.java +++ b/src/main/java/cc/reconnected/server/commands/teleport/TeleportAskCommand.java @@ -1,24 +1,23 @@ package cc.reconnected.server.commands.teleport; +import cc.reconnected.server.RccServer; import cc.reconnected.server.core.TeleportTracker; import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minecraft.command.CommandRegistryAccess; +import eu.pb4.placeholders.api.PlaceholderContext; import net.minecraft.command.CommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.Style; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import static net.minecraft.server.command.CommandManager.*; +import java.util.Map; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class TeleportAskCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var node = dispatcher.register(literal("tpa") .then(argument("player", StringArgumentType.word()) .suggests((context, builder) -> { @@ -47,27 +46,45 @@ public class TeleportAskCommand { var targetName = StringArgumentType.getString(context, "player"); var playerManager = server.getPlayerManager(); var target = playerManager.getPlayer(targetName); + var playerContext = PlaceholderContext.of(player); if (target == null) { - source.sendFeedback(() -> Text.literal("Player \"" + targetName + "\" not found!").setStyle(Style.EMPTY.withColor(Formatting.RED)), false); + var placeholders = Map.of( + "targetPlayer", Text.of(targetName) + ); + source.sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.playerNotFound, + playerContext, + placeholders + ), false); return; } var request = new TeleportTracker.TeleportRequest(player.getUuid(), target.getUuid()); var targetRequests = TeleportTracker.teleportRequests.get(target.getUuid()); targetRequests.addLast(request); + var targetContext = PlaceholderContext.of(target); + var placeholders = Map.of( + "requesterPlayer", player.getDisplayName(), + "acceptButton", Components.button( + RccServer.CONFIG.textFormats.commands.common.accept, + RccServer.CONFIG.textFormats.commands.teleportRequest.hoverAccept, + "/tpaccept " + request.requestId), + "refuseButton", Components.button( + RccServer.CONFIG.textFormats.commands.common.refuse, + RccServer.CONFIG.textFormats.commands.teleportRequest.hoverRefuse, + "/tpdeny " + request.requestId) + ); - var requestMessage = Component.empty() - .append(player.getDisplayName()) - .appendSpace() - .append(Component.text("requested to teleport to you.", NamedTextColor.GOLD)) - .appendNewline().appendSpace() - .append(Components.makeButton(Component.text("Accept", NamedTextColor.GREEN), Component.text("Click to accept request"), "/tpaccept " + request.requestId)) - .appendSpace() - .append(Components.makeButton(Component.text("Refuse", NamedTextColor.RED), Component.text("Click to refuse request"), "/tpdeny " + request.requestId)); + target.sendMessage(Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.pendingTeleport, + targetContext, + placeholders + )); - target.sendMessage(requestMessage); - - source.sendFeedback(() -> Text.literal("Teleport request sent.").setStyle(Style.EMPTY.withColor(Formatting.GREEN)), false); + source.sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.requestSent, + playerContext + ), false); } } diff --git a/src/main/java/cc/reconnected/server/commands/teleport/TeleportAskHereCommand.java b/src/main/java/cc/reconnected/server/commands/teleport/TeleportAskHereCommand.java index b7e043d..5b72006 100644 --- a/src/main/java/cc/reconnected/server/commands/teleport/TeleportAskHereCommand.java +++ b/src/main/java/cc/reconnected/server/commands/teleport/TeleportAskHereCommand.java @@ -1,25 +1,23 @@ package cc.reconnected.server.commands.teleport; +import cc.reconnected.server.RccServer; import cc.reconnected.server.core.TeleportTracker; import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minecraft.command.CommandRegistryAccess; +import eu.pb4.placeholders.api.PlaceholderContext; import net.minecraft.command.CommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.Style; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; + +import java.util.Map; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; public class TeleportAskHereCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var node = dispatcher.register(literal("tpahere") .then(argument("player", StringArgumentType.word()) .suggests((context, builder) -> { @@ -48,8 +46,16 @@ public class TeleportAskHereCommand { var targetName = StringArgumentType.getString(context, "player"); var playerManager = server.getPlayerManager(); var target = playerManager.getPlayer(targetName); + var playerContext = PlaceholderContext.of(player); if (target == null) { - source.sendFeedback(() -> Text.literal("Player \"" + targetName + "\" not found!").setStyle(Style.EMPTY.withColor(Formatting.RED)), false); + var placeholders = Map.of( + "targetPlayer", Text.of(targetName) + ); + source.sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.playerNotFound, + playerContext, + placeholders + ), false); return; } @@ -57,17 +63,28 @@ public class TeleportAskHereCommand { var targetRequests = TeleportTracker.teleportRequests.get(target.getUuid()); targetRequests.addLast(request); - var requestMessage = Component.empty() - .append(player.getDisplayName()) - .appendSpace() - .append(Component.text("requested you to teleport to them.", NamedTextColor.GOLD)) - .appendNewline().appendSpace() - .append(Components.makeButton(Component.text("Accept", NamedTextColor.GREEN), Component.text("Click to accept request"), "/tpaccept " + request.requestId)) - .appendSpace() - .append(Components.makeButton(Component.text("Refuse", NamedTextColor.RED), Component.text("Click to refuse request"), "/tpdeny " + request.requestId)); + var targetContext = PlaceholderContext.of(target); + var placeholders = Map.of( + "requesterPlayer", player.getDisplayName(), + "acceptButton", Components.button( + RccServer.CONFIG.textFormats.commands.common.accept, + RccServer.CONFIG.textFormats.commands.teleportRequest.hoverAccept, + "/tpaccept " + request.requestId), + "refuseButton", Components.button( + RccServer.CONFIG.textFormats.commands.common.refuse, + RccServer.CONFIG.textFormats.commands.teleportRequest.hoverRefuse, + "/tpdeny " + request.requestId) + ); - target.sendMessage(requestMessage); + target.sendMessage(Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.pendingTeleportHere, + targetContext, + placeholders + )); - source.sendFeedback(() -> Text.literal("Teleport request sent.").setStyle(Style.EMPTY.withColor(Formatting.GREEN)), false); + source.sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.requestSent, + playerContext + ), false); } } diff --git a/src/main/java/cc/reconnected/server/commands/teleport/TeleportDenyCommand.java b/src/main/java/cc/reconnected/server/commands/teleport/TeleportDenyCommand.java index 0890e1f..5bc8b5e 100644 --- a/src/main/java/cc/reconnected/server/commands/teleport/TeleportDenyCommand.java +++ b/src/main/java/cc/reconnected/server/commands/teleport/TeleportDenyCommand.java @@ -1,22 +1,23 @@ package cc.reconnected.server.commands.teleport; +import cc.reconnected.server.RccServer; import cc.reconnected.server.core.TeleportTracker; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; -import net.minecraft.command.CommandRegistryAccess; +import eu.pb4.placeholders.api.PlaceholderContext; import net.minecraft.command.argument.UuidArgumentType; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Style; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; + +import java.util.Map; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; public class TeleportDenyCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var node = dispatcher.register(literal("tpdeny") .executes(context -> { if (!context.getSource().isExecutedByPlayer()) { @@ -24,13 +25,18 @@ public class TeleportDenyCommand { return 1; } - var playerUuid = context.getSource().getPlayer().getUuid(); + var player = context.getSource().getPlayer(); + var playerUuid = player.getUuid(); var playerRequests = TeleportTracker.teleportRequests.get(playerUuid); + var playerContext = PlaceholderContext.of(player); var request = playerRequests.pollLast(); if (request == null) { - context.getSource().sendFeedback(() -> Text.literal("You have no pending teleport requests.").setStyle(Style.EMPTY.withColor(Formatting.RED)), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.noPending, + playerContext + ), false); return 1; } @@ -45,13 +51,18 @@ public class TeleportDenyCommand { return 1; } + var player = context.getSource().getPlayer(); var uuid = UuidArgumentType.getUuid(context, "uuid"); - var playerUuid = context.getSource().getPlayer().getUuid(); + var playerUuid = player.getUuid(); var playerRequests = TeleportTracker.teleportRequests.get(playerUuid); + var playerContext = PlaceholderContext.of(player); var request = playerRequests.stream().filter(req -> req.requestId.equals(uuid)).findFirst().orElse(null); if (request == null) { - context.getSource().sendFeedback(() -> Text.literal("This request expired or is no longer available.").setStyle(Style.EMPTY.withColor(Formatting.RED)), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.unavailable, + playerContext + ), false); return 1; } @@ -69,8 +80,8 @@ public class TeleportDenyCommand { request.expire(); var player = source.getPlayer(); - var playerManager = context.getSource().getServer().getPlayerManager(); + var playerContext = PlaceholderContext.of(player); ServerPlayerEntity otherPlayer = null; if (player.getUuid().equals(request.target)) { @@ -80,8 +91,17 @@ public class TeleportDenyCommand { } if (otherPlayer != null) { - otherPlayer.sendMessage(Text.empty().append(player.getDisplayName()).append(Text.literal(" denied your teleport request.").formatted(Formatting.RED))); + var otherContext = PlaceholderContext.of(otherPlayer); + otherPlayer.sendMessage(Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.requestRefused, + otherContext, + Map.of("player", player.getDisplayName()) + ), false); } - context.getSource().sendFeedback(() -> Text.literal("You denied the teleport request.").formatted(Formatting.GOLD), false); + + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.teleportRequest.requestRefusedResult, + playerContext + ), false); } } diff --git a/src/main/java/cc/reconnected/server/commands/tell/ReplyCommand.java b/src/main/java/cc/reconnected/server/commands/tell/ReplyCommand.java index 24ccd44..277f9bb 100644 --- a/src/main/java/cc/reconnected/server/commands/tell/ReplyCommand.java +++ b/src/main/java/cc/reconnected/server/commands/tell/ReplyCommand.java @@ -1,21 +1,20 @@ package cc.reconnected.server.commands.tell; +import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; +import eu.pb4.placeholders.api.PlaceholderContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.Style; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import static net.minecraft.server.command.CommandManager.*; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class ReplyCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var messageNode = dispatcher.register(literal("reply") .requires(Permissions.require("rcc.command.tell", true)) .then(argument("message", StringArgumentType.greedyString()) @@ -30,7 +29,11 @@ public class ReplyCommand { var message = StringArgumentType.getString(context, "message"); if (!TellCommand.lastSender.containsKey(senderName)) { - source.sendFeedback(() -> Text.literal("You have no one to reply to.").setStyle(Style.EMPTY.withColor(Formatting.RED)), false); + var playerContext = PlaceholderContext.of(context.getSource()); + source.sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.tell.noLastSenderReply, + playerContext + ), false); return 1; } diff --git a/src/main/java/cc/reconnected/server/commands/tell/TellCommand.java b/src/main/java/cc/reconnected/server/commands/tell/TellCommand.java index 28ce8e4..401eea0 100644 --- a/src/main/java/cc/reconnected/server/commands/tell/TellCommand.java +++ b/src/main/java/cc/reconnected/server/commands/tell/TellCommand.java @@ -1,34 +1,28 @@ package cc.reconnected.server.commands.tell; import cc.reconnected.server.RccServer; -import cc.reconnected.server.parser.MarkdownParser; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; +import eu.pb4.placeholders.api.PlaceholderContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; -import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Style; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.HashMap; +import java.util.Map; -import static net.minecraft.server.command.CommandManager.*; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class TellCommand { public static final HashMap lastSender = new HashMap<>(); - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var messageNode = dispatcher.register(literal("msg") .requires(Permissions.require("rcc.command.tell", true)) .then(argument("player", StringArgumentType.word()) @@ -63,28 +57,73 @@ public class TellCommand { } else { targetPlayer = source.getServer().getPlayerManager().getPlayer(targetName); if (targetPlayer == null) { - source.sendFeedback(() -> Text.literal("Player \"" + targetName + "\" not found").setStyle(Style.EMPTY.withColor(Formatting.RED)), false); + var placeholders = Map.of( + "targetPlayer", Text.of(targetName) + ); + var sourceContext = PlaceholderContext.of(source); + + source.sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.tell.playerNotFound, + sourceContext, + placeholders + ), false); return; } targetDisplayName = targetPlayer.getDisplayName(); } - var parsedMessage = MarkdownParser.defaultParser.parseNode(message); - var you = Component.text("You", NamedTextColor.GRAY, TextDecoration.ITALIC); - var sourceText = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage, - Placeholder.component("source", you), - Placeholder.component("target", targetDisplayName), - Placeholder.component("message", parsedMessage.toText())); + var parsedMessage = Components.chat(message, source); - var targetText = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage, - Placeholder.component("source", source.getDisplayName()), - Placeholder.component("target", you), - Placeholder.component("message", parsedMessage.toText())); + var serverContext = PlaceholderContext.of(source.getServer()); + var sourceContext = PlaceholderContext.of(source); + PlaceholderContext targetContext; + if (targetPlayer == null) { + targetContext = serverContext; + } else { + targetContext = PlaceholderContext.of(targetPlayer); + } - var text = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage, - Placeholder.component("source", source.getDisplayName()), - Placeholder.component("target", targetDisplayName), - Placeholder.component("message", parsedMessage.toText())); + + var you = Components.parse(RccServer.CONFIG.textFormats.commands.tell.you); + + var placeholdersToSource = Map.of( + "sourcePlayer", you, + "targetPlayer", targetDisplayName, + "message", parsedMessage + ); + + var placeholdersToTarget = Map.of( + "sourcePlayer", source.getDisplayName(), + "targetPlayer", you, + "message", parsedMessage + ); + + var placeholders = Map.of( + "sourcePlayer", source.getDisplayName(), + "targetPlayer", targetDisplayName, + "message", parsedMessage + ); + + var sourceText = Components.parse( + RccServer.CONFIG.textFormats.commands.tell.message, + sourceContext, + placeholdersToSource + ); + var targetText = Components.parse( + RccServer.CONFIG.textFormats.commands.tell.message, + targetContext, + placeholdersToTarget + ); + var genericText = Components.parse( + RccServer.CONFIG.textFormats.commands.tell.message, + serverContext, + placeholders + ); + var spyText = Components.parse( + RccServer.CONFIG.textFormats.commands.tell.messageSpy, + serverContext, + placeholders + ); lastSender.put(targetName, source.getName()); lastSender.put(source.getName(), targetName); @@ -95,7 +134,7 @@ public class TellCommand { if (targetPlayer != null) { targetPlayer.sendMessage(targetText); if (source.isExecutedByPlayer()) { - source.getServer().sendMessage(text); + source.getServer().sendMessage(genericText); } } else { // avoid duped message @@ -104,10 +143,6 @@ public class TellCommand { var lp = RccServer.getInstance().luckPerms(); var playerAdapter = lp.getPlayerAdapter(ServerPlayerEntity.class); - var spyText = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessageSpy, - Placeholder.component("source", source.getDisplayName()), - Placeholder.component("target", targetDisplayName), - Placeholder.component("message", parsedMessage.toText())); source.getServer().getPlayerManager().getPlayerList().forEach(player -> { var playerName = player.getGameProfile().getName(); if (playerName.equals(targetName) || playerName.equals(source.getName())) { diff --git a/src/main/java/cc/reconnected/server/commands/warp/DeleteWarpCommand.java b/src/main/java/cc/reconnected/server/commands/warp/DeleteWarpCommand.java index a33c9fa..1896b8b 100644 --- a/src/main/java/cc/reconnected/server/commands/warp/DeleteWarpCommand.java +++ b/src/main/java/cc/reconnected/server/commands/warp/DeleteWarpCommand.java @@ -5,9 +5,7 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -16,7 +14,7 @@ import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; public class DeleteWarpCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("delwarp") .requires(Permissions.require("rcc.command.delwarp", 3)) .then(argument("name", StringArgumentType.word()) diff --git a/src/main/java/cc/reconnected/server/commands/warp/SetWarpCommand.java b/src/main/java/cc/reconnected/server/commands/warp/SetWarpCommand.java index 7e15b5d..ec06516 100644 --- a/src/main/java/cc/reconnected/server/commands/warp/SetWarpCommand.java +++ b/src/main/java/cc/reconnected/server/commands/warp/SetWarpCommand.java @@ -6,16 +6,15 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -import static net.minecraft.server.command.CommandManager.*; +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class SetWarpCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("setwarp") .requires(Permissions.require("rcc.command.setwarp", 3)) .then(argument("name", StringArgumentType.word()) diff --git a/src/main/java/cc/reconnected/server/commands/warp/WarpCommand.java b/src/main/java/cc/reconnected/server/commands/warp/WarpCommand.java index 5430359..4757c45 100644 --- a/src/main/java/cc/reconnected/server/commands/warp/WarpCommand.java +++ b/src/main/java/cc/reconnected/server/commands/warp/WarpCommand.java @@ -1,21 +1,23 @@ package cc.reconnected.server.commands.warp; import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; +import eu.pb4.placeholders.api.PlaceholderContext; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; -import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import static net.minecraft.server.command.CommandManager.*; +import java.util.Map; + +import static net.minecraft.server.command.CommandManager.argument; +import static net.minecraft.server.command.CommandManager.literal; public class WarpCommand { - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + public static void register(CommandDispatcher dispatcher) { var rootCommand = literal("warp") .requires(Permissions.require("rcc.command.warp", true)) .then(argument("name", StringArgumentType.word()) @@ -39,20 +41,23 @@ public class WarpCommand { var player = context.getSource().getPlayer(); var serverState = RccServer.state.getServerState(); var warps = serverState.warps; + var playerContext = PlaceholderContext.of(player); if (!warps.containsKey(name)) { - context.getSource().sendFeedback(() -> Text.literal("The warp ") - .append(Text.literal(name).formatted(Formatting.GOLD)) - .append(" does not exist!") - .formatted(Formatting.RED), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.warp.warpNotFound, + playerContext + ), false); return 1; } - context.getSource().sendFeedback(() -> Text - .literal("Teleporting to ") - .append(Text.literal(name).formatted(Formatting.GREEN)) - .append("...") - .formatted(Formatting.GOLD), false); + context.getSource().sendFeedback(() -> Components.parse( + RccServer.CONFIG.textFormats.commands.warp.teleporting, + playerContext, + Map.of( + "warp", Text.of(name) + ) + ), false); var warpPosition = warps.get(name); warpPosition.teleport(player); diff --git a/src/main/java/cc/reconnected/server/config/Config.java b/src/main/java/cc/reconnected/server/config/Config.java index 12a61a2..c89b6b5 100644 --- a/src/main/java/cc/reconnected/server/config/Config.java +++ b/src/main/java/cc/reconnected/server/config/Config.java @@ -1,7 +1,9 @@ package cc.reconnected.server.config; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class Config { Config() { @@ -9,12 +11,12 @@ public class Config { public HttpApi httpApi = new HttpApi(); public Afk afk = new Afk(); - public DirectMessages directMessages = new DirectMessages(); public TeleportRequests teleportRequests = new TeleportRequests(); public Homes homes = new Homes(); public CustomTabList customTabList = new CustomTabList(); public NearCommand nearCommand = new NearCommand(); public AutoRestart autoRestart = new AutoRestart(); + public Chat chat = new Chat(); public TextFormats textFormats = new TextFormats(); public static class HttpApi { @@ -24,14 +26,6 @@ public class Config { public static class Afk { public int afkTimeTrigger = 300; - public String afkMessage = " is now AFK"; - public String afkReturnMessage = " is no longer AFK"; - public String afkTag = "[AFK] "; - } - - public static class DirectMessages { - public String tellMessage = "[ ] "; - public String tellMessageSpy = "\uD83D\uDC41 [] "; } public static class TeleportRequests { @@ -92,23 +86,115 @@ public class Config { )); } + public static class Chat { + public boolean enableChatMarkdown = true; + public HashMap replacements = new HashMap<>(Map.of( + ":shrug:", "¯\\\\_(ツ)_/¯" + )); + } + public static class TextFormats { public record NameFormat(String group, String format) { } - public boolean enableChatMarkdown = true; - public ArrayList nameFormats = new ArrayList<>(List.of( new NameFormat("admin", "%player:name%"), new NameFormat("default", "%player:name%") )); - public String chatFormat = "${player}: ${message}"; - public String emoteFormat = "\uD83D\uDC64 ${player} ${message}"; - public String joinFormat = "+ ${player} joined!"; - public String joinRenamedFormat = "+ ${player} joined! (Previously known as ${previousName})"; - public String leaveFormat = "- ${player} left!"; + public String chatFormat = "%player:displayname%: ${message}"; + public String emoteFormat = "\uD83D\uDC64 %player:displayname% ${message}"; + public String joinFormat = "+ %player:displayname% joined!"; + public String joinRenamedFormat = "+ %player:displayname% joined! (Previously known as ${previousName})"; + public String leaveFormat = "- %player:displayname% left!"; public String deathFormat = "\u2620 ${message}"; + + public String link = "${label}"; + public String linkHover = "${url}"; + + public Commands commands = new Commands(); + + public static class Commands { + public Common common = new Common(); + public Back back = new Back(); + public Near near = new Near(); + public Home home = new Home(); + public Spawn spawn = new Spawn(); + public TeleportRequest teleportRequest = new TeleportRequest(); + public Tell tell = new Tell(); + public Warp warp = new Warp(); + public Afk afk = new Afk(); + + public static class Common { + // `{{command}}` is replaced as a string before parsing + public String button = "[${label}]"; + public String accept = "Accept"; + public String refuse = "Refuse"; + } + + public static class Back { + public String teleporting = "Teleporting to previous position..."; + public String noPosition = "There is no position to return back to."; + } + + public static class Near { + public String noOne = "There are no players near you."; + public String nearestPlayers = "Nearest players: ${playerList}"; + public String format = "${player} (${distance})"; + public String comma = ", "; + } + + public static class Home { + public String teleporting = "Teleporting to ${home}"; + public String homeExists = "You already have set this home.\n ${forceSetButton}"; + public String homeNotFound = "The home ${home} does not exist!"; + public String maxHomesReached = "You have reached the maximum amount of homes!"; + public String homeSetSuccess = "New home ${home} set!"; + public String forceSetLabel = "Force set home"; + public String forceSetHover = "Click to force setting new home"; + public String homeDeleted = "Home ${home} deleted!"; + } + + public static class Spawn { + public String teleporting = "Teleporting to spawn..."; + } + + public static class TeleportRequest { + public String teleporting = "Teleporting..."; + public String playerNotFound = "Player ${targetPlayer} not found!"; + public String requestSent = "Teleport request sent."; + public String pendingTeleport = "${requesterPlayer} requested to teleport to you.\n ${acceptButton} ${refuseButton}"; + public String pendingTeleportHere = "${requesterPlayer} requested you to teleport to them.\n ${acceptButton} ${refuseButton}"; + public String hoverAccept = "Click to accept request"; + public String hoverRefuse = "Click to refuse request"; + public String noPending = "There are no pending teleport requests for you."; + public String unavailable = "This requested expired or is no longer available."; + public String playerUnavailable = "The other player is no longer available."; + public String requestAcceptedResult = "Teleport request accepted."; + public String requestRefusedResult = "Teleport request refused."; + public String requestAccepted = "${player} accepted your teleport request!"; + public String requestRefused = "${player} refused your teleport request!"; + } + + public static class Tell { + public String playerNotFound = "Player ${targetPlayer} not found!"; + public String you = "You"; + public String message = "[${sourcePlayer} ${targetPlayer}] ${message}"; + public String messageSpy = "\uD83D\uDC41 [${sourcePlayer} → ${targetPlayer}] ${message}"; + public String noLastSenderReply = "You have no one to reply to."; // relatable + } + + public static class Warp { + public String teleporting = "Warping to ${warp}..."; + public String warpNotFound = "The warp ${warp} does not exist!"; + } + + public static class Afk { + public String goneAfk = "%player:displayname% is now AFK"; + public String returnAfk = "%player:displayname% is no longer AFK"; + public String tag = "[AFK] "; + } + } } diff --git a/src/main/java/cc/reconnected/server/config/ConfigManager.java b/src/main/java/cc/reconnected/server/config/ConfigManager.java index 97f7040..dd0c9d7 100644 --- a/src/main/java/cc/reconnected/server/config/ConfigManager.java +++ b/src/main/java/cc/reconnected/server/config/ConfigManager.java @@ -1,7 +1,6 @@ package cc.reconnected.server.config; import cc.reconnected.server.RccServer; -import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import net.fabricmc.loader.api.FabricLoader; diff --git a/src/main/java/cc/reconnected/server/core/AfkTracker.java b/src/main/java/cc/reconnected/server/core/AfkTracker.java index 41344f4..4f7874d 100644 --- a/src/main/java/cc/reconnected/server/core/AfkTracker.java +++ b/src/main/java/cc/reconnected/server/core/AfkTracker.java @@ -4,15 +4,14 @@ import cc.reconnected.server.RccServer; import cc.reconnected.server.api.events.PlayerActivityEvents; import cc.reconnected.server.api.events.RccEvents; import cc.reconnected.server.util.Components; +import eu.pb4.placeholders.api.PlaceholderContext; import eu.pb4.placeholders.api.PlaceholderResult; import eu.pb4.placeholders.api.Placeholders; +import eu.pb4.placeholders.api.TextParserUtils; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.player.*; import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; -import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; @@ -54,38 +53,30 @@ public class AfkTracker { PlayerActivityEvents.AFK.register((player, server) -> { RccServer.LOGGER.info("{} is AFK. Active time: {} seconds.", player.getGameProfile().getName(), getInstance().getActiveTime(player)); - var displayNameJson = Text.Serializer.toJson(player.getDisplayName()); - var displayName = JSONComponentSerializer.json().deserialize(displayNameJson); + var playerContext = PlaceholderContext.of(player); - var message = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkMessage, - Placeholder.component("displayname", displayName), - Placeholder.unparsed("username", player.getGameProfile().getName()), - Placeholder.unparsed("uuid", player.getUuid().toString()) - ); - - RccServer.getInstance().broadcastMessage(server, message); + RccServer.getInstance().broadcast(Components.parse( + RccServer.CONFIG.textFormats.commands.afk.goneAfk, + playerContext + )); }); PlayerActivityEvents.AFK_RETURN.register((player, server) -> { RccServer.LOGGER.info("{} is no longer AFK. Active time: {} seconds.", player.getGameProfile().getName(), getInstance().getActiveTime(player)); - var displayNameJson = Text.Serializer.toJson(player.getDisplayName()); - var displayName = JSONComponentSerializer.json().deserialize(displayNameJson); + var playerContext = PlaceholderContext.of(player); - var message = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkReturnMessage, - Placeholder.component("displayname", displayName), - Placeholder.unparsed("username", player.getGameProfile().getName()), - Placeholder.unparsed("uuid", player.getUuid().toString()) - ); - - RccServer.getInstance().broadcastMessage(server, message); + RccServer.getInstance().broadcast(Components.parse( + RccServer.CONFIG.textFormats.commands.afk.returnAfk, + playerContext + )); }); RccEvents.RELOAD.register(inst -> loadAfkTag()); } private static void loadAfkTag() { - afkTag = Components.toText(MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkTag)); + afkTag = TextParserUtils.formatText(RccServer.CONFIG.textFormats.commands.afk.tag); } private AfkTracker() { diff --git a/src/main/java/cc/reconnected/server/core/AutoRestart.java b/src/main/java/cc/reconnected/server/core/AutoRestart.java index bce8028..5338d13 100644 --- a/src/main/java/cc/reconnected/server/core/AutoRestart.java +++ b/src/main/java/cc/reconnected/server/core/AutoRestart.java @@ -119,7 +119,7 @@ public class AutoRestart { audience.playSound(sound, Sound.Emitter.self()); var comp = bar.parseLabel(RccServer.CONFIG.autoRestart.restartChatMessage); - rcc.broadcastMessage(server, comp); + rcc.broadcastComponent(server, comp); } @Nullable diff --git a/src/main/java/cc/reconnected/server/core/HttpApiServer.java b/src/main/java/cc/reconnected/server/core/HttpApiServer.java index 1192836..fdb4d91 100644 --- a/src/main/java/cc/reconnected/server/core/HttpApiServer.java +++ b/src/main/java/cc/reconnected/server/core/HttpApiServer.java @@ -1,9 +1,9 @@ package cc.reconnected.server.core; +import cc.reconnected.server.RccServer; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; -import cc.reconnected.server.RccServer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; diff --git a/src/main/java/cc/reconnected/server/core/customChat/CustomChatMessage.java b/src/main/java/cc/reconnected/server/core/customChat/CustomChatMessage.java index 1ff1f3a..aef77d8 100644 --- a/src/main/java/cc/reconnected/server/core/customChat/CustomChatMessage.java +++ b/src/main/java/cc/reconnected/server/core/customChat/CustomChatMessage.java @@ -1,15 +1,8 @@ package cc.reconnected.server.core.customChat; import cc.reconnected.server.RccServer; -import cc.reconnected.server.parser.MarkdownParser; import cc.reconnected.server.util.Components; -import eu.pb4.placeholders.api.Placeholders; -import eu.pb4.placeholders.api.TextParserUtils; -import eu.pb4.placeholders.api.node.TextNode; -import eu.pb4.placeholders.api.parsers.PatternPlaceholderParser; -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 eu.pb4.placeholders.api.PlaceholderContext; import net.minecraft.network.message.MessageType; import net.minecraft.network.message.SignedMessage; import net.minecraft.registry.RegistryKeys; @@ -19,26 +12,29 @@ import net.minecraft.text.Text; import java.util.Map; 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 = Utils.formatChatMessage(message, player); - - var placeholders = Map.of( - "message", messageText, - "player", player.getDisplayName() - ); - - - var format = TextParserUtils.formatText(RccServer.CONFIG.textFormats.chatFormat); - var text = Placeholders.parseText(format, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders); + var text = getFormattedMessage(message, player); 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); } + + public static Text getFormattedMessage(SignedMessage message, ServerPlayerEntity player) { + Text messageText = Components.chat(message, player); + + var playerContext = PlaceholderContext.of(player); + var text = Components.parse( + RccServer.CONFIG.textFormats.chatFormat, + playerContext, + Map.of( + "message", messageText + ) + ); + return text; + } } diff --git a/src/main/java/cc/reconnected/server/core/customChat/CustomConnectionMessage.java b/src/main/java/cc/reconnected/server/core/customChat/CustomConnectionMessage.java index 9da49c9..7578bf1 100644 --- a/src/main/java/cc/reconnected/server/core/customChat/CustomConnectionMessage.java +++ b/src/main/java/cc/reconnected/server/core/customChat/CustomConnectionMessage.java @@ -2,46 +2,35 @@ package cc.reconnected.server.core.customChat; import cc.reconnected.server.RccServer; import cc.reconnected.server.util.Components; -import eu.pb4.placeholders.api.Placeholders; -import eu.pb4.placeholders.api.TextParserUtils; -import eu.pb4.placeholders.api.node.TextNode; -import eu.pb4.placeholders.api.parsers.PatternPlaceholderParser; -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 eu.pb4.placeholders.api.PlaceholderContext; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import java.util.Map; public class CustomConnectionMessage { - private static final MiniMessage miniMessage = MiniMessage.miniMessage(); - public static Text onJoin(ServerPlayerEntity player) { - var placeholders = Map.of( - "player", player.getDisplayName() + var playerContext = PlaceholderContext.of(player); + return Components.parse( + RccServer.CONFIG.textFormats.joinFormat, + playerContext ); - - var format = TextParserUtils.formatText(RccServer.CONFIG.textFormats.joinFormat); - return Placeholders.parseText(format, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders); } public static Text onJoinRenamed(ServerPlayerEntity player, String previousName) { - var placeholders = Map.of( - "previousName", Text.of(previousName), - "player", player.getDisplayName() + var playerContext = PlaceholderContext.of(player); + return Components.parse( + RccServer.CONFIG.textFormats.joinRenamedFormat, + playerContext, + Map.of("previousName", Text.of(previousName)) ); - - var format = TextParserUtils.formatText(RccServer.CONFIG.textFormats.joinRenamedFormat); - return Placeholders.parseText(format, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders); } public static Text onLeave(ServerPlayerEntity player) { - var placeholders = Map.of( - "player", player.getDisplayName() + var playerContext = PlaceholderContext.of(player); + return Components.parse( + RccServer.CONFIG.textFormats.leaveFormat, + playerContext ); - - var format = TextParserUtils.formatText(RccServer.CONFIG.textFormats.leaveFormat); - return Placeholders.parseText(format, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders); } } diff --git a/src/main/java/cc/reconnected/server/core/customChat/CustomDeathMessage.java b/src/main/java/cc/reconnected/server/core/customChat/CustomDeathMessage.java index e938d00..7807c7a 100644 --- a/src/main/java/cc/reconnected/server/core/customChat/CustomDeathMessage.java +++ b/src/main/java/cc/reconnected/server/core/customChat/CustomDeathMessage.java @@ -3,13 +3,6 @@ package cc.reconnected.server.core.customChat; import cc.reconnected.server.RccServer; import cc.reconnected.server.util.Components; import eu.pb4.placeholders.api.PlaceholderContext; -import eu.pb4.placeholders.api.Placeholders; -import eu.pb4.placeholders.api.TextParserUtils; -import eu.pb4.placeholders.api.node.TextNode; -import eu.pb4.placeholders.api.parsers.PatternPlaceholderParser; -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; @@ -17,17 +10,14 @@ import net.minecraft.text.Text; import java.util.Map; public class CustomDeathMessage { - private static final MiniMessage miniMessage = MiniMessage.miniMessage(); - public static Text onDeath(ServerPlayerEntity player, DamageTracker instance) { var deathMessage = instance.getDeathMessage(); + var playerContext = PlaceholderContext.of(player); - var placeholders = Map.of( - "message", deathMessage, - "player", player.getDisplayName() + return Components.parse( + RccServer.CONFIG.textFormats.deathFormat, + playerContext, + Map.of("message", deathMessage) ); - - var format = TextParserUtils.formatText(RccServer.CONFIG.textFormats.deathFormat); - return Placeholders.parseText(format, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders); } } diff --git a/src/main/java/cc/reconnected/server/core/customChat/CustomEmoteMessage.java b/src/main/java/cc/reconnected/server/core/customChat/CustomEmoteMessage.java index f039019..51d6572 100644 --- a/src/main/java/cc/reconnected/server/core/customChat/CustomEmoteMessage.java +++ b/src/main/java/cc/reconnected/server/core/customChat/CustomEmoteMessage.java @@ -1,10 +1,8 @@ package cc.reconnected.server.core.customChat; import cc.reconnected.server.RccServer; -import eu.pb4.placeholders.api.Placeholders; -import eu.pb4.placeholders.api.TextParserUtils; -import eu.pb4.placeholders.api.parsers.PatternPlaceholderParser; -import net.kyori.adventure.text.minimessage.MiniMessage; +import cc.reconnected.server.util.Components; +import eu.pb4.placeholders.api.PlaceholderContext; import net.minecraft.network.message.MessageType; import net.minecraft.network.message.SignedMessage; import net.minecraft.registry.RegistryKeys; @@ -14,22 +12,21 @@ import net.minecraft.text.Text; import java.util.Map; 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); + var playerContext = PlaceholderContext.of(player); - Text messageText = Utils.formatChatMessage(message, player); + Text messageText = Components.chat(message, player); - var placeholders = Map.of( - "message", messageText, - "player", player.getDisplayName() + var text = Components.parse( + RccServer.CONFIG.textFormats.emoteFormat, + playerContext, + Map.of( + "message", messageText + ) ); - var format = TextParserUtils.formatText(RccServer.CONFIG.textFormats.emoteFormat); - var text = Placeholders.parseText(format, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders); - var msgType = RccServer.server.getRegistryManager().get(RegistryKeys.MESSAGE_TYPE).getOrThrow(RccServer.CHAT_TYPE); var newParams = new MessageType.Parameters(msgType, text, null); diff --git a/src/main/java/cc/reconnected/server/core/customChat/Utils.java b/src/main/java/cc/reconnected/server/core/customChat/Utils.java deleted file mode 100644 index eb8f51b..0000000 --- a/src/main/java/cc/reconnected/server/core/customChat/Utils.java +++ /dev/null @@ -1,32 +0,0 @@ -package cc.reconnected.server.core.customChat; - -import cc.reconnected.server.RccServer; -import cc.reconnected.server.parser.MarkdownParser; -import eu.pb4.placeholders.api.parsers.NodeParser; -import eu.pb4.placeholders.api.parsers.TextParserV1; -import net.minecraft.network.message.SignedMessage; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; - -public class Utils { - public static Text formatChatMessage(SignedMessage message, ServerPlayerEntity player) { - var luckperms = RccServer.getInstance().luckPerms(); - - var permissions = luckperms.getPlayerAdapter(ServerPlayerEntity.class).getPermissionData(player); - var allowAdvancedChatFormat = permissions.checkPermission("rcc.chat.advanced").asBoolean(); - var enableMarkdown = RccServer.CONFIG.textFormats.enableChatMarkdown; - - if(!allowAdvancedChatFormat && !enableMarkdown) { - return message.getContent(); - } - - NodeParser parser; - if(allowAdvancedChatFormat) { - parser = NodeParser.merge(TextParserV1.DEFAULT, MarkdownParser.defaultParser); - } else { - parser = MarkdownParser.defaultParser; - } - - return parser.parseNode(message.getSignedContent()).toText(); - } -} diff --git a/src/main/java/cc/reconnected/server/mixin/SentMessageMixin.java b/src/main/java/cc/reconnected/server/mixin/SentMessageMixin.java index d26b131..0984c16 100644 --- a/src/main/java/cc/reconnected/server/mixin/SentMessageMixin.java +++ b/src/main/java/cc/reconnected/server/mixin/SentMessageMixin.java @@ -3,7 +3,7 @@ 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.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; diff --git a/src/main/java/cc/reconnected/server/parser/LinkParser.java b/src/main/java/cc/reconnected/server/parser/LinkParser.java new file mode 100644 index 0000000..7e18c7b --- /dev/null +++ b/src/main/java/cc/reconnected/server/parser/LinkParser.java @@ -0,0 +1,99 @@ +package cc.reconnected.server.parser; + +import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; +import eu.pb4.placeholders.api.node.DirectTextNode; +import eu.pb4.placeholders.api.node.LiteralNode; +import eu.pb4.placeholders.api.node.TextNode; +import eu.pb4.placeholders.api.node.parent.ParentNode; +import eu.pb4.placeholders.api.parsers.NodeParser; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.HoverEvent; +import net.minecraft.text.Style; +import net.minecraft.text.Text; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +public class LinkParser implements NodeParser { + public static final Pattern URL_REGEX = Pattern.compile("https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)"); + + @Override + public TextNode[] parseNodes(TextNode node) { + if (node instanceof LiteralNode literalNode) { + var input = literalNode.value(); + var list = new ArrayList(); + var inputLength = input.length(); + + var matcher = URL_REGEX.matcher(input); + int pos = 0; + + while (matcher.find()) { + if (inputLength <= matcher.start()) { + break; + } + + String betweenText = input.substring(pos, matcher.start()); + + if (!betweenText.isEmpty()) { + list.add(new LiteralNode(betweenText)); + } + + var link = matcher.group(); + + var url = Text.of(link); + + var placeholders = Map.of( + "url", url, + "label", url + ); + + var display = Components.parse( + RccServer.CONFIG.textFormats.link, + placeholders + ); + + var hover = Components.parse( + RccServer.CONFIG.textFormats.linkHover, + placeholders + ); + + var text = Text.empty() + .append(display) + .setStyle(Style.EMPTY + .withHoverEvent( + new HoverEvent(HoverEvent.Action.SHOW_TEXT, hover) + ) + .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, link)) + ); + + list.add(new DirectTextNode(text)); + + pos = matcher.end(); + } + + if (pos < inputLength) { + var text = input.substring(pos, inputLength); + if (!text.isEmpty()) { + list.add(new LiteralNode(text)); + } + } + + return list.toArray(TextNode[]::new); + } else if (node instanceof ParentNode parentNode) { + var list = new ArrayList(); + + for (var child : parentNode.getChildren()) { + list.addAll(List.of(this.parseNodes(child))); + } + + return new TextNode[]{ + parentNode.copyWith(list.toArray(TextNode[]::new)) + }; + } + + return TextNode.array(node); + } +} \ No newline at end of file diff --git a/src/main/java/cc/reconnected/server/parser/MarkdownComponentParser.java b/src/main/java/cc/reconnected/server/parser/MarkdownComponentParser.java index 17815da..64a8f51 100644 --- a/src/main/java/cc/reconnected/server/parser/MarkdownComponentParser.java +++ b/src/main/java/cc/reconnected/server/parser/MarkdownComponentParser.java @@ -1,10 +1,16 @@ package cc.reconnected.server.parser; +import cc.reconnected.server.RccServer; +import cc.reconnected.server.util.Components; import eu.pb4.placeholders.api.node.TextNode; -import eu.pb4.placeholders.api.node.parent.*; -import net.minecraft.text.*; +import eu.pb4.placeholders.api.node.parent.ClickActionNode; +import eu.pb4.placeholders.api.node.parent.FormattingNode; +import eu.pb4.placeholders.api.node.parent.HoverNode; +import net.minecraft.text.ClickEvent; import net.minecraft.util.Formatting; +import java.util.Map; + public class MarkdownComponentParser { public static TextNode spoilerFormatting(TextNode[] textNodes) { var text = TextNode.asSingle(textNodes); @@ -27,16 +33,20 @@ public class MarkdownComponentParser { } public static TextNode urlFormatting(TextNode[] textNodes, TextNode url) { + var placeholders = Map.of( + "label", TextNode.wrap(textNodes).toText(), + "url", url.toText() + ); + var text = Components.parse(RccServer.CONFIG.textFormats.link, placeholders); + var hover = Components.parse(RccServer.CONFIG.textFormats.linkHover, placeholders); + return new HoverNode<>(TextNode.array( new ClickActionNode( TextNode.array( - new StyledNode(textNodes, - Style.EMPTY.withColor(0x8888ff).withUnderline(true), - null, null, null - ) + TextNode.convert(text) ), ClickEvent.Action.OPEN_URL, url)), - HoverNode.Action.TEXT, TextNode.of("Click to open: " + url.toText().getString()) + HoverNode.Action.TEXT, TextNode.convert(hover) ); } } diff --git a/src/main/java/cc/reconnected/server/parser/MarkdownParser.java b/src/main/java/cc/reconnected/server/parser/MarkdownParser.java index e5cfd47..6cd61ef 100644 --- a/src/main/java/cc/reconnected/server/parser/MarkdownParser.java +++ b/src/main/java/cc/reconnected/server/parser/MarkdownParser.java @@ -20,11 +20,13 @@ public class MarkdownParser { public static final NodeParser defaultParser = createParser(ALL); public static NodeParser createParser(MarkdownFormat[] capabilities) { - return new MarkdownLiteParserV1( + var mdParser = new MarkdownLiteParserV1( MarkdownComponentParser::spoilerFormatting, MarkdownComponentParser::quoteFormatting, MarkdownComponentParser::urlFormatting, capabilities ); + + return NodeParser.merge(mdParser, new LinkParser()); } } diff --git a/src/main/java/cc/reconnected/server/util/Components.java b/src/main/java/cc/reconnected/server/util/Components.java index ae8cd2b..5c023d3 100644 --- a/src/main/java/cc/reconnected/server/util/Components.java +++ b/src/main/java/cc/reconnected/server/util/Components.java @@ -1,15 +1,32 @@ package cc.reconnected.server.util; +import cc.reconnected.server.RccServer; +import cc.reconnected.server.parser.MarkdownParser; +import eu.pb4.placeholders.api.PlaceholderContext; +import eu.pb4.placeholders.api.Placeholders; +import eu.pb4.placeholders.api.TextParserUtils; +import eu.pb4.placeholders.api.node.TextNode; +import eu.pb4.placeholders.api.parsers.NodeParser; +import eu.pb4.placeholders.api.parsers.PatternPlaceholderParser; +import eu.pb4.placeholders.api.parsers.TextParserV1; +import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents; +import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentLike; 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.network.message.SignedMessage; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.MutableText; import net.minecraft.text.Text; +import java.util.Map; + public class Components { + @Deprecated public static Component makeButton(ComponentLike text, ComponentLike hoverText, String command) { return Component.empty() .append(Component.text("[")) @@ -20,8 +37,101 @@ public class Components { .clickEvent(ClickEvent.runCommand(command)); } + public static Text button(Text label, Text hoverText, String command) { + var format = RccServer.CONFIG.textFormats.commands.common.button; + var placeholders = Map.of( + "label", label, + "hoverText", hoverText, + "command", Text.of(command) + ); + + format = format.replace("{{command}}", command); + var text = TextParserUtils.formatText(format); + return Placeholders.parseText(text, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders); + } + + public static Text button(String label, String hoverText, String command) { + var btn = button( + TextParserUtils.formatText(label), + TextParserUtils.formatText(hoverText), + command + ); + + return btn; + } + public static MutableText toText(Component component) { var json = JSONComponentSerializer.json().serialize(component); return Text.Serializer.fromJson(json); } + + public static Text parse(String text) { + return TextParserUtils.formatText(text); + } + + public static Text parse(TextNode textNode, PlaceholderContext context, Map placeholders) { + var predefinedNode = Placeholders.parseNodes(textNode, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders); + return Placeholders.parseText(predefinedNode, context); + } + + public static Text parse(Text text, PlaceholderContext context, Map placeholders) { + return parse(TextNode.convert(text), context, placeholders); + } + + public static Text parse(String text, PlaceholderContext context, Map placeholders) { + return parse(parse(text), context, placeholders); + } + + public static Text parse(String text, PlaceholderContext context) { + return parse(parse(text), context, Map.of()); + } + + public static Text parse(String text, Map placeholders) { + return Placeholders.parseText(parse(text), PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders); + } + + public static Text chat(SignedMessage message, ServerPlayerEntity player) { + var luckperms = RccServer.getInstance().luckPerms(); + + var permissions = luckperms.getPlayerAdapter(ServerPlayerEntity.class).getPermissionData(player); + var allowAdvancedChatFormat = permissions.checkPermission("rcc.chat.advanced").asBoolean(); + + return chat(message.getSignedContent(), allowAdvancedChatFormat); + } + + public static Text chat(String message, ServerPlayerEntity player) { + var luckperms = RccServer.getInstance().luckPerms(); + + var permissions = luckperms.getPlayerAdapter(ServerPlayerEntity.class).getPermissionData(player); + var allowAdvancedChatFormat = permissions.checkPermission("rcc.chat.advanced").asBoolean(); + + return chat(message, allowAdvancedChatFormat); + } + + public static Text chat(String message, boolean allowAdvancedChatFormat) { + var enableMarkdown = RccServer.CONFIG.chat.enableChatMarkdown; + + for(var repl : RccServer.CONFIG.chat.replacements.entrySet() ) { + message = message.replace(repl.getKey(), repl.getValue()); + } + + if(!allowAdvancedChatFormat && !enableMarkdown) { + return Text.of(message); + } + + NodeParser parser; + if(allowAdvancedChatFormat) { + parser = NodeParser.merge(TextParserV1.DEFAULT, MarkdownParser.defaultParser); + } else { + parser = MarkdownParser.defaultParser; + } + + return parser.parseNode(message).toText(); + } + + public static Text chat(String message, ServerCommandSource source) { + if(source.isExecutedByPlayer()) + return chat(message, source.getPlayer()); + return chat(message, true); + } }