Changed config management, switched to pb4 placeholders in new custom chat formats

This commit is contained in:
Alessandro Proto 2024-11-04 22:55:36 +01:00
parent 362132f696
commit df169f61d7
24 changed files with 218 additions and 149 deletions

View file

@ -17,7 +17,6 @@ repositories {
// See https://docs.gradle.org/current/userguide/declaring_repositories.html // See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories. // for more information about repositories.
maven { url 'https://maven.wispforest.io' }
maven { url 'https://maven.nucleoid.xyz' } maven { url 'https://maven.nucleoid.xyz' }
maven { url 'https://maven.reconnected.cc/releases' } maven { url 'https://maven.reconnected.cc/releases' }
} }
@ -42,9 +41,6 @@ dependencies {
// Fabric API. This is technically optional, but you probably want it anyway. // Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
annotationProcessor modImplementation("io.wispforest:owo-lib:${project.owo_version}")
include "io.wispforest:owo-sentinel:${project.owo_version}"
compileOnly "net.luckperms:api:${project.luckpermsapi_version}" compileOnly "net.luckperms:api:${project.luckpermsapi_version}"
include modImplementation("me.lucko:fabric-permissions-api:${project.permissions_api_version}") include modImplementation("me.lucko:fabric-permissions-api:${project.permissions_api_version}")

View file

@ -16,8 +16,6 @@ archives_base_name=rcc-server
# Dependencies # Dependencies
fabric_version=0.92.2+1.20.1 fabric_version=0.92.2+1.20.1
owo_version=0.11.2+1.20
luckpermsapi_version=5.4 luckpermsapi_version=5.4
permissions_api_version=0.2-SNAPSHOT permissions_api_version=0.2-SNAPSHOT

View file

@ -8,6 +8,8 @@ import cc.reconnected.server.commands.spawn.*;
import cc.reconnected.server.commands.teleport.*; import cc.reconnected.server.commands.teleport.*;
import cc.reconnected.server.commands.tell.*; import cc.reconnected.server.commands.tell.*;
import cc.reconnected.server.commands.warp.*; import cc.reconnected.server.commands.warp.*;
import cc.reconnected.server.config.Config;
import cc.reconnected.server.config.ConfigManager;
import cc.reconnected.server.core.*; import cc.reconnected.server.core.*;
import cc.reconnected.server.data.StateManager; import cc.reconnected.server.data.StateManager;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
@ -36,7 +38,7 @@ public class RccServer implements ModInitializer {
public static final String MOD_ID = "rcc-server"; public static final String MOD_ID = "rcc-server";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
public static final cc.reconnected.server.RccServerConfig CONFIG = cc.reconnected.server.RccServerConfig.createAndLoad(); public static Config CONFIG = ConfigManager.load();
public static final StateManager state = new StateManager(); public static final StateManager state = new StateManager();

View file

@ -2,6 +2,7 @@ package cc.reconnected.server.commands.admin;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.api.events.RccEvents; import cc.reconnected.server.api.events.RccEvents;
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.command.CommandRegistryAccess;
@ -21,7 +22,7 @@ public class RccCommand {
context.getSource().sendFeedback(() -> Text.of("Reloading RCC config..."), true); context.getSource().sendFeedback(() -> Text.of("Reloading RCC config..."), true);
try { try {
RccServer.CONFIG.load(); RccServer.CONFIG = ConfigManager.load();
} catch(Exception e) { } catch(Exception e) {
RccServer.LOGGER.error("Failed to load RCC config", e); RccServer.LOGGER.error("Failed to load RCC config", e);
context.getSource().sendFeedback(() -> Text.of("Failed to load RCC config. Check console for more info."), true); context.getSource().sendFeedback(() -> Text.of("Failed to load RCC config. Check console for more info."), true);

View file

@ -1,7 +1,6 @@
package cc.reconnected.server.commands.admin; package cc.reconnected.server.commands.admin;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.api.events.RccEvents;
import cc.reconnected.server.core.AutoRestart; import cc.reconnected.server.core.AutoRestart;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType;
@ -37,7 +36,7 @@ public class RestartCommand {
private static int schedule(CommandContext<ServerCommandSource> context, int seconds, @Nullable String message) { private static int schedule(CommandContext<ServerCommandSource> context, int seconds, @Nullable String message) {
if (message == null) { if (message == null) {
message = RccServer.CONFIG.autoRestart.restartBarLabel(); message = RccServer.CONFIG.autoRestart.restartBarLabel;
} }
AutoRestart.schedule(seconds, message); AutoRestart.schedule(seconds, message);

View file

@ -62,7 +62,7 @@ public class SetHomeCommand {
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(() -> Text.literal("You have reached the maximum amount of homes!").formatted(Formatting.RED), false);
return 1; return 1;

View file

@ -26,9 +26,9 @@ public class NearCommand {
context.getSource().sendFeedback(() -> Text.of("This command can only be executed by players!"), false); context.getSource().sendFeedback(() -> Text.of("This command can only be executed by players!"), false);
return 1; return 1;
} }
return execute(context, RccServer.CONFIG.nearCommand.nearCommandDefaultRange(), context.getSource().getPlayer()); return execute(context, RccServer.CONFIG.nearCommand.nearCommandDefaultRange, context.getSource().getPlayer());
}) })
.then(argument("radius", IntegerArgumentType.integer(0, RccServer.CONFIG.nearCommand.nearCommandMaxRange())) .then(argument("radius", IntegerArgumentType.integer(0, RccServer.CONFIG.nearCommand.nearCommandMaxRange))
.executes(context -> { .executes(context -> {
if (!context.getSource().isExecutedByPlayer()) { if (!context.getSource().isExecutedByPlayer()) {
context.getSource().sendFeedback(() -> Text.of("This command can only be executed by players!"), false); context.getSource().sendFeedback(() -> Text.of("This command can only be executed by players!"), false);

View file

@ -71,17 +71,17 @@ public class TellCommand {
var parsedMessage = MarkdownParser.defaultParser.parseNode(message); var parsedMessage = MarkdownParser.defaultParser.parseNode(message);
var you = Component.text("You", NamedTextColor.GRAY, TextDecoration.ITALIC); var you = Component.text("You", NamedTextColor.GRAY, TextDecoration.ITALIC);
var sourceText = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage(), var sourceText = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage,
Placeholder.component("source", you), Placeholder.component("source", you),
Placeholder.component("target", targetDisplayName), Placeholder.component("target", targetDisplayName),
Placeholder.component("message", parsedMessage.toText())); Placeholder.component("message", parsedMessage.toText()));
var targetText = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage(), var targetText = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage,
Placeholder.component("source", source.getDisplayName()), Placeholder.component("source", source.getDisplayName()),
Placeholder.component("target", you), Placeholder.component("target", you),
Placeholder.component("message", parsedMessage.toText())); Placeholder.component("message", parsedMessage.toText()));
var text = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage(), var text = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessage,
Placeholder.component("source", source.getDisplayName()), Placeholder.component("source", source.getDisplayName()),
Placeholder.component("target", targetDisplayName), Placeholder.component("target", targetDisplayName),
Placeholder.component("message", parsedMessage.toText())); Placeholder.component("message", parsedMessage.toText()));
@ -104,7 +104,7 @@ 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(), var spyText = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.directMessages.tellMessageSpy,
Placeholder.component("source", source.getDisplayName()), Placeholder.component("source", source.getDisplayName()),
Placeholder.component("target", targetDisplayName), Placeholder.component("target", targetDisplayName),
Placeholder.component("message", parsedMessage.toText())); Placeholder.component("message", parsedMessage.toText()));

View file

@ -1,41 +1,21 @@
package cc.reconnected.server; package cc.reconnected.server.config;
import io.wispforest.owo.config.annotation.Config; import java.util.ArrayList;
import io.wispforest.owo.config.annotation.Nest; import java.util.List;
import java.util.*; public class Config {
Config() {
}
@Config(name = "rcc-server-config", wrapperName = "RccServerConfig")
public class RccServerConfigModel {
@Nest
public HttpApi httpApi = new HttpApi(); public HttpApi httpApi = new HttpApi();
@Nest
public Afk afk = new Afk(); public Afk afk = new Afk();
@Nest
public DirectMessages directMessages = new DirectMessages(); public DirectMessages directMessages = new DirectMessages();
@Nest
public TeleportRequests teleportRequests = new TeleportRequests(); public TeleportRequests teleportRequests = new TeleportRequests();
@Nest
public Homes homes = new Homes(); public Homes homes = new Homes();
@Nest
public CustomTabList customTabList = new CustomTabList(); public CustomTabList customTabList = new CustomTabList();
@Nest
public NearCommand nearCommand = new NearCommand(); public NearCommand nearCommand = new NearCommand();
@Nest
public AutoRestart autoRestart = new AutoRestart(); public AutoRestart autoRestart = new AutoRestart();
public TextFormats textFormats = new TextFormats();
@Nest
public CustomNameConfig customName = new CustomNameConfig();
@Nest
public CustomChatFormat customChatFormat = new CustomChatFormat();
public static class HttpApi { public static class HttpApi {
public boolean enableHttpApi = true; public boolean enableHttpApi = true;
@ -112,20 +92,24 @@ public class RccServerConfigModel {
)); ));
} }
public static class CustomNameConfig { public static class TextFormats {
public LinkedHashMap<String, String> formats = new LinkedHashMap<>(Map.of( public record NameFormat(String group, String format) {
"admin", "<red><username></red>",
"default", "<green><username></green>"
));
} }
public static class CustomChatFormat { public boolean enableChatMarkdown = true;
public boolean enableMarkdown = true;
public String chatFormat = "<display_name><gray>:</gray> <message>"; public ArrayList<NameFormat> nameFormats = new ArrayList<>(List.of(
public String emoteFormat = "<gray>\uD83D\uDC64 <display_name> <i><message></i></gray>"; new NameFormat("admin", "<red>%player:name%</red>"),
public String joinFormat = "<green>+</green> <display_name> <yellow>joined!</yellow>"; new NameFormat("default", "<green>%player:name%</green>")
public String joinRenamedFormat = "<green>+</green> <display_name> <yellow>joined! <i>(Previously known as <previous_name>)</i></yellow>"; ));
public String leaveFormat = "<red>-</red> <display_name> <yellow>left!</yellow>";
public String deathFormat = "<gray>\u2620 <death_message></gray>"; public String chatFormat = "${player}<gray>:</gray> ${message}";
public String emoteFormat = "<gray>\uD83D\uDC64 ${player} <i>${message}</i></gray>";
public String joinFormat = "<green>+</green> ${player} <yellow>joined!</yellow>";
public String joinRenamedFormat = "<green>+</green> ${player} <yellow>joined! <i>(Previously known as ${previousName})</i></yellow>";
public String leaveFormat = "<red>-</red> ${player} <yellow>left!</yellow>";
public String deathFormat = "<gray>\u2620 ${message}</gray>";
} }
} }

View file

@ -0,0 +1,47 @@
package cc.reconnected.server.config;
import cc.reconnected.server.RccServer;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.fabricmc.loader.api.FabricLoader;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
public class ConfigManager {
private static final Gson gson = new GsonBuilder()
.disableHtmlEscaping()
.setPrettyPrinting()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
.create();
private static final Path configFilePath = FabricLoader.getInstance().getConfigDir().resolve(RccServer.MOD_ID + ".json");
private static Config config = null;
public static Config load() {
if (!configFilePath.toFile().exists()) {
config = new Config();
save();
return config;
}
try (var bf = new BufferedReader(new FileReader(configFilePath.toFile(), StandardCharsets.UTF_8))) {
config = gson.fromJson(bf, Config.class);
save();
} catch (Exception e) {
RccServer.LOGGER.error("Error loading the RccServer config file.", e);
}
return config;
}
public static void save() {
var json = gson.toJson(config);
try (var fw = new FileWriter(configFilePath.toFile(), StandardCharsets.UTF_8)) {
fw.write(json);
} catch (Exception e) {
RccServer.LOGGER.error("Error saving the RccServer config file.", e);
}
}
}

View file

@ -25,7 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class AfkTracker { public class AfkTracker {
private static final int cycleDelay = 1; private static final int cycleDelay = 1;
private static final int absentTimeTrigger = RccServer.CONFIG.afk.afkTimeTrigger() * 20; // seconds * 20 ticks private static final int absentTimeTrigger = RccServer.CONFIG.afk.afkTimeTrigger * 20; // seconds * 20 ticks
private final ConcurrentHashMap<UUID, PlayerActivityState> playerActivityStates = new ConcurrentHashMap<>(); private final ConcurrentHashMap<UUID, PlayerActivityState> playerActivityStates = new ConcurrentHashMap<>();
@ -57,7 +57,7 @@ public class AfkTracker {
var displayNameJson = Text.Serializer.toJson(player.getDisplayName()); var displayNameJson = Text.Serializer.toJson(player.getDisplayName());
var displayName = JSONComponentSerializer.json().deserialize(displayNameJson); var displayName = JSONComponentSerializer.json().deserialize(displayNameJson);
var message = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkMessage(), var message = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkMessage,
Placeholder.component("displayname", displayName), Placeholder.component("displayname", displayName),
Placeholder.unparsed("username", player.getGameProfile().getName()), Placeholder.unparsed("username", player.getGameProfile().getName()),
Placeholder.unparsed("uuid", player.getUuid().toString()) Placeholder.unparsed("uuid", player.getUuid().toString())
@ -72,7 +72,7 @@ public class AfkTracker {
var displayNameJson = Text.Serializer.toJson(player.getDisplayName()); var displayNameJson = Text.Serializer.toJson(player.getDisplayName());
var displayName = JSONComponentSerializer.json().deserialize(displayNameJson); var displayName = JSONComponentSerializer.json().deserialize(displayNameJson);
var message = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkReturnMessage(), var message = MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkReturnMessage,
Placeholder.component("displayname", displayName), Placeholder.component("displayname", displayName),
Placeholder.unparsed("username", player.getGameProfile().getName()), Placeholder.unparsed("username", player.getGameProfile().getName()),
Placeholder.unparsed("uuid", player.getUuid().toString()) Placeholder.unparsed("uuid", player.getUuid().toString())
@ -85,7 +85,7 @@ public class AfkTracker {
} }
private static void loadAfkTag() { private static void loadAfkTag() {
afkTag = Components.toText(MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkTag())); afkTag = Components.toText(MiniMessage.miniMessage().deserialize(RccServer.CONFIG.afk.afkTag));
} }
private AfkTracker() { private AfkTracker() {

View file

@ -33,7 +33,7 @@ public class AutoRestart {
var miniMessage = MiniMessage.miniMessage(); var miniMessage = MiniMessage.miniMessage();
RccEvents.READY.register((server, luckPerms) -> { RccEvents.READY.register((server, luckPerms) -> {
if (RccServer.CONFIG.autoRestart.enableAutoRestart()) { if (RccServer.CONFIG.autoRestart.enableAutoRestart) {
scheduleNextRestart(); scheduleNextRestart();
} }
}); });
@ -42,7 +42,7 @@ public class AutoRestart {
if (restartBar == null || !timeBar.getUuid().equals(restartBar.getUuid())) if (restartBar == null || !timeBar.getUuid().equals(restartBar.getUuid()))
return; return;
var notificationTimes = RccServer.CONFIG.autoRestart.restartNotifications(); var notificationTimes = RccServer.CONFIG.autoRestart.restartNotifications;
var remainingSeconds = restartBar.getRemainingSeconds(); var remainingSeconds = restartBar.getRemainingSeconds();
if (notificationTimes.contains(remainingSeconds)) { if (notificationTimes.contains(remainingSeconds)) {
@ -57,7 +57,7 @@ public class AutoRestart {
return; return;
final var text = Components.toText( final var text = Components.toText(
miniMessage.deserialize(RccServer.CONFIG.autoRestart.restartKickMessage()) miniMessage.deserialize(RccServer.CONFIG.autoRestart.restartKickMessage)
); );
server.getPlayerManager().getPlayerList().forEach(player -> { server.getPlayerManager().getPlayerList().forEach(player -> {
player.networkHandler.disconnect(text); player.networkHandler.disconnect(text);
@ -74,7 +74,7 @@ public class AutoRestart {
} }
private static void setup() { private static void setup() {
var soundName = RccServer.CONFIG.autoRestart.restartSound(); var soundName = RccServer.CONFIG.autoRestart.restartSound;
try { try {
notificationKey = Key.key(soundName); notificationKey = Key.key(soundName);
} catch (InvalidKeyException e) { } catch (InvalidKeyException e) {
@ -115,10 +115,10 @@ public class AutoRestart {
private static void notifyRestart(MinecraftServer server, BossBarManager.TimeBar bar) { private static void notifyRestart(MinecraftServer server, BossBarManager.TimeBar bar) {
var rcc = RccServer.getInstance(); var rcc = RccServer.getInstance();
var audience = rcc.adventure().players(); var audience = rcc.adventure().players();
var sound = Sound.sound(notificationKey, Sound.Source.MASTER, 10f, RccServer.CONFIG.autoRestart.restartSoundPitch()); var sound = Sound.sound(notificationKey, Sound.Source.MASTER, 10f, RccServer.CONFIG.autoRestart.restartSoundPitch);
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.broadcastMessage(server, comp);
} }
@ -133,7 +133,7 @@ public class AutoRestart {
var barStartTime = delay - barTime; var barStartTime = delay - barTime;
currentSchedule = scheduler.schedule(() -> { currentSchedule = scheduler.schedule(() -> {
schedule(barTime, RccServer.CONFIG.autoRestart.restartBarLabel()); schedule(barTime, RccServer.CONFIG.autoRestart.restartBarLabel);
}, barStartTime, TimeUnit.SECONDS); }, barStartTime, TimeUnit.SECONDS);
RccServer.LOGGER.info("Restart scheduled for in {} seconds", delay); RccServer.LOGGER.info("Restart scheduled for in {} seconds", delay);
@ -142,7 +142,7 @@ public class AutoRestart {
@Nullable @Nullable
private static Long getNextDelay() { private static Long getNextDelay() {
var restartTimeStrings = RccServer.CONFIG.autoRestart.restartAt(); var restartTimeStrings = RccServer.CONFIG.autoRestart.restartAt;
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
LocalDateTime nextRunTime = null; LocalDateTime nextRunTime = null;
long shortestDelay = Long.MAX_VALUE; long shortestDelay = Long.MAX_VALUE;

View file

@ -1,12 +1,10 @@
package cc.reconnected.server.core; package cc.reconnected.server.core;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
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.Placeholders;
import eu.pb4.placeholders.api.TextParserUtils;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import net.luckperms.api.model.group.Group; import net.luckperms.api.model.group.Group;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.MutableText; import net.minecraft.text.MutableText;
@ -14,7 +12,7 @@ import net.minecraft.text.MutableText;
public class CustomNameFormat { public class CustomNameFormat {
private static final MiniMessage miniMessage = MiniMessage.miniMessage(); private static final MiniMessage miniMessage = MiniMessage.miniMessage();
public static MutableText getNameForPlayer(ServerPlayerEntity player) { public static MutableText getNameForPlayer(ServerPlayerEntity player) {
var formats = RccServer.CONFIG.customName.formats().entrySet(); var formats = RccServer.CONFIG.textFormats.nameFormats;
var lp = RccServer.getInstance().luckPerms(); var lp = RccServer.getInstance().luckPerms();
var playerContext = PlaceholderContext.of(player); var playerContext = PlaceholderContext.of(player);
@ -23,21 +21,18 @@ public class CustomNameFormat {
var groups = user.getInheritedGroups(user.getQueryOptions()).stream().map(Group::getName).toList(); var groups = user.getInheritedGroups(user.getQueryOptions()).stream().map(Group::getName).toList();
String format = null; String format = null;
for (var entry : formats) { for (var f : formats) {
if (groups.contains(entry.getKey())) { if (groups.contains(f.group())) {
format = entry.getValue(); format = f.format();
break; break;
} }
} }
if (format == null) { if (format == null) {
format = "<username>"; format = "%player:name%";
} }
var displayName = miniMessage.deserialize(format, TagResolver.resolver( var output = TextParserUtils.formatText(format);
Placeholder.parsed("username", player.getGameProfile().getName()) return Placeholders.parseText(output, playerContext).copy();
));
return Placeholders.parseText(Components.toText(displayName), playerContext).copy();
} }
} }

View file

@ -23,7 +23,7 @@ public class HttpApiServer {
private static int currentPlayerCount = 0; private static int currentPlayerCount = 0;
public static void register() { public static void register() {
if (!RccServer.CONFIG.httpApi.enableHttpApi()) if (!RccServer.CONFIG.httpApi.enableHttpApi)
return; return;
try { try {
@ -62,7 +62,7 @@ public class HttpApiServer {
} }
private HttpApiServer() throws IOException { private HttpApiServer() throws IOException {
server = HttpServer.create(new InetSocketAddress(RccServer.CONFIG.httpApi.httpPort()), 0); server = HttpServer.create(new InetSocketAddress(RccServer.CONFIG.httpApi.httpPort), 0);
server.createContext("/tps", new TPSHandler()); server.createContext("/tps", new TPSHandler());
server.createContext("/mspt", new MSPTHandler()); server.createContext("/mspt", new MSPTHandler());
server.createContext("/player", new PlayerCountHandler()); server.createContext("/player", new PlayerCountHandler());

View file

@ -10,23 +10,23 @@ import net.kyori.adventure.text.minimessage.MiniMessage;
public class TabList { public class TabList {
public static void register() { public static void register() {
if (!RccServer.CONFIG.customTabList.enableTabList()) if (!RccServer.CONFIG.customTabList.enableTabList)
return; return;
var minimessage = MiniMessage.miniMessage(); var minimessage = MiniMessage.miniMessage();
ServerTickEvents.END_SERVER_TICK.register(server -> { ServerTickEvents.END_SERVER_TICK.register(server -> {
var delay = Math.max(RccServer.CONFIG.customTabList.tabListTickDelay(), 1); var delay = Math.max(RccServer.CONFIG.customTabList.tabListTickDelay, 1);
if(server.getTicks() % delay == 0) { if(server.getTicks() % delay == 0) {
var period = Math.max(RccServer.CONFIG.customTabList.tabPhasePeriod(), 1); var period = Math.max(RccServer.CONFIG.customTabList.tabPhasePeriod, 1);
var phase = (Math.sin((server.getTicks() * Math.PI * 2) / period) + 1) / 2d; var phase = (Math.sin((server.getTicks() * Math.PI * 2) / period) + 1) / 2d;
server.getPlayerManager().getPlayerList().forEach(player -> { server.getPlayerManager().getPlayerList().forEach(player -> {
var playerContext = PlaceholderContext.of(player); var playerContext = PlaceholderContext.of(player);
Component headerComponent = Component.empty(); Component headerComponent = Component.empty();
for (int i = 0; i < RccServer.CONFIG.customTabList.tabHeader().size(); i++) { for (int i = 0; i < RccServer.CONFIG.customTabList.tabHeader.size(); i++) {
var line = RccServer.CONFIG.customTabList.tabHeader().get(i); var line = RccServer.CONFIG.customTabList.tabHeader.get(i);
line = line.replace("{phase}", String.valueOf(phase)); line = line.replace("{phase}", String.valueOf(phase));
if (i > 0) { if (i > 0) {
headerComponent = headerComponent.appendNewline(); headerComponent = headerComponent.appendNewline();
@ -36,8 +36,8 @@ public class TabList {
} }
Component footerComponent = Component.empty(); Component footerComponent = Component.empty();
for (int i = 0; i < RccServer.CONFIG.customTabList.tabFooter().size(); i++) { for (int i = 0; i < RccServer.CONFIG.customTabList.tabFooter.size(); i++) {
var line = RccServer.CONFIG.customTabList.tabFooter().get(i); var line = RccServer.CONFIG.customTabList.tabFooter.get(i);
line = line.replace("{phase}", String.valueOf(phase)); line = line.replace("{phase}", String.valueOf(phase));
if (i > 0) { if (i > 0) {
footerComponent = footerComponent.appendNewline(); footerComponent = footerComponent.appendNewline();

View file

@ -37,7 +37,7 @@ public class TeleportTracker {
this.player = player; this.player = player;
this.target = target; this.target = target;
// Seconds in config per 20 ticks // Seconds in config per 20 ticks
this.remainingTicks = RccServer.CONFIG.teleportRequests.teleportRequestTimeout() * 20; this.remainingTicks = RccServer.CONFIG.teleportRequests.teleportRequestTimeout * 20;
} }
public void expire() { public void expire() {

View file

@ -3,6 +3,10 @@ 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.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.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.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
@ -12,6 +16,8 @@ import net.minecraft.registry.RegistryKeys;
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;
public class CustomChatMessage { public class CustomChatMessage {
private static final MiniMessage miniMessage = MiniMessage.miniMessage(); private static final MiniMessage miniMessage = MiniMessage.miniMessage();
@ -19,19 +25,16 @@ public class CustomChatMessage {
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; Text messageText = Utils.formatChatMessage(message, player);
if (RccServer.CONFIG.customChatFormat.enableMarkdown()) {
messageText = MarkdownParser.defaultParser.parseNode(message.getSignedContent()).toText();
} else {
messageText = message.getContent();
}
var component = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.chatFormat(), TagResolver.resolver( var placeholders = Map.of(
Placeholder.component("display_name", player.getDisplayName()), "message", messageText,
Placeholder.component("message", messageText) "player", player.getDisplayName()
)); );
var text = Components.toText(component);
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);

View file

@ -2,40 +2,46 @@ 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.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.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 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;
public class CustomConnectionMessage { public class CustomConnectionMessage {
private static final MiniMessage miniMessage = MiniMessage.miniMessage(); private static final MiniMessage miniMessage = MiniMessage.miniMessage();
public static Text onJoin(ServerPlayerEntity player) { public static Text onJoin(ServerPlayerEntity player) {
var joinMessage = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.joinFormat(), var placeholders = Map.of(
TagResolver.resolver( "player", player.getDisplayName()
Placeholder.component("display_name", player.getDisplayName()) );
));
return Components.toText(joinMessage); 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 joinMessage = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.joinRenamedFormat(), var placeholders = Map.of(
TagResolver.resolver( "previousName", Text.of(previousName),
Placeholder.component("display_name", player.getDisplayName()), "player", player.getDisplayName()
Placeholder.component("previous_name", Text.of(previousName)) );
));
return Components.toText(joinMessage); 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 leaveMessage = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.leaveFormat(), var placeholders = Map.of(
TagResolver.resolver( "player", player.getDisplayName()
Placeholder.component("display_name", player.getDisplayName()) );
));
return Components.toText(leaveMessage); var format = TextParserUtils.formatText(RccServer.CONFIG.textFormats.leaveFormat);
return Placeholders.parseText(format, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders);
} }
} }

View file

@ -2,6 +2,11 @@ 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.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.MiniMessage;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
@ -9,16 +14,20 @@ 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;
import java.util.Map;
public class CustomDeathMessage { public class CustomDeathMessage {
private static final MiniMessage miniMessage = MiniMessage.miniMessage(); 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 deathComponent = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.deathFormat(),
TagResolver.resolver(
Placeholder.component("death_message", deathMessage)
));
return Components.toText(deathComponent); var placeholders = Map.of(
"message", deathMessage,
"player", player.getDisplayName()
);
var format = TextParserUtils.formatText(RccServer.CONFIG.textFormats.deathFormat);
return Placeholders.parseText(format, PatternPlaceholderParser.PREDEFINED_PLACEHOLDER_PATTERN, placeholders);
} }
} }

View file

@ -1,17 +1,18 @@
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 eu.pb4.placeholders.api.Placeholders;
import cc.reconnected.server.util.Components; import eu.pb4.placeholders.api.TextParserUtils;
import eu.pb4.placeholders.api.parsers.PatternPlaceholderParser;
import net.kyori.adventure.text.minimessage.MiniMessage; 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;
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;
public class CustomEmoteMessage { public class CustomEmoteMessage {
private static final MiniMessage miniMessage = MiniMessage.miniMessage(); private static final MiniMessage miniMessage = MiniMessage.miniMessage();
@ -19,19 +20,15 @@ public class CustomEmoteMessage {
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; Text messageText = Utils.formatChatMessage(message, player);
if (RccServer.CONFIG.customChatFormat.enableMarkdown()) {
messageText = MarkdownParser.defaultParser.parseNode(message.getSignedContent()).toText();
} else {
messageText = message.getContent();
}
var component = miniMessage.deserialize(RccServer.CONFIG.customChatFormat.emoteFormat(), TagResolver.resolver( var placeholders = Map.of(
Placeholder.component("display_name", player.getDisplayName()), "message", messageText,
Placeholder.component("message", messageText) "player", player.getDisplayName()
)); );
var text = Components.toText(component); 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

@ -0,0 +1,32 @@
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

@ -2,13 +2,11 @@ package cc.reconnected.server.mixin;
import cc.reconnected.server.RccServer; import cc.reconnected.server.RccServer;
import cc.reconnected.server.core.customChat.CustomConnectionMessage; import cc.reconnected.server.core.customChat.CustomConnectionMessage;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayNetworkHandler;
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.text.TranslatableTextContent;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -30,7 +28,7 @@ public abstract class ServerPlayNetworkManagerMixin {
@Inject(method = "tick", at = @At("TAIL")) @Inject(method = "tick", at = @At("TAIL"))
private void rccServer$updatePlayerList(CallbackInfo ci) { private void rccServer$updatePlayerList(CallbackInfo ci) {
if(RccServer.CONFIG.customTabList.enableTabList()) { if(RccServer.CONFIG.customTabList.enableTabList) {
var packet = new PlayerListS2CPacket(EnumSet.of(PlayerListS2CPacket.Action.UPDATE_DISPLAY_NAME, PlayerListS2CPacket.Action.UPDATE_LISTED), List.of(this.player)); var packet = new PlayerListS2CPacket(EnumSet.of(PlayerListS2CPacket.Action.UPDATE_DISPLAY_NAME, PlayerListS2CPacket.Action.UPDATE_LISTED), List.of(this.player));
this.server.getPlayerManager().sendToAll(packet); this.server.getPlayerManager().sendToAll(packet);
} }

View file

@ -23,10 +23,10 @@ public class ServerPlayerEntityMixin {
@Inject(method = "getPlayerListName", at = @At("HEAD"), cancellable = true) @Inject(method = "getPlayerListName", at = @At("HEAD"), cancellable = true)
private void rccServer$customizePlayerListName(CallbackInfoReturnable<Text> callback) { private void rccServer$customizePlayerListName(CallbackInfoReturnable<Text> callback) {
if (RccServer.CONFIG.customTabList.enableTabList()) { if (RccServer.CONFIG.customTabList.enableTabList) {
var player = (ServerPlayerEntity) (Object) this; var player = (ServerPlayerEntity) (Object) this;
var playerContext = PlaceholderContext.of(player); var playerContext = PlaceholderContext.of(player);
var text = Placeholders.parseText(parser.parseNode(RccServer.CONFIG.customTabList.playerTabName()), playerContext); var text = Placeholders.parseText(parser.parseNode(RccServer.CONFIG.customTabList.playerTabName), playerContext);
callback.setReturnValue(text); callback.setReturnValue(text);
} }
} }

View file

@ -1,10 +1,8 @@
package cc.reconnected.server.parser; package cc.reconnected.server.parser;
import eu.pb4.placeholders.api.node.TextNode; import eu.pb4.placeholders.api.node.TextNode;
import eu.pb4.placeholders.api.node.parent.ClickActionNode; import eu.pb4.placeholders.api.node.parent.*;
import eu.pb4.placeholders.api.node.parent.FormattingNode; import net.minecraft.text.*;
import eu.pb4.placeholders.api.node.parent.HoverNode;
import net.minecraft.text.ClickEvent;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
public class MarkdownComponentParser { public class MarkdownComponentParser {
@ -32,7 +30,11 @@ public class MarkdownComponentParser {
return new HoverNode<>(TextNode.array( return new HoverNode<>(TextNode.array(
new ClickActionNode( new ClickActionNode(
TextNode.array( TextNode.array(
new FormattingNode(textNodes, Formatting.BLUE, Formatting.UNDERLINE)), new StyledNode(textNodes,
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.of("Click to open: " + url.toText().getString())
); );