diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 23809584..db56482f 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -265,7 +265,7 @@ Example usages: // not a problem in apps -### `display_title(players, type, title?, fadeInTicks?, stayTicks?, fadeOutTicks),` +### `display_title(players, type, text?, fadeInTicks?, stayTicks?, fadeOutTicks),` Sends the player (or players if `players` is a list) a title of a specific type, with optionally some times. * `players` is either an online player or a list of players. When sending a single player, it will throw if the player is invalid or offline. @@ -277,13 +277,12 @@ Sends the player (or players if `players` is a list) a title of a specific type, Executing with those will set the times to the specified ones. Note that `actionbar` type doesn't support changing times (vanilla bug, see [MC-106167](https://bugs.mojang.com/browse/MC-106167)). -### `display_title(players, 'player_list')` -### `display_title(players, 'player_list', footer)` -### `display_title(players, 'player_list', header, footer)` +### `display_title(players, 'player_list_header', text)` +### `display_title(players, 'player_list_footer', text)` -Changes the header and footer of the player list. -When no `header` and `footer` is specified, they will be reset. -Keep in mind this would interfere with carpet's loggers, so if you are using this, you need to keep them off. +Changes the header or footer of the player list for the specified targets. +If `text` is `null` or an empty string it will remove the header or footer for the specified targets. +In case the player has Carpet loggers running, the footer specified by Scarpet will appear above the loggers. ### `logger(msg), logger(type, msg)` diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index 862ed86d..ae9e4dce 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -112,7 +112,7 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit public static void tick(MinecraftServer server) { TickSpeed.tick(); - HUDController.update_hud(server); + HUDController.update_hud(server, null); scriptServer.tick(); //in case something happens @@ -180,6 +180,7 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit currentCommandDispatcher = null; LoggerRegistry.stopLoggers(); + HUDController.resetScarpetHUDs(); extensions.forEach(e -> e.onServerClosed(server)); minecraft_server = null; } diff --git a/src/main/java/carpet/logging/HUDController.java b/src/main/java/carpet/logging/HUDController.java index 6066d2a6..76963fab 100644 --- a/src/main/java/carpet/logging/HUDController.java +++ b/src/main/java/carpet/logging/HUDController.java @@ -21,10 +21,13 @@ import net.minecraft.world.World; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.function.Consumer; public class HUDController @@ -40,9 +43,18 @@ public class HUDController HUDListeners.add(listener); } - public static Map> player_huds = new HashMap<>(); + public static Map> player_huds = new HashMap<>(); - public static void addMessage(PlayerEntity player, BaseText hudMessage) + public static final Map scarpet_headers = new HashMap<>(); + + public static final Map scarpet_footers = new HashMap<>(); + + public static void resetScarpetHUDs() { + scarpet_headers.clear(); + scarpet_footers.clear(); + } + + public static void addMessage(ServerPlayerEntity player, BaseText hudMessage) { if (!player_huds.containsKey(player)) { @@ -64,13 +76,15 @@ public class HUDController } - public static void update_hud(MinecraftServer server) + public static void update_hud(MinecraftServer server, List force) { - if(server.getTicks() % 20 != 0 || CarpetServer.minecraft_server == null) + if (((server.getTicks() % 20 != 0) && force == null) || CarpetServer.minecraft_server == null) return; player_huds.clear(); + scarpet_footers.forEach(HUDController::addMessage); + if (LoggerRegistry.__tps) LoggerRegistry.getLogger("tps").log(()-> send_tps_display(server)); @@ -101,7 +115,9 @@ public class HUDController // extensions have time to pitch in. HUDListeners.forEach(l -> l.accept(server)); - for (PlayerEntity player: player_huds.keySet()) + Set targets = new HashSet<>(player_huds.keySet()); + if (force!= null) targets.addAll(force); + for (ServerPlayerEntity player: targets) { PacketByteBuf packetData = new PacketByteBuf(Unpooled.buffer()). writeText(new LiteralText("")). @@ -109,9 +125,9 @@ public class HUDController PlayerListHeaderS2CPacket packet = new PlayerListHeaderS2CPacket(packetData); //PlayerListHeaderS2CPacket packet = new PlayerListHeaderS2CPacket(); - //((PlayerListHeaderS2CPacketMixin)packet).setHeader(new LiteralText("")); - //((PlayerListHeaderS2CPacketMixin)packet).setFooter(Messenger.c(player_huds.get(player).toArray(new Object[0]))); - ((ServerPlayerEntity)player).networkHandler.sendPacket(packet); + //((PlayerListHeaderS2CPacketMixin)packet).setHeader(scarpet_headers.getOrDefault(player, new LiteralText(""))); + //((PlayerListHeaderS2CPacketMixin)packet).setFooter(Messenger.c(player_huds.getOrDefault(player, Collections.emptyList()).toArray(new Object[0]))); + player.networkHandler.sendPacket(packet); } } private static BaseText [] send_tps_display(MinecraftServer server) diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 107e497a..5ce1eb80 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -7,6 +7,7 @@ import carpet.fakes.ServerWorldInterface; import carpet.fakes.StatTypeInterface; import carpet.fakes.ThreadedAnvilChunkStorageInterface; import carpet.helpers.FeatureGenerator; +import carpet.logging.HUDController; import carpet.script.argument.FileArgument; import carpet.script.CarpetContext; import carpet.script.CarpetEventServer; @@ -79,6 +80,7 @@ import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; import net.minecraft.stat.Stat; import net.minecraft.stat.StatType; +import net.minecraft.text.BaseText; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -580,56 +582,55 @@ public class Auxiliary { packetGetter = (x) -> new ClearTitleS2CPacket(true); // resetting default fade //action = Action.CLEAR; break; - case "player_list": - Text footer; - Text header; - - if(lv.size() == 2) { - footer = new LiteralText(""); - header = new LiteralText(""); - } else if(lv.size() == 3) { - pVal = lv.get(2).evalValue(c); - if (pVal instanceof FormattedTextValue) - footer = ((FormattedTextValue) pVal).getText(); - else - footer = new LiteralText(pVal.getString()); - - header = new LiteralText(""); - } else { - pVal = lv.get(2).evalValue(c); - if (pVal instanceof FormattedTextValue) - header = ((FormattedTextValue) pVal).getText(); - else - header = new LiteralText(pVal.getString()); - - pVal = lv.get(3).evalValue(c); - if (pVal instanceof FormattedTextValue) - footer = ((FormattedTextValue) pVal).getText(); - else - footer = new LiteralText(pVal.getString()); - } - - PlayerListHeaderS2CPacket packet = new PlayerListHeaderS2CPacket(header, footer); - AtomicInteger total = new AtomicInteger(0); - targets.forEach(p -> { - p.networkHandler.sendPacket(packet); - total.getAndIncrement(); - }); - Value ret = NumericValue.of(total.get()); - return (cc, tt) -> ret; + case "player_list_header": + case "player_list_footer": + action = null; + break; default: - throw new InternalExpressionException("'display_title' requires 'title', 'subtitle', 'actionbar', 'player_list' or 'clear' as second argument"); + throw new InternalExpressionException("'display_title' requires 'title', 'subtitle', 'actionbar', 'player_list_header', 'player_list_footer' or 'clear' as second argument"); } //if (action != Action.CLEAR && lv.size() < 3) // throw new InternalExpressionException("Third argument of 'display_title' must be present except for 'clear' type"); - Text title = null; + Text title; + boolean soundsTrue = false; if (lv.size() > 2) { pVal = lv.get(2).evalValue(c); if (pVal instanceof FormattedTextValue) + { title = ((FormattedTextValue) pVal).getText(); + soundsTrue = !title.asString().isEmpty(); + } else + { title = new LiteralText(pVal.getString()); + soundsTrue = pVal.getBoolean(); + } + } + else title = null; // Will never happen, just to make lambda happy + if (action == null) + { + Map map; + if (actionString.equals("player_list_header")) + map = HUDController.scarpet_headers; + else + map = HUDController.scarpet_footers; + + AtomicInteger total = new AtomicInteger(0); + List targetList = targets.collect(Collectors.toList()); + if (!soundsTrue) // null or empty string + targetList.forEach(target -> { + map.remove(target); + total.getAndIncrement(); + }); + else + targetList.forEach(target -> { + map.put(target, (BaseText) title); + total.getAndIncrement(); + }); + HUDController.update_hud(((CarpetContext)c).s.getMinecraftServer(), targetList); + Value ret = NumericValue.of(total.get()); + return (cc, tt) -> ret; } TitleFadeS2CPacket timesPacket; // TimesPacket if (lv.size() > 3)