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..846f4773 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, false); 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 a8332203..fa0882d9 100644 --- a/src/main/java/carpet/logging/HUDController.java +++ b/src/main/java/carpet/logging/HUDController.java @@ -39,6 +39,15 @@ public class HUDController } public static Map> player_huds = new HashMap<>(); + + 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(PlayerEntity player, BaseText hudMessage) { @@ -61,13 +70,15 @@ public class HUDController } - public static void update_hud(MinecraftServer server) + public static void update_hud(MinecraftServer server, boolean force) { - if(server.getTicks() % 20 != 0 || CarpetServer.minecraft_server == null) + if ((server.getTicks() % 20 != 0 && !force) || CarpetServer.minecraft_server == null) return; player_huds.clear(); + scarpet_footers.forEach((p, m) -> addMessage(p, m)); + if (LoggerRegistry.__tps) LoggerRegistry.getLogger("tps").log(()-> send_tps_display(server)); @@ -101,7 +112,7 @@ public class HUDController for (PlayerEntity player: player_huds.keySet()) { PlayerListHeaderS2CPacket packet = new PlayerListHeaderS2CPacket(); - ((PlayerListHeaderS2CPacketMixin)packet).setHeader(new LiteralText("")); + ((PlayerListHeaderS2CPacketMixin)packet).setHeader(scarpet_headers.getOrDefault(player, new LiteralText(""))); ((PlayerListHeaderS2CPacketMixin)packet).setFooter(Messenger.c(player_huds.get(player).toArray(new Object[0]))); ((ServerPlayerEntity)player).networkHandler.sendPacket(packet); } diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index d2b24952..c2d96cc0 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -7,8 +7,7 @@ import carpet.fakes.ServerWorldInterface; import carpet.fakes.StatTypeInterface; import carpet.fakes.ThreadedAnvilChunkStorageInterface; import carpet.helpers.FeatureGenerator; -import carpet.mixins.PlayerListHeaderS2CPacketMixin; -import carpet.script.bundled.Module; +import carpet.logging.HUDController; import carpet.script.argument.FileArgument; import carpet.script.CarpetContext; import carpet.script.CarpetEventServer; @@ -59,7 +58,6 @@ import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import net.minecraft.network.packet.s2c.play.PlaySoundIdS2CPacket; -import net.minecraft.network.packet.s2c.play.PlayerListHeaderS2CPacket; import net.minecraft.network.packet.s2c.play.TitleS2CPacket; import net.minecraft.network.packet.s2c.play.TitleS2CPacket.Action; import net.minecraft.particle.ParticleEffect; @@ -75,6 +73,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; @@ -562,51 +561,16 @@ public class Auxiliary { case "clear": 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(); - ((PlayerListHeaderS2CPacketMixin) packet).setFooter(footer); - ((PlayerListHeaderS2CPacketMixin) packet).setHeader(header); - 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; if (lv.size() > 2) { pVal = lv.get(2).evalValue(c); @@ -615,6 +579,30 @@ public class Auxiliary { else title = new LiteralText(pVal.getString()); } + 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); + if (!lv.get(2).evalValue(c).getBoolean()) // null or empty string + targets.forEach(target -> { + map.remove(target); + total.getAndIncrement(); + }); + else + targets.forEach(target -> { + map.put(target, (BaseText) title); + total.getAndIncrement(); + }); + HUDController.update_hud(((CarpetContext)c).s.getMinecraftServer(), true); + Value ret = NumericValue.of(total.get()); + return (cc, tt) -> ret; + } TitleS2CPacket timesPacket; if (lv.size() > 3) {