Merge pull request #8

* WIP

* Make most Texts customizable from config.

* Minor changes

* Remove unused args in commands
This commit is contained in:
Alessandro Proto 2024-11-08 19:41:08 +01:00 committed by GitHub
parent 9807f5c018
commit 822a860756
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 865 additions and 416 deletions

View file

@ -2,30 +2,44 @@ package cc.reconnected.server;
import cc.reconnected.server.api.events.RccEvents; import cc.reconnected.server.api.events.RccEvents;
import cc.reconnected.server.commands.admin.*; import cc.reconnected.server.commands.admin.*;
import cc.reconnected.server.commands.home.*; import cc.reconnected.server.commands.home.DeleteHomeCommand;
import cc.reconnected.server.commands.misc.*; import cc.reconnected.server.commands.home.HomeCommand;
import cc.reconnected.server.commands.spawn.*; import cc.reconnected.server.commands.home.SetHomeCommand;
import cc.reconnected.server.commands.teleport.*; import cc.reconnected.server.commands.misc.AfkCommand;
import cc.reconnected.server.commands.tell.*; import cc.reconnected.server.commands.teleport.BackCommand;
import cc.reconnected.server.commands.warp.*; 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.Config;
import cc.reconnected.server.config.ConfigManager; import cc.reconnected.server.config.ConfigManager;
import cc.reconnected.server.core.*; import cc.reconnected.server.core.*;
import cc.reconnected.server.core.customChat.CustomChatMessage;
import cc.reconnected.server.data.StateManager; import cc.reconnected.server.data.StateManager;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; 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.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.kyori.adventure.platform.fabric.FabricServerAudiences; import net.kyori.adventure.platform.fabric.FabricServerAudiences;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.luckperms.api.LuckPerms; import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider; import net.luckperms.api.LuckPermsProvider;
import net.minecraft.network.message.MessageType; import net.minecraft.network.message.MessageType;
import net.minecraft.network.message.SignedMessage;
import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.WorldSavePath; import net.minecraft.util.WorldSavePath;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -84,38 +98,37 @@ public class RccServer implements ModInitializer {
ServerLifecycleEvents.SERVER_STOPPED.register(server -> this.adventure = null); ServerLifecycleEvents.SERVER_STOPPED.register(server -> this.adventure = null);
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { 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); TellCommand.register(dispatcher);
ReplyCommand.register(dispatcher, registryAccess, environment); ReplyCommand.register(dispatcher);
TeleportAskCommand.register(dispatcher, registryAccess, environment); TeleportAskCommand.register(dispatcher);
TeleportAskHereCommand.register(dispatcher, registryAccess, environment); TeleportAskHereCommand.register(dispatcher);
TeleportAcceptCommand.register(dispatcher, registryAccess, environment); TeleportAcceptCommand.register(dispatcher);
TeleportDenyCommand.register(dispatcher, registryAccess, environment); TeleportDenyCommand.register(dispatcher);
BackCommand.register(dispatcher);
BackCommand.register(dispatcher, registryAccess, environment); FlyCommand.register(dispatcher);
GodCommand.register(dispatcher);
FlyCommand.register(dispatcher, registryAccess, environment); SetSpawnCommand.register(dispatcher);
GodCommand.register(dispatcher, registryAccess, environment); SpawnCommand.register(dispatcher);
SetSpawnCommand.register(dispatcher, registryAccess, environment); HomeCommand.register(dispatcher);
SpawnCommand.register(dispatcher, registryAccess, environment); SetHomeCommand.register(dispatcher);
DeleteHomeCommand.register(dispatcher);
HomeCommand.register(dispatcher, registryAccess, environment); WarpCommand.register(dispatcher);
SetHomeCommand.register(dispatcher, registryAccess, environment); SetWarpCommand.register(dispatcher);
DeleteHomeCommand.register(dispatcher, registryAccess, environment); DeleteWarpCommand.register(dispatcher);
WarpCommand.register(dispatcher, registryAccess, environment); TimeBarCommand.register(dispatcher);
SetWarpCommand.register(dispatcher, registryAccess, environment); RestartCommand.register(dispatcher);
DeleteWarpCommand.register(dispatcher, registryAccess, environment);
TimeBarCommand.register(dispatcher, registryAccess, environment); NearCommand.register(dispatcher);
RestartCommand.register(dispatcher, registryAccess, environment);
NearCommand.register(dispatcher, registryAccess, environment);
}); });
AfkTracker.register(); 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()) { for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) {
player.sendMessage(message); 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);
}
}
} }

View file

@ -12,7 +12,10 @@ import org.jetbrains.annotations.Nullable;
import java.time.Instant; import java.time.Instant;
import java.time.format.DateTimeFormatter; 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.concurrent.CompletableFuture;
import java.util.stream.Collectors; import java.util.stream.Collectors;

View file

@ -3,19 +3,18 @@ package cc.reconnected.server.commands.admin;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import me.lucko.fabric.api.permissions.v0.Permissions; import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Style; import net.minecraft.text.Style;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting; 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 class FlyCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("fly") var rootCommand = literal("fly")
.requires(Permissions.require("rcc.command.fly", 3)) .requires(Permissions.require("rcc.command.fly", 3))
.executes(context -> { .executes(context -> {

View file

@ -3,9 +3,7 @@ package cc.reconnected.server.commands.admin;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import me.lucko.fabric.api.permissions.v0.Permissions; import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Style; 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; import static net.minecraft.server.command.CommandManager.literal;
public class GodCommand { public class GodCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("god") var rootCommand = literal("god")
.requires(Permissions.require("rcc.command.god", 3)) .requires(Permissions.require("rcc.command.god", 3))
.executes(context -> { .executes(context -> {

View file

@ -5,15 +5,13 @@ import cc.reconnected.server.api.events.RccEvents;
import cc.reconnected.server.config.ConfigManager; import cc.reconnected.server.config.ConfigManager;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.command.ServerCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
public class RccCommand { public class RccCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("rcc") var rootCommand = literal("rcc")
.requires(Permissions.require("rcc.command.rcc", 3)) .requires(Permissions.require("rcc.command.rcc", 3))
.then(literal("reload") .then(literal("reload")

View file

@ -7,17 +7,16 @@ import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.command.ServerCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import org.jetbrains.annotations.Nullable; 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 class RestartCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("restart") var rootCommand = literal("restart")
.requires(Permissions.require("rcc.command.restart", 4)) .requires(Permissions.require("rcc.command.restart", 4))
.then(literal("schedule") .then(literal("schedule")

View file

@ -9,11 +9,9 @@ import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import me.lucko.fabric.api.permissions.v0.Permissions; import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.command.argument.UuidArgumentType; import net.minecraft.command.argument.UuidArgumentType;
import net.minecraft.entity.boss.BossBar; import net.minecraft.entity.boss.BossBar;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.ClickEvent; import net.minecraft.text.ClickEvent;
import net.minecraft.text.HoverEvent; import net.minecraft.text.HoverEvent;
@ -25,12 +23,13 @@ import java.util.Arrays;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; 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 { public class TimeBarCommand {
private static final ConcurrentHashMap<UUID, BarCommand> runningBars = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<UUID, BarCommand> runningBars = new ConcurrentHashMap<>();
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("timebar") var rootCommand = literal("timebar")
.requires(Permissions.require("rcc.command.timebar", 3)) .requires(Permissions.require("rcc.command.timebar", 3))
.then(literal("start") .then(literal("start")

View file

@ -1,22 +1,23 @@
package cc.reconnected.server.commands.home; package cc.reconnected.server.commands.home;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import eu.pb4.placeholders.api.PlaceholderContext;
import me.lucko.fabric.api.permissions.v0.Permissions; import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Text; 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.argument;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
public class DeleteHomeCommand { public class DeleteHomeCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("delhome") var rootCommand = literal("delhome")
.requires(Permissions.require("rcc.command.delhome", true)) .requires(Permissions.require("rcc.command.delhome", true))
.executes(context -> execute(context, "home")) .executes(context -> execute(context, "home"))
@ -41,23 +42,29 @@ public class DeleteHomeCommand {
var player = context.getSource().getPlayer(); var player = context.getSource().getPlayer();
var playerState = RccServer.state.getPlayerState(player.getUuid()); var playerState = RccServer.state.getPlayerState(player.getUuid());
var homes = playerState.homes; var homes = playerState.homes;
var playerContext = PlaceholderContext.of(context.getSource().getPlayer());
var placeholders = Map.of(
"home", Text.of(name)
);
if (!homes.containsKey(name)) { if (!homes.containsKey(name)) {
context.getSource().sendFeedback(() -> Text.literal("The home ") context.getSource().sendFeedback(() -> Components.parse(
.append(Text.literal(name).formatted(Formatting.GOLD)) RccServer.CONFIG.textFormats.commands.home.homeNotFound,
.append(" does not exist!") playerContext,
.formatted(Formatting.RED), false); placeholders
), false);
return 1; return 1;
} }
homes.remove(name); homes.remove(name);
RccServer.state.savePlayerState(player.getUuid(), playerState); RccServer.state.savePlayerState(player.getUuid(), playerState);
context.getSource().sendFeedback(() -> Text context.getSource().sendFeedback(() -> Components.parse(
.literal("Home ") RccServer.CONFIG.textFormats.commands.home.homeDeleted,
.append(Text.literal(name).formatted(Formatting.GOLD)) playerContext,
.append(" deleted!") placeholders
.formatted(Formatting.GREEN), false); ), false);
return 1; return 1;
} }

View file

@ -1,21 +1,23 @@
package cc.reconnected.server.commands.home; package cc.reconnected.server.commands.home;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import eu.pb4.placeholders.api.PlaceholderContext;
import me.lucko.fabric.api.permissions.v0.Permissions; import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Text; 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 class HomeCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("home") var rootCommand = literal("home")
.requires(Permissions.require("rcc.command.home", true)) .requires(Permissions.require("rcc.command.home", true))
.executes(context -> execute(context, "home")) .executes(context -> execute(context, "home"))
@ -40,20 +42,29 @@ public class HomeCommand {
var player = context.getSource().getPlayer(); var player = context.getSource().getPlayer();
var playerState = RccServer.state.getPlayerState(player.getUuid()); var playerState = RccServer.state.getPlayerState(player.getUuid());
var homes = playerState.homes; var homes = playerState.homes;
var playerContext = PlaceholderContext.of(context.getSource().getPlayer());
var placeholders = Map.of(
"home", Text.of(name)
);
if (!homes.containsKey(name)) { if (!homes.containsKey(name)) {
context.getSource().sendFeedback(() -> Text.literal("The home ") context.getSource().sendFeedback(() ->
.append(Text.literal(name).formatted(Formatting.GOLD)) Components.parse(
.append(" does not exist!") RccServer.CONFIG.textFormats.commands.home.homeNotFound,
.formatted(Formatting.RED), false); playerContext,
placeholders
), false);
return 1; return 1;
} }
context.getSource().sendFeedback(() -> Text context.getSource().sendFeedback(() ->
.literal("Teleporting to ") Components.parse(
.append(Text.literal(name).formatted(Formatting.GREEN)) RccServer.CONFIG.textFormats.commands.home.teleporting,
.append("...") playerContext,
.formatted(Formatting.GOLD), false); placeholders
), false);
var homePosition = homes.get(name); var homePosition = homes.get(name);
homePosition.teleport(player); homePosition.teleport(player);

View file

@ -7,19 +7,18 @@ import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import eu.pb4.placeholders.api.PlaceholderContext;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.server.command.ServerCommandSource;
import net.minecraft.text.Text; 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 class SetHomeCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("sethome") var rootCommand = literal("sethome")
.requires(Permissions.require("rcc.command.sethome", true)) .requires(Permissions.require("rcc.command.sethome", true))
.executes(context -> execute(context, .executes(context -> execute(context,
@ -44,27 +43,38 @@ public class SetHomeCommand {
} }
var player = context.getSource().getPlayer(); var player = context.getSource().getPlayer();
var playerState = RccServer.state.getPlayerState(player.getUuid()); var playerState = RccServer.state.getPlayerState(player.getUuid());
var homes = playerState.homes; 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); var exists = homes.containsKey(name);
if (exists && !forced) { if (exists && !forced) {
var text = Component.text("You already have set this home.") var text = Components.parse(
.appendNewline().appendSpace() RccServer.CONFIG.textFormats.commands.home.homeExists,
.append(Components.makeButton( playerContext,
Component.text("Force set home", NamedTextColor.GOLD), placeholders
Component.text("Click to force set the home"), );
"/sethome " + name + " true"
));
context.getSource().sendFailure(text); context.getSource().sendFeedback(() -> text, false);
return 1; return 1;
} }
var maxHomes = RccServer.CONFIG.homes.maxHomes; var maxHomes = RccServer.CONFIG.homes.maxHomes;
if(homes.size() >= maxHomes && !exists) { 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; return 1;
} }
@ -73,10 +83,11 @@ public class SetHomeCommand {
RccServer.state.savePlayerState(player.getUuid(), playerState); RccServer.state.savePlayerState(player.getUuid(), playerState);
context.getSource().sendFeedback(() -> Text.literal("New home ") context.getSource().sendFeedback(() -> Components.parse(
.append(Text.literal(name).formatted(Formatting.GOLD)) RccServer.CONFIG.textFormats.commands.home.homeSetSuccess,
.append(" set!") playerContext,
.formatted(Formatting.GREEN), false); placeholders
), false);
return 1; return 1;
} }

View file

@ -3,15 +3,13 @@ package cc.reconnected.server.commands.misc;
import cc.reconnected.server.core.AfkTracker; import cc.reconnected.server.core.AfkTracker;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.command.ServerCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
public class AfkCommand { public class AfkCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("afk") var rootCommand = literal("afk")
.requires(Permissions.require("rcc.command.afk", true)) .requires(Permissions.require("rcc.command.afk", true))
.executes(context -> { .executes(context -> {

View file

@ -1,24 +1,25 @@
package cc.reconnected.server.commands.misc; package cc.reconnected.server.commands.misc;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import eu.pb4.placeholders.api.PlaceholderContext;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; 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 class NearCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("near") var rootCommand = literal("near")
.requires(Permissions.require("rcc.command.near", 2)) .requires(Permissions.require("rcc.command.near", 2))
.executes(context -> { .executes(context -> {
@ -41,6 +42,7 @@ public class NearCommand {
} }
private static int execute(CommandContext<ServerCommandSource> context, int range, ServerPlayerEntity sourcePlayer) { private static int execute(CommandContext<ServerCommandSource> context, int range, ServerPlayerEntity sourcePlayer) {
var playerContext = PlaceholderContext.of(sourcePlayer);
var list = new ArrayList<ClosePlayers>(); var list = new ArrayList<ClosePlayers>();
var sourcePos = sourcePlayer.getPos(); var sourcePos = sourcePlayer.getPos();
@ -48,35 +50,53 @@ public class NearCommand {
var targetPos = targetPlayer.getPos(); var targetPos = targetPlayer.getPos();
if (!sourcePlayer.getUuid().equals(targetPlayer.getUuid()) && sourcePos.isInRange(targetPos, range)) { if (!sourcePlayer.getUuid().equals(targetPlayer.getUuid()) && sourcePos.isInRange(targetPos, range)) {
var distance = sourcePos.distanceTo(targetPos); var distance = sourcePos.distanceTo(targetPos);
list.add(new ClosePlayers(targetPlayer.getDisplayName(), distance)); list.add(new ClosePlayers(targetPlayer, distance));
} }
}); });
if (list.isEmpty()) { if (list.isEmpty()) {
context.getSource().sendFeedback(() -> Text.literal("There is no one near you.").formatted(Formatting.GOLD), false); context.getSource().sendFeedback(() -> Components.parse(
RccServer.CONFIG.textFormats.commands.near.noOne,
playerContext
), false);
return 1; return 1;
} }
list.sort(Comparator.comparingDouble(ClosePlayers::distance)); list.sort(Comparator.comparingDouble(ClosePlayers::distance));
var text = Text.empty().append(Text.literal("Nearest players: ").formatted(Formatting.GOLD)); var listText = Text.empty();
var comma = Text.literal(", ").formatted(Formatting.GOLD); var comma = Components.parse(RccServer.CONFIG.textFormats.commands.near.comma);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
var player = list.get(i); var player = list.get(i);
if (i > 0) { if (i > 0) {
text = text.append(comma); listText = listText.append(comma);
} }
text = text.append(player.displayName) var placeholders = Map.of(
.append(" ") "player", player.player.getDisplayName(),
.append(Text.literal(String.format("(%.1fm)", player.distance)).formatted(Formatting.GREEN)); "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; var placeholders = Map.of(
context.getSource().sendFeedback(() -> finalText, false); "playerList", (Text) listText
);
context.getSource().sendFeedback(() -> Components.parse(
RccServer.CONFIG.textFormats.commands.near.nearestPlayers,
playerContext,
placeholders
), false);
return 1; return 1;
} }
private record ClosePlayers(Text displayName, double distance) { private record ClosePlayers(ServerPlayerEntity player, double distance) {
} }
} }

View file

@ -4,8 +4,6 @@ import cc.reconnected.server.RccServer;
import cc.reconnected.server.struct.ServerPosition; import cc.reconnected.server.struct.ServerPosition;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.command.ServerCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
@ -13,7 +11,7 @@ import net.minecraft.util.Formatting;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
public class SetSpawnCommand { public class SetSpawnCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("setspawn") var rootCommand = literal("setspawn")
.requires(Permissions.require("rcc.command.setspawn", 3)) .requires(Permissions.require("rcc.command.setspawn", 3))
.executes(context -> { .executes(context -> {

View file

@ -2,18 +2,17 @@ package cc.reconnected.server.commands.spawn;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.struct.ServerPosition; import cc.reconnected.server.struct.ServerPosition;
import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import eu.pb4.placeholders.api.PlaceholderContext;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.command.ServerCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
public class SpawnCommand { public class SpawnCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("spawn") var rootCommand = literal("spawn")
.requires(Permissions.require("rcc.command.spawn", true)) .requires(Permissions.require("rcc.command.spawn", true))
.executes(context -> { .executes(context -> {
@ -24,6 +23,7 @@ public class SpawnCommand {
var player = context.getSource().getPlayer(); var player = context.getSource().getPlayer();
var serverState = RccServer.state.getServerState(); var serverState = RccServer.state.getServerState();
var playerContext = PlaceholderContext.of(player);
var spawnPosition = serverState.spawn; var spawnPosition = serverState.spawn;
if (spawnPosition == null) { if (spawnPosition == null) {
var server = context.getSource().getServer(); var server = context.getSource().getServer();
@ -31,7 +31,10 @@ public class SpawnCommand {
spawnPosition = new ServerPosition(spawnPos.getX(), spawnPos.getY(), spawnPos.getZ(), 0, 0, server.getOverworld()); 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); spawnPosition.teleport(player);
return 1; return 1;

View file

@ -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.core.BackTracker;
import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import eu.pb4.placeholders.api.PlaceholderContext;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.command.ServerCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
public class BackCommand { public class BackCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("back") var rootCommand = literal("back")
.requires(Permissions.require("rcc.command.back", true)) .requires(Permissions.require("rcc.command.back", true))
.executes(context -> { .executes(context -> {
@ -22,14 +22,21 @@ public class BackCommand {
} }
var player = context.getSource().getPlayer(); var player = context.getSource().getPlayer();
var playerContext = PlaceholderContext.of(player);
var lastPosition = BackTracker.lastPlayerPositions.get(player.getUuid()); var lastPosition = BackTracker.lastPlayerPositions.get(player.getUuid());
if (lastPosition == null) { 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; 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); lastPosition.teleport(player);
return 1; return 1;

View file

@ -1,21 +1,23 @@
package cc.reconnected.server.commands.teleport; package cc.reconnected.server.commands.teleport;
import cc.reconnected.server.RccServer;
import cc.reconnected.server.core.TeleportTracker; import cc.reconnected.server.core.TeleportTracker;
import cc.reconnected.server.struct.ServerPosition; import cc.reconnected.server.struct.ServerPosition;
import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext; 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.command.argument.UuidArgumentType;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Style;
import net.minecraft.text.Text; 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 class TeleportAcceptCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var node = dispatcher.register(literal("tpaccept") var node = dispatcher.register(literal("tpaccept")
.executes(context -> { .executes(context -> {
if (!context.getSource().isExecutedByPlayer()) { if (!context.getSource().isExecutedByPlayer()) {
@ -23,14 +25,18 @@ public class TeleportAcceptCommand {
return 1; return 1;
} }
var playerUuid = context.getSource().getPlayer().getUuid(); var player = context.getSource().getPlayer();
var playerUuid = player.getUuid();
var playerRequests = TeleportTracker.teleportRequests.get(playerUuid); var playerRequests = TeleportTracker.teleportRequests.get(playerUuid);
var playerContext = PlaceholderContext.of(player);
var request = playerRequests.pollLast(); var request = playerRequests.pollLast();
if (request == null) { 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; return 1;
} }
@ -45,13 +51,18 @@ public class TeleportAcceptCommand {
return 1; return 1;
} }
var player = context.getSource().getPlayer();
var uuid = UuidArgumentType.getUuid(context, "uuid"); var uuid = UuidArgumentType.getUuid(context, "uuid");
var playerUuid = context.getSource().getPlayer().getUuid(); var playerUuid = player.getUuid();
var playerRequests = TeleportTracker.teleportRequests.get(playerUuid); var playerRequests = TeleportTracker.teleportRequests.get(playerUuid);
var playerContext = PlaceholderContext.of(player);
var request = playerRequests.stream().filter(req -> req.requestId.equals(uuid)).findFirst().orElse(null); var request = playerRequests.stream().filter(req -> req.requestId.equals(uuid)).findFirst().orElse(null);
if (request == 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; return 1;
} }
@ -74,19 +85,40 @@ public class TeleportAcceptCommand {
var sourcePlayer = playerManager.getPlayer(request.player); var sourcePlayer = playerManager.getPlayer(request.player);
var targetPlayer = playerManager.getPlayer(request.target); var targetPlayer = playerManager.getPlayer(request.target);
var playerContext = PlaceholderContext.of(player);
if (sourcePlayer == null || targetPlayer == null) { 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; return;
} }
if (player.getUuid().equals(request.target)) { if (player.getUuid().equals(request.target)) {
var sourceContext = PlaceholderContext.of(sourcePlayer);
// accepted a tpa from other to self // accepted a tpa from other to self
context.getSource().sendFeedback(() -> Text.literal("Teleport request accepted.").formatted(Formatting.GREEN), false); context.getSource().sendFeedback(() -> Components.parse(
sourcePlayer.sendMessage(Text.literal("Teleporting...").formatted(Formatting.GOLD), false); RccServer.CONFIG.textFormats.commands.teleportRequest.requestAcceptedResult,
playerContext
), false);
sourcePlayer.sendMessage(Components.parse(
RccServer.CONFIG.textFormats.commands.teleportRequest.teleporting,
sourceContext
), false);
} else { } else {
var targetContext = PlaceholderContext.of(targetPlayer);
// accepted a tpa from self to other // accepted a tpa from self to other
context.getSource().sendFeedback(() -> Text.literal("Teleporting...").formatted(Formatting.GOLD), false); context.getSource().sendFeedback(() -> Components.parse(
targetPlayer.sendMessage(Text.empty().append(player.getDisplayName()).append(Text.literal(" accepted your teleport request.").formatted(Formatting.GREEN)), false); 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); var targetPosition = new ServerPosition(targetPlayer);

View file

@ -1,24 +1,23 @@
package cc.reconnected.server.commands.teleport; package cc.reconnected.server.commands.teleport;
import cc.reconnected.server.RccServer;
import cc.reconnected.server.core.TeleportTracker; import cc.reconnected.server.core.TeleportTracker;
import cc.reconnected.server.util.Components; import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import net.kyori.adventure.text.Component; import eu.pb4.placeholders.api.PlaceholderContext;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Style;
import net.minecraft.text.Text; 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 class TeleportAskCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var node = dispatcher.register(literal("tpa") var node = dispatcher.register(literal("tpa")
.then(argument("player", StringArgumentType.word()) .then(argument("player", StringArgumentType.word())
.suggests((context, builder) -> { .suggests((context, builder) -> {
@ -47,27 +46,45 @@ public class TeleportAskCommand {
var targetName = StringArgumentType.getString(context, "player"); var targetName = StringArgumentType.getString(context, "player");
var playerManager = server.getPlayerManager(); var playerManager = server.getPlayerManager();
var target = playerManager.getPlayer(targetName); var target = playerManager.getPlayer(targetName);
var playerContext = PlaceholderContext.of(player);
if (target == null) { 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; return;
} }
var request = new TeleportTracker.TeleportRequest(player.getUuid(), target.getUuid()); var request = new TeleportTracker.TeleportRequest(player.getUuid(), target.getUuid());
var targetRequests = TeleportTracker.teleportRequests.get(target.getUuid()); var targetRequests = TeleportTracker.teleportRequests.get(target.getUuid());
targetRequests.addLast(request); 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() target.sendMessage(Components.parse(
.append(player.getDisplayName()) RccServer.CONFIG.textFormats.commands.teleportRequest.pendingTeleport,
.appendSpace() targetContext,
.append(Component.text("requested to teleport to you.", NamedTextColor.GOLD)) placeholders
.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(requestMessage); source.sendFeedback(() -> Components.parse(
RccServer.CONFIG.textFormats.commands.teleportRequest.requestSent,
source.sendFeedback(() -> Text.literal("Teleport request sent.").setStyle(Style.EMPTY.withColor(Formatting.GREEN)), false); playerContext
), false);
} }
} }

View file

@ -1,25 +1,23 @@
package cc.reconnected.server.commands.teleport; package cc.reconnected.server.commands.teleport;
import cc.reconnected.server.RccServer;
import cc.reconnected.server.core.TeleportTracker; import cc.reconnected.server.core.TeleportTracker;
import cc.reconnected.server.util.Components; import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import net.kyori.adventure.text.Component; import eu.pb4.placeholders.api.PlaceholderContext;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Style;
import net.minecraft.text.Text; 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.argument;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
public class TeleportAskHereCommand { public class TeleportAskHereCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var node = dispatcher.register(literal("tpahere") var node = dispatcher.register(literal("tpahere")
.then(argument("player", StringArgumentType.word()) .then(argument("player", StringArgumentType.word())
.suggests((context, builder) -> { .suggests((context, builder) -> {
@ -48,8 +46,16 @@ public class TeleportAskHereCommand {
var targetName = StringArgumentType.getString(context, "player"); var targetName = StringArgumentType.getString(context, "player");
var playerManager = server.getPlayerManager(); var playerManager = server.getPlayerManager();
var target = playerManager.getPlayer(targetName); var target = playerManager.getPlayer(targetName);
var playerContext = PlaceholderContext.of(player);
if (target == null) { 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; return;
} }
@ -57,17 +63,28 @@ public class TeleportAskHereCommand {
var targetRequests = TeleportTracker.teleportRequests.get(target.getUuid()); var targetRequests = TeleportTracker.teleportRequests.get(target.getUuid());
targetRequests.addLast(request); targetRequests.addLast(request);
var requestMessage = Component.empty() var targetContext = PlaceholderContext.of(target);
.append(player.getDisplayName()) var placeholders = Map.of(
.appendSpace() "requesterPlayer", player.getDisplayName(),
.append(Component.text("requested you to teleport to them.", NamedTextColor.GOLD)) "acceptButton", Components.button(
.appendNewline().appendSpace() RccServer.CONFIG.textFormats.commands.common.accept,
.append(Components.makeButton(Component.text("Accept", NamedTextColor.GREEN), Component.text("Click to accept request"), "/tpaccept " + request.requestId)) RccServer.CONFIG.textFormats.commands.teleportRequest.hoverAccept,
.appendSpace() "/tpaccept " + request.requestId),
.append(Components.makeButton(Component.text("Refuse", NamedTextColor.RED), Component.text("Click to refuse request"), "/tpdeny " + 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);
} }
} }

View file

@ -1,22 +1,23 @@
package cc.reconnected.server.commands.teleport; package cc.reconnected.server.commands.teleport;
import cc.reconnected.server.RccServer;
import cc.reconnected.server.core.TeleportTracker; import cc.reconnected.server.core.TeleportTracker;
import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext; 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.command.argument.UuidArgumentType;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Style;
import net.minecraft.text.Text; 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.argument;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
public class TeleportDenyCommand { public class TeleportDenyCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var node = dispatcher.register(literal("tpdeny") var node = dispatcher.register(literal("tpdeny")
.executes(context -> { .executes(context -> {
if (!context.getSource().isExecutedByPlayer()) { if (!context.getSource().isExecutedByPlayer()) {
@ -24,13 +25,18 @@ public class TeleportDenyCommand {
return 1; return 1;
} }
var playerUuid = context.getSource().getPlayer().getUuid(); var player = context.getSource().getPlayer();
var playerUuid = player.getUuid();
var playerRequests = TeleportTracker.teleportRequests.get(playerUuid); var playerRequests = TeleportTracker.teleportRequests.get(playerUuid);
var playerContext = PlaceholderContext.of(player);
var request = playerRequests.pollLast(); var request = playerRequests.pollLast();
if (request == null) { 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; return 1;
} }
@ -45,13 +51,18 @@ public class TeleportDenyCommand {
return 1; return 1;
} }
var player = context.getSource().getPlayer();
var uuid = UuidArgumentType.getUuid(context, "uuid"); var uuid = UuidArgumentType.getUuid(context, "uuid");
var playerUuid = context.getSource().getPlayer().getUuid(); var playerUuid = player.getUuid();
var playerRequests = TeleportTracker.teleportRequests.get(playerUuid); var playerRequests = TeleportTracker.teleportRequests.get(playerUuid);
var playerContext = PlaceholderContext.of(player);
var request = playerRequests.stream().filter(req -> req.requestId.equals(uuid)).findFirst().orElse(null); var request = playerRequests.stream().filter(req -> req.requestId.equals(uuid)).findFirst().orElse(null);
if (request == 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; return 1;
} }
@ -69,8 +80,8 @@ public class TeleportDenyCommand {
request.expire(); request.expire();
var player = source.getPlayer(); var player = source.getPlayer();
var playerManager = context.getSource().getServer().getPlayerManager(); var playerManager = context.getSource().getServer().getPlayerManager();
var playerContext = PlaceholderContext.of(player);
ServerPlayerEntity otherPlayer = null; ServerPlayerEntity otherPlayer = null;
if (player.getUuid().equals(request.target)) { if (player.getUuid().equals(request.target)) {
@ -80,8 +91,17 @@ public class TeleportDenyCommand {
} }
if (otherPlayer != null) { 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);
} }
} }

View file

@ -1,21 +1,20 @@
package cc.reconnected.server.commands.tell; 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.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import eu.pb4.placeholders.api.PlaceholderContext;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.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 class ReplyCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var messageNode = dispatcher.register(literal("reply") var messageNode = dispatcher.register(literal("reply")
.requires(Permissions.require("rcc.command.tell", true)) .requires(Permissions.require("rcc.command.tell", true))
.then(argument("message", StringArgumentType.greedyString()) .then(argument("message", StringArgumentType.greedyString())
@ -30,7 +29,11 @@ public class ReplyCommand {
var message = StringArgumentType.getString(context, "message"); var message = StringArgumentType.getString(context, "message");
if (!TellCommand.lastSender.containsKey(senderName)) { 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; return 1;
} }

View file

@ -1,34 +1,28 @@
package cc.reconnected.server.commands.tell; package cc.reconnected.server.commands.tell;
import cc.reconnected.server.RccServer; 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.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import eu.pb4.placeholders.api.PlaceholderContext;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.command.CommandSource;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Style;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import java.util.HashMap; 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 class TellCommand {
public static final HashMap<String, String> lastSender = new HashMap<>(); public static final HashMap<String, String> lastSender = new HashMap<>();
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var messageNode = dispatcher.register(literal("msg") var messageNode = dispatcher.register(literal("msg")
.requires(Permissions.require("rcc.command.tell", true)) .requires(Permissions.require("rcc.command.tell", true))
.then(argument("player", StringArgumentType.word()) .then(argument("player", StringArgumentType.word())
@ -63,28 +57,73 @@ public class TellCommand {
} else { } else {
targetPlayer = source.getServer().getPlayerManager().getPlayer(targetName); targetPlayer = source.getServer().getPlayerManager().getPlayer(targetName);
if (targetPlayer == null) { 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; return;
} }
targetDisplayName = targetPlayer.getDisplayName(); targetDisplayName = targetPlayer.getDisplayName();
} }
var parsedMessage = MarkdownParser.defaultParser.parseNode(message); var parsedMessage = Components.chat(message, source);
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 targetText = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage, var serverContext = PlaceholderContext.of(source.getServer());
Placeholder.component("source", source.getDisplayName()), var sourceContext = PlaceholderContext.of(source);
Placeholder.component("target", you), PlaceholderContext targetContext;
Placeholder.component("message", parsedMessage.toText())); if (targetPlayer == null) {
targetContext = serverContext;
} else {
targetContext = PlaceholderContext.of(targetPlayer);
}
var text = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage,
Placeholder.component("source", source.getDisplayName()), var you = Components.parse(RccServer.CONFIG.textFormats.commands.tell.you);
Placeholder.component("target", targetDisplayName),
Placeholder.component("message", parsedMessage.toText())); 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(targetName, source.getName());
lastSender.put(source.getName(), targetName); lastSender.put(source.getName(), targetName);
@ -95,7 +134,7 @@ public class TellCommand {
if (targetPlayer != null) { if (targetPlayer != null) {
targetPlayer.sendMessage(targetText); targetPlayer.sendMessage(targetText);
if (source.isExecutedByPlayer()) { if (source.isExecutedByPlayer()) {
source.getServer().sendMessage(text); source.getServer().sendMessage(genericText);
} }
} else { } else {
// avoid duped message // avoid duped message
@ -104,10 +143,6 @@ public class TellCommand {
var lp = RccServer.getInstance().luckPerms(); var lp = RccServer.getInstance().luckPerms();
var playerAdapter = lp.getPlayerAdapter(ServerPlayerEntity.class); 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 -> { source.getServer().getPlayerManager().getPlayerList().forEach(player -> {
var playerName = player.getGameProfile().getName(); var playerName = player.getGameProfile().getName();
if (playerName.equals(targetName) || playerName.equals(source.getName())) { if (playerName.equals(targetName) || playerName.equals(source.getName())) {

View file

@ -5,9 +5,7 @@ import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import me.lucko.fabric.api.permissions.v0.Permissions; import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting; 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; import static net.minecraft.server.command.CommandManager.literal;
public class DeleteWarpCommand { public class DeleteWarpCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("delwarp") var rootCommand = literal("delwarp")
.requires(Permissions.require("rcc.command.delwarp", 3)) .requires(Permissions.require("rcc.command.delwarp", 3))
.then(argument("name", StringArgumentType.word()) .then(argument("name", StringArgumentType.word())

View file

@ -6,16 +6,15 @@ import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import me.lucko.fabric.api.permissions.v0.Permissions; 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.command.ServerCommandSource;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Formatting; 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 class SetWarpCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("setwarp") var rootCommand = literal("setwarp")
.requires(Permissions.require("rcc.command.setwarp", 3)) .requires(Permissions.require("rcc.command.setwarp", 3))
.then(argument("name", StringArgumentType.word()) .then(argument("name", StringArgumentType.word())

View file

@ -1,21 +1,23 @@
package cc.reconnected.server.commands.warp; package cc.reconnected.server.commands.warp;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.util.Components;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import eu.pb4.placeholders.api.PlaceholderContext;
import me.lucko.fabric.api.permissions.v0.Permissions; import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Text; 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 class WarpCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
var rootCommand = literal("warp") var rootCommand = literal("warp")
.requires(Permissions.require("rcc.command.warp", true)) .requires(Permissions.require("rcc.command.warp", true))
.then(argument("name", StringArgumentType.word()) .then(argument("name", StringArgumentType.word())
@ -39,20 +41,23 @@ public class WarpCommand {
var player = context.getSource().getPlayer(); var player = context.getSource().getPlayer();
var serverState = RccServer.state.getServerState(); var serverState = RccServer.state.getServerState();
var warps = serverState.warps; var warps = serverState.warps;
var playerContext = PlaceholderContext.of(player);
if (!warps.containsKey(name)) { if (!warps.containsKey(name)) {
context.getSource().sendFeedback(() -> Text.literal("The warp ") context.getSource().sendFeedback(() -> Components.parse(
.append(Text.literal(name).formatted(Formatting.GOLD)) RccServer.CONFIG.textFormats.commands.warp.warpNotFound,
.append(" does not exist!") playerContext
.formatted(Formatting.RED), false); ), false);
return 1; return 1;
} }
context.getSource().sendFeedback(() -> Text context.getSource().sendFeedback(() -> Components.parse(
.literal("Teleporting to ") RccServer.CONFIG.textFormats.commands.warp.teleporting,
.append(Text.literal(name).formatted(Formatting.GREEN)) playerContext,
.append("...") Map.of(
.formatted(Formatting.GOLD), false); "warp", Text.of(name)
)
), false);
var warpPosition = warps.get(name); var warpPosition = warps.get(name);
warpPosition.teleport(player); warpPosition.teleport(player);

View file

@ -1,7 +1,9 @@
package cc.reconnected.server.config; package cc.reconnected.server.config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
public class Config { public class Config {
Config() { Config() {
@ -9,12 +11,12 @@ public class Config {
public HttpApi httpApi = new HttpApi(); public HttpApi httpApi = new HttpApi();
public Afk afk = new Afk(); public Afk afk = new Afk();
public DirectMessages directMessages = new DirectMessages();
public TeleportRequests teleportRequests = new TeleportRequests(); public TeleportRequests teleportRequests = new TeleportRequests();
public Homes homes = new Homes(); public Homes homes = new Homes();
public CustomTabList customTabList = new CustomTabList(); public CustomTabList customTabList = new CustomTabList();
public NearCommand nearCommand = new NearCommand(); public NearCommand nearCommand = new NearCommand();
public AutoRestart autoRestart = new AutoRestart(); public AutoRestart autoRestart = new AutoRestart();
public Chat chat = new Chat();
public TextFormats textFormats = new TextFormats(); public TextFormats textFormats = new TextFormats();
public static class HttpApi { public static class HttpApi {
@ -24,14 +26,6 @@ public class Config {
public static class Afk { public static class Afk {
public int afkTimeTrigger = 300; public int afkTimeTrigger = 300;
public String afkMessage = "<gray><displayname> is now AFK</gray>";
public String afkReturnMessage = "<gray><displayname> is no longer AFK</gray>";
public String afkTag = "<gray>[AFK]</gray> ";
}
public static class DirectMessages {
public String tellMessage = "<gold>[</gold><source> <gray>→</gray> <target><gold>]</gold> <message>";
public String tellMessageSpy = "\uD83D\uDC41 <gray>[<source> → <target>] <message></gray>";
} }
public static class TeleportRequests { public static class TeleportRequests {
@ -92,23 +86,115 @@ public class Config {
)); ));
} }
public static class Chat {
public boolean enableChatMarkdown = true;
public HashMap<String, String> replacements = new HashMap<>(Map.of(
":shrug:", "¯\\\\_(ツ)_/¯"
));
}
public static class TextFormats { public static class TextFormats {
public record NameFormat(String group, String format) { public record NameFormat(String group, String format) {
} }
public boolean enableChatMarkdown = true;
public ArrayList<NameFormat> nameFormats = new ArrayList<>(List.of( public ArrayList<NameFormat> nameFormats = new ArrayList<>(List.of(
new NameFormat("admin", "<red>%player:name%</red>"), new NameFormat("admin", "<red>%player:name%</red>"),
new NameFormat("default", "<green>%player:name%</green>") new NameFormat("default", "<green>%player:name%</green>")
)); ));
public String chatFormat = "${player}<gray>:</gray> ${message}"; public String chatFormat = "%player:displayname%<gray>:</gray> ${message}";
public String emoteFormat = "<gray>\uD83D\uDC64 ${player} <i>${message}</i></gray>"; public String emoteFormat = "<gray>\uD83D\uDC64 %player:displayname% <i>${message}</i></gray>";
public String joinFormat = "<green>+</green> ${player} <yellow>joined!</yellow>"; public String joinFormat = "<green>+</green> %player:displayname% <yellow>joined!</yellow>";
public String joinRenamedFormat = "<green>+</green> ${player} <yellow>joined! <i>(Previously known as ${previousName})</i></yellow>"; public String joinRenamedFormat = "<green>+</green> %player:displayname% <yellow>joined! <i>(Previously known as ${previousName})</i></yellow>";
public String leaveFormat = "<red>-</red> ${player} <yellow>left!</yellow>"; public String leaveFormat = "<red>-</red> %player:displayname% <yellow>left!</yellow>";
public String deathFormat = "<gray>\u2620 ${message}</gray>"; public String deathFormat = "<gray>\u2620 ${message}</gray>";
public String link = "<c:#8888ff><u>${label}</u></c>";
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 = "<click:run_command:'{{command}}'><hover:show_text:'${hoverText}'><aqua>[</aqua>${label}<aqua>]</aqua></hover></click>";
public String accept = "<green>Accept</green>";
public String refuse = "<red>Refuse</red>";
}
public static class Back {
public String teleporting = "<gold>Teleporting to previous position...</gold>";
public String noPosition = "<red>There is no position to return back to.</red>";
}
public static class Near {
public String noOne = "<gold>There are no players near you.</gold>";
public String nearestPlayers = "<gold>Nearest players: ${playerList}</gold>";
public String format = "${player} <gold>(</gold><yellow>${distance}</yellow><gold>)</gold>";
public String comma = "<gold>, </gold>";
}
public static class Home {
public String teleporting = "<gold>Teleporting to <yellow>${home}</yellow></gold>";
public String homeExists = "<gold>You already have set this home.</gold>\n ${forceSetButton}";
public String homeNotFound = "<red>The home <yellow>${home}</yellow> does not exist!</red>";
public String maxHomesReached = "<red>You have reached the maximum amount of homes!</red>";
public String homeSetSuccess = "<gold>New home <yellow>${home}</yellow> set!</gold>";
public String forceSetLabel = "<yellow>Force set home</yellow>";
public String forceSetHover = "Click to force setting new home";
public String homeDeleted = "<gold>Home <yellow>${home}</yellow> deleted!</gold>";
}
public static class Spawn {
public String teleporting = "<gold>Teleporting to spawn...</gold>";
}
public static class TeleportRequest {
public String teleporting = "<gold>Teleporting...</gold>";
public String playerNotFound = "<red>Player <yellow>${targetPlayer}</yellow> not found!</red>";
public String requestSent = "<gold>Teleport request sent.</gold>";
public String pendingTeleport = "${requesterPlayer} <gold>requested to teleport to you.</gold>\n ${acceptButton} ${refuseButton}";
public String pendingTeleportHere = "${requesterPlayer} <gold>requested you to teleport to them.</gold>\n ${acceptButton} ${refuseButton}";
public String hoverAccept = "Click to accept request";
public String hoverRefuse = "Click to refuse request";
public String noPending = "<gold>There are no pending teleport requests for you.</gold>";
public String unavailable = "<red>This requested expired or is no longer available.</red>";
public String playerUnavailable = "<red>The other player is no longer available.</red>";
public String requestAcceptedResult = "<green>Teleport request accepted.</green>";
public String requestRefusedResult = "<gold>Teleport request refused.</gold>";
public String requestAccepted = "<green>${player} accepted your teleport request!</green>";
public String requestRefused = "<gold>${player} refused your teleport request!</gold>";
}
public static class Tell {
public String playerNotFound = "<red>Player <yellow>${targetPlayer}</yellow> not found!</red>";
public String you = "<gray><i>You</i></gray>";
public String message = "<gold>[</gold>${sourcePlayer} <gray>→</gray> ${targetPlayer}<gold>]</gold> ${message}";
public String messageSpy = "\uD83D\uDC41 <gray>[${sourcePlayer} → ${targetPlayer}] ${message}</gray>";
public String noLastSenderReply = "<red>You have no one to reply to.</red>"; // relatable
}
public static class Warp {
public String teleporting = "<gold>Warping to <yellow>${warp}</yellow>...</gold>";
public String warpNotFound = "<red>The warp <yellow>${warp}</yellow> does not exist!</red>";
}
public static class Afk {
public String goneAfk = "<gray>%player:displayname% is now AFK</gray>";
public String returnAfk = "<gray>%player:displayname% is no longer AFK</gray>";
public String tag = "<gray>[AFK]</gray> ";
}
}
} }

View file

@ -1,7 +1,6 @@
package cc.reconnected.server.config; package cc.reconnected.server.config;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;

View file

@ -4,15 +4,14 @@ import cc.reconnected.server.RccServer;
import cc.reconnected.server.api.events.PlayerActivityEvents; import cc.reconnected.server.api.events.PlayerActivityEvents;
import cc.reconnected.server.api.events.RccEvents; import cc.reconnected.server.api.events.RccEvents;
import cc.reconnected.server.util.Components; import cc.reconnected.server.util.Components;
import eu.pb4.placeholders.api.PlaceholderContext;
import eu.pb4.placeholders.api.PlaceholderResult; import eu.pb4.placeholders.api.PlaceholderResult;
import eu.pb4.placeholders.api.Placeholders; 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.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.player.*; import net.fabricmc.fabric.api.event.player.*;
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; 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.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text; import net.minecraft.text.Text;
@ -54,38 +53,30 @@ public class AfkTracker {
PlayerActivityEvents.AFK.register((player, server) -> { PlayerActivityEvents.AFK.register((player, server) -> {
RccServer.LOGGER.info("{} is AFK. Active time: {} seconds.", player.getGameProfile().getName(), getInstance().getActiveTime(player)); RccServer.LOGGER.info("{} is AFK. Active time: {} seconds.", player.getGameProfile().getName(), getInstance().getActiveTime(player));
var displayNameJson = Text.Serializer.toJson(player.getDisplayName()); var playerContext = PlaceholderContext.of(player);
var displayName = JSONComponentSerializer.json().deserialize(displayNameJson);
var message = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkMessage, RccServer.getInstance().broadcast(Components.parse(
Placeholder.component("displayname", displayName), RccServer.CONFIG.textFormats.commands.afk.goneAfk,
Placeholder.unparsed("username", player.getGameProfile().getName()), playerContext
Placeholder.unparsed("uuid", player.getUuid().toString()) ));
);
RccServer.getInstance().broadcastMessage(server, message);
}); });
PlayerActivityEvents.AFK_RETURN.register((player, server) -> { PlayerActivityEvents.AFK_RETURN.register((player, server) -> {
RccServer.LOGGER.info("{} is no longer AFK. Active time: {} seconds.", player.getGameProfile().getName(), getInstance().getActiveTime(player)); RccServer.LOGGER.info("{} is no longer AFK. Active time: {} seconds.", player.getGameProfile().getName(), getInstance().getActiveTime(player));
var displayNameJson = Text.Serializer.toJson(player.getDisplayName()); var playerContext = PlaceholderContext.of(player);
var displayName = JSONComponentSerializer.json().deserialize(displayNameJson);
var message = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkReturnMessage, RccServer.getInstance().broadcast(Components.parse(
Placeholder.component("displayname", displayName), RccServer.CONFIG.textFormats.commands.afk.returnAfk,
Placeholder.unparsed("username", player.getGameProfile().getName()), playerContext
Placeholder.unparsed("uuid", player.getUuid().toString()) ));
);
RccServer.getInstance().broadcastMessage(server, message);
}); });
RccEvents.RELOAD.register(inst -> loadAfkTag()); RccEvents.RELOAD.register(inst -> loadAfkTag());
} }
private static void 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() { private AfkTracker() {

View file

@ -119,7 +119,7 @@ public class AutoRestart {
audience.playSound(sound, Sound.Emitter.self()); audience.playSound(sound, Sound.Emitter.self());
var comp = bar.parseLabel(RccServer.CONFIG.autoRestart.restartChatMessage); var comp = bar.parseLabel(RccServer.CONFIG.autoRestart.restartChatMessage);
rcc.broadcastMessage(server, comp); rcc.broadcastComponent(server, comp);
} }
@Nullable @Nullable

View file

@ -1,9 +1,9 @@
package cc.reconnected.server.core; package cc.reconnected.server.core;
import cc.reconnected.server.RccServer;
import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer; 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.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;

View file

@ -1,15 +1,8 @@
package cc.reconnected.server.core.customChat; package cc.reconnected.server.core.customChat;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.parser.MarkdownParser;
import cc.reconnected.server.util.Components; import cc.reconnected.server.util.Components;
import eu.pb4.placeholders.api.Placeholders; import eu.pb4.placeholders.api.PlaceholderContext;
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.network.message.MessageType; import net.minecraft.network.message.MessageType;
import net.minecraft.network.message.SignedMessage; import net.minecraft.network.message.SignedMessage;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
@ -19,26 +12,29 @@ import net.minecraft.text.Text;
import java.util.Map; import java.util.Map;
public class CustomChatMessage { public class CustomChatMessage {
private static final MiniMessage miniMessage = MiniMessage.miniMessage();
public static void sendChatMessage(ServerPlayerEntity receiver, SignedMessage message, MessageType.Parameters params) { public static void sendChatMessage(ServerPlayerEntity receiver, SignedMessage message, MessageType.Parameters params) {
var playerUuid = message.link().sender(); var playerUuid = message.link().sender();
var player = RccServer.server.getPlayerManager().getPlayer(playerUuid); var player = RccServer.server.getPlayerManager().getPlayer(playerUuid);
Text messageText = Utils.formatChatMessage(message, player); var text = getFormattedMessage(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 msgType = RccServer.server.getRegistryManager().get(RegistryKeys.MESSAGE_TYPE).getOrThrow(RccServer.CHAT_TYPE); var msgType = RccServer.server.getRegistryManager().get(RegistryKeys.MESSAGE_TYPE).getOrThrow(RccServer.CHAT_TYPE);
var newParams = new MessageType.Parameters(msgType, text, null); var newParams = new MessageType.Parameters(msgType, text, null);
receiver.networkHandler.sendChatMessage(message, newParams); 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;
}
} }

View file

@ -2,46 +2,35 @@ package cc.reconnected.server.core.customChat;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.util.Components; import cc.reconnected.server.util.Components;
import eu.pb4.placeholders.api.Placeholders; import eu.pb4.placeholders.api.PlaceholderContext;
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.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import java.util.Map; import java.util.Map;
public class CustomConnectionMessage { public class CustomConnectionMessage {
private static final MiniMessage miniMessage = MiniMessage.miniMessage();
public static Text onJoin(ServerPlayerEntity player) { public static Text onJoin(ServerPlayerEntity player) {
var placeholders = Map.of( var playerContext = PlaceholderContext.of(player);
"player", player.getDisplayName() 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) { public static Text onJoinRenamed(ServerPlayerEntity player, String previousName) {
var placeholders = Map.of( var playerContext = PlaceholderContext.of(player);
"previousName", Text.of(previousName), return Components.parse(
"player", player.getDisplayName() 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) { public static Text onLeave(ServerPlayerEntity player) {
var placeholders = Map.of( var playerContext = PlaceholderContext.of(player);
"player", player.getDisplayName() 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);
} }
} }

View file

@ -3,13 +3,6 @@ package cc.reconnected.server.core.customChat;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.util.Components; import cc.reconnected.server.util.Components;
import eu.pb4.placeholders.api.PlaceholderContext; 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.entity.damage.DamageTracker;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text; import net.minecraft.text.Text;
@ -17,17 +10,14 @@ import net.minecraft.text.Text;
import java.util.Map; import java.util.Map;
public class CustomDeathMessage { public class CustomDeathMessage {
private static final MiniMessage miniMessage = MiniMessage.miniMessage();
public static Text onDeath(ServerPlayerEntity player, DamageTracker instance) { public static Text onDeath(ServerPlayerEntity player, DamageTracker instance) {
var deathMessage = instance.getDeathMessage(); var deathMessage = instance.getDeathMessage();
var playerContext = PlaceholderContext.of(player);
var placeholders = Map.of( return Components.parse(
"message", deathMessage, RccServer.CONFIG.textFormats.deathFormat,
"player", player.getDisplayName() playerContext,
Map.of("message", deathMessage)
); );
var format = TextParserUtils.formatText(RccServer.CONFIG.textFormats.deathFormat);
return Placeholders.parseText(format, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders);
} }
} }

View file

@ -1,10 +1,8 @@
package cc.reconnected.server.core.customChat; package cc.reconnected.server.core.customChat;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import eu.pb4.placeholders.api.Placeholders; import cc.reconnected.server.util.Components;
import eu.pb4.placeholders.api.TextParserUtils; import eu.pb4.placeholders.api.PlaceholderContext;
import eu.pb4.placeholders.api.parsers.PatternPlaceholderParser;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.minecraft.network.message.MessageType; import net.minecraft.network.message.MessageType;
import net.minecraft.network.message.SignedMessage; import net.minecraft.network.message.SignedMessage;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
@ -14,22 +12,21 @@ import net.minecraft.text.Text;
import java.util.Map; import java.util.Map;
public class CustomEmoteMessage { public class CustomEmoteMessage {
private static final MiniMessage miniMessage = MiniMessage.miniMessage();
public static void sendEmoteMessage(ServerPlayerEntity receiver, SignedMessage message, MessageType.Parameters params) { public static void sendEmoteMessage(ServerPlayerEntity receiver, SignedMessage message, MessageType.Parameters params) {
var playerUuid = message.link().sender(); var playerUuid = message.link().sender();
var player = RccServer.server.getPlayerManager().getPlayer(playerUuid); 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( var text = Components.parse(
"message", messageText, RccServer.CONFIG.textFormats.emoteFormat,
"player", player.getDisplayName() 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 msgType = RccServer.server.getRegistryManager().get(RegistryKeys.MESSAGE_TYPE).getOrThrow(RccServer.CHAT_TYPE);
var newParams = new MessageType.Parameters(msgType, text, null); var newParams = new MessageType.Parameters(msgType, text, null);

View file

@ -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();
}
}

View file

@ -3,7 +3,7 @@ package cc.reconnected.server.mixin;
import cc.reconnected.server.core.customChat.CustomSentMessage; import cc.reconnected.server.core.customChat.CustomSentMessage;
import net.minecraft.network.message.SentMessage; import net.minecraft.network.message.SentMessage;
import net.minecraft.network.message.SignedMessage; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

View file

@ -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<TextNode>();
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<TextNode>();
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);
}
}

View file

@ -1,10 +1,16 @@
package cc.reconnected.server.parser; 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.TextNode;
import eu.pb4.placeholders.api.node.parent.*; import eu.pb4.placeholders.api.node.parent.ClickActionNode;
import net.minecraft.text.*; 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 net.minecraft.util.Formatting;
import java.util.Map;
public class MarkdownComponentParser { public class MarkdownComponentParser {
public static TextNode spoilerFormatting(TextNode[] textNodes) { public static TextNode spoilerFormatting(TextNode[] textNodes) {
var text = TextNode.asSingle(textNodes); var text = TextNode.asSingle(textNodes);
@ -27,16 +33,20 @@ public class MarkdownComponentParser {
} }
public static TextNode urlFormatting(TextNode[] textNodes, TextNode url) { 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( return new HoverNode<>(TextNode.array(
new ClickActionNode( new ClickActionNode(
TextNode.array( TextNode.array(
new StyledNode(textNodes, TextNode.convert(text)
Style.EMPTY.withColor(0x8888ff).withUnderline(true),
null, null, null
)
), ),
ClickEvent.Action.OPEN_URL, url)), ClickEvent.Action.OPEN_URL, url)),
HoverNode.Action.TEXT, TextNode.of("Click to open: " + url.toText().getString()) HoverNode.Action.TEXT, TextNode.convert(hover)
); );
} }
} }

View file

@ -20,11 +20,13 @@ public class MarkdownParser {
public static final NodeParser defaultParser = createParser(ALL); public static final NodeParser defaultParser = createParser(ALL);
public static NodeParser createParser(MarkdownFormat[] capabilities) { public static NodeParser createParser(MarkdownFormat[] capabilities) {
return new MarkdownLiteParserV1( var mdParser = new MarkdownLiteParserV1(
MarkdownComponentParser::spoilerFormatting, MarkdownComponentParser::spoilerFormatting,
MarkdownComponentParser::quoteFormatting, MarkdownComponentParser::quoteFormatting,
MarkdownComponentParser::urlFormatting, MarkdownComponentParser::urlFormatting,
capabilities capabilities
); );
return NodeParser.merge(mdParser, new LinkParser());
} }
} }

View file

@ -1,15 +1,32 @@
package cc.reconnected.server.util; 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.Component;
import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; 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.MutableText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import java.util.Map;
public class Components { public class Components {
@Deprecated
public static Component makeButton(ComponentLike text, ComponentLike hoverText, String command) { public static Component makeButton(ComponentLike text, ComponentLike hoverText, String command) {
return Component.empty() return Component.empty()
.append(Component.text("[")) .append(Component.text("["))
@ -20,8 +37,101 @@ public class Components {
.clickEvent(ClickEvent.runCommand(command)); .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) { public static MutableText toText(Component component) {
var json = JSONComponentSerializer.json().serialize(component); var json = JSONComponentSerializer.json().serialize(component);
return Text.Serializer.fromJson(json); return Text.Serializer.fromJson(json);
} }
public static Text parse(String text) {
return TextParserUtils.formatText(text);
}
public static Text parse(TextNode textNode, PlaceholderContext context, Map<String, Text> 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<String, Text> placeholders) {
return parse(TextNode.convert(text), context, placeholders);
}
public static Text parse(String text, PlaceholderContext context, Map<String, Text> 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<String, Text> 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);
}
} }