From 9532ff01ee287595b5445fca1d702e1468aebc40 Mon Sep 17 00:00:00 2001 From: William Blake Galbreath Date: Sun, 12 Jan 2025 13:35:04 -0800 Subject: [PATCH] Signs allow color codes --- .../server/0214-Signs-allow-color-codes.patch | 101 ------------------ .../util/permissions/PurpurPermissions.java | 7 ++ .../server/level/ServerPlayer.java.patch | 8 ++ .../block/entity/SignBlockEntity.java.patch | 66 ++++++++++++ .../purpurmc/purpur/PurpurWorldConfig.java | 5 + 5 files changed, 86 insertions(+), 101 deletions(-) delete mode 100644 patches/server/0214-Signs-allow-color-codes.patch create mode 100644 purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch diff --git a/patches/server/0214-Signs-allow-color-codes.patch b/patches/server/0214-Signs-allow-color-codes.patch deleted file mode 100644 index 5bbd03d7d..000000000 --- a/patches/server/0214-Signs-allow-color-codes.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 6 Jun 2019 17:40:30 -0500 -Subject: [PATCH] Signs allow color codes - - -diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index ad4ace81452d83cc01ac9de5ef323770a8a2f417..d97db4d05d7940d8408e7e0d473a3b17d956b858 100644 ---- a/net/minecraft/server/level/ServerPlayer.java -+++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1959,6 +1959,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple - - @Override - public void openTextEdit(SignBlockEntity sign, boolean front) { -+ if (level().purpurConfig.signAllowColors) this.connection.send(sign.getTranslatedUpdatePacket(textFilteringEnabled, front)); // Purpur - this.connection.send(new ClientboundBlockUpdatePacket(this.level(), sign.getBlockPos())); - this.connection.send(new ClientboundOpenSignEditorPacket(sign.getBlockPos(), front)); - } -diff --git a/net/minecraft/world/level/block/entity/SignBlockEntity.java b/net/minecraft/world/level/block/entity/SignBlockEntity.java -index 7a1d9a718dc57b5f630ca8e5358120cebaeefb9c..b51b0b0f48b1da6187387d6ec025681e10ed584d 100644 ---- a/net/minecraft/world/level/block/entity/SignBlockEntity.java -+++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java -@@ -201,16 +201,31 @@ public class SignBlockEntity extends BlockEntity { - return this.setText((SignText) textChanger.apply(signtext), front); - } - -+ // Purpur start -+ private Component translateColors(org.bukkit.entity.Player player, String line, Style style) { -+ if (level.purpurConfig.signAllowColors) { -+ if (player.hasPermission("purpur.sign.color")) line = line.replaceAll("(?i)&([0-9a-fr])", "\u00a7$1"); -+ if (player.hasPermission("purpur.sign.style")) line = line.replaceAll("(?i)&([l-or])", "\u00a7$1"); -+ if (player.hasPermission("purpur.sign.magic")) line = line.replaceAll("(?i)&([kr])", "\u00a7$1"); -+ -+ return io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(line)); -+ } else { -+ return Component.literal(line).setStyle(style); -+ } -+ } -+ // Purpur end -+ - private SignText setMessages(net.minecraft.world.entity.player.Player entityhuman, List list, SignText signtext, boolean front) { // CraftBukkit - SignText originalText = signtext; // CraftBukkit - for (int i = 0; i < list.size(); ++i) { - FilteredText filteredtext = (FilteredText) list.get(i); - Style chatmodifier = signtext.getMessage(i, entityhuman.isTextFilteringEnabled()).getStyle(); - -+ org.bukkit.entity.Player player = (org.bukkit.craftbukkit.entity.CraftPlayer) entityhuman.getBukkitEntity(); // Purpur - if (entityhuman.isTextFilteringEnabled()) { -- signtext = signtext.setMessage(i, Component.literal(net.minecraft.util.StringUtil.filterText(filteredtext.filteredOrEmpty())).setStyle(chatmodifier)); // Paper - filter sign text to chat only -+ signtext = signtext.setMessage(i, translateColors(player, net.minecraft.util.StringUtil.filterText(filteredtext.filteredOrEmpty()), chatmodifier)); // Paper - filter sign text to chat only // Purpur - } else { -- signtext = signtext.setMessage(i, Component.literal(net.minecraft.util.StringUtil.filterText(filteredtext.raw())).setStyle(chatmodifier), Component.literal(net.minecraft.util.StringUtil.filterText(filteredtext.filteredOrEmpty())).setStyle(chatmodifier)); // Paper - filter sign text to chat only -+ signtext = signtext.setMessage(i, translateColors(player, net.minecraft.util.StringUtil.filterText(filteredtext.raw()), chatmodifier), translateColors(player, net.minecraft.util.StringUtil.filterText(filteredtext.filteredOrEmpty()), chatmodifier)); // Paper - filter sign text to chat only // Purpur - } - } - -@@ -348,6 +363,28 @@ public class SignBlockEntity extends BlockEntity { - return new CommandSourceStack(commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel) world, 2, s, (Component) object, world.getServer(), player); // Paper - Fix commands from signs not firing command events - } - -+ // Purpur start -+ public ClientboundBlockEntityDataPacket getTranslatedUpdatePacket(boolean filtered, boolean front) { -+ final CompoundTag nbt = new CompoundTag(); -+ this.saveAdditional(nbt, this.getLevel().registryAccess()); -+ final Component[] lines = front ? frontText.getMessages(filtered) : backText.getMessages(filtered); -+ final String side = front ? "front_text" : "back_text"; -+ for (int i = 0; i < 4; i++) { -+ final var component = io.papermc.paper.adventure.PaperAdventure.asAdventure(lines[i]); -+ final String line = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacyAmpersand().serialize(component); -+ final var text = net.kyori.adventure.text.Component.text(line); -+ final String json = net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(text); -+ if (!nbt.contains(side)) nbt.put(side, new CompoundTag()); -+ final CompoundTag sideNbt = nbt.getCompound(side); -+ if (!sideNbt.contains("messages")) sideNbt.put("messages", new net.minecraft.nbt.ListTag()); -+ final net.minecraft.nbt.ListTag messagesNbt = sideNbt.getList("messages", Tag.TAG_STRING); -+ messagesNbt.set(i, net.minecraft.nbt.StringTag.valueOf(json)); -+ } -+ nbt.putString("PurpurEditor", "true"); -+ return ClientboundBlockEntityDataPacket.create(this, (blockEntity, registryAccess) -> nbt); -+ } -+ // Purpur end -+ - @Override - public ClientboundBlockEntityDataPacket getUpdatePacket() { - return ClientboundBlockEntityDataPacket.create(this); -diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index c8260dddc2852ad55bdb0091bfccb252a09a4ff3..1f5b541cd87c4e6fafbd1ee9b75d4a323aeacaa1 100644 ---- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -@@ -1009,6 +1009,11 @@ public class PurpurWorldConfig { - } - } - -+ public boolean signAllowColors = false; -+ private void signSettings() { -+ signAllowColors = getBoolean("blocks.sign.allow-colors", signAllowColors); -+ } -+ - public boolean slabHalfBreak = false; - private void slabSettings() { - slabHalfBreak = getBoolean("blocks.slab.break-individual-slabs-when-sneaking", slabHalfBreak); diff --git a/purpur-api/src/main/java/org/purpurmc/purpur/util/permissions/PurpurPermissions.java b/purpur-api/src/main/java/org/purpurmc/purpur/util/permissions/PurpurPermissions.java index 60661eaff..50647252e 100644 --- a/purpur-api/src/main/java/org/purpurmc/purpur/util/permissions/PurpurPermissions.java +++ b/purpur-api/src/main/java/org/purpurmc/purpur/util/permissions/PurpurPermissions.java @@ -56,6 +56,13 @@ public final class PurpurPermissions { DefaultPermissions.registerPermission(PREFIX + "book.color.sign", "Allows the user to use color codes on books when signing", PermissionDefault.FALSE, book); book.recalculatePermissibles(); + Permission sign = DefaultPermissions.registerPermission(PREFIX + "sign", "Allows the user to use all sign abilities", PermissionDefault.FALSE, purpur); + DefaultPermissions.registerPermission(PREFIX + "sign.edit", "Allows the user to click signs to open sign editor", PermissionDefault.TRUE, sign); + DefaultPermissions.registerPermission(PREFIX + "sign.color", "Allows the user to use color codes on signs", PermissionDefault.FALSE, sign); + DefaultPermissions.registerPermission(PREFIX + "sign.style", "Allows the user to use style codes on signs", PermissionDefault.FALSE, sign); + DefaultPermissions.registerPermission(PREFIX + "sign.magic", "Allows the user to use magic/obfuscate code on signs", PermissionDefault.FALSE, sign); + sign.recalculatePermissibles(); + Permission ride = DefaultPermissions.registerPermission("allow.ride", "Allows the user to ride all mobs", PermissionDefault.FALSE, purpur); for (String mob : mobs) { DefaultPermissions.registerPermission("allow.ride." + mob, "Allows the user to ride " + mob, PermissionDefault.FALSE, ride); diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerPlayer.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerPlayer.java.patch index e7a002959..9e005b3b0 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerPlayer.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerPlayer.java.patch @@ -89,6 +89,14 @@ } ((ServerLevel)this.level()).updateSleepingPlayerList(); +@@ -1709,6 +_,7 @@ + + @Override + public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) { ++ if (level().purpurConfig.signAllowColors) this.connection.send(signEntity.getTranslatedUpdatePacket(textFilteringEnabled, isFrontText)); // Purpur - Signs allow color codes + this.connection.send(new ClientboundBlockUpdatePacket(this.level(), signEntity.getBlockPos())); + this.connection.send(new ClientboundOpenSignEditorPacket(signEntity.getBlockPos(), isFrontText)); + } @@ -2014,6 +_,26 @@ this.lastSentExp = -1; // CraftBukkit - Added to reset } diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch new file mode 100644 index 000000000..db6bfc0bf --- /dev/null +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/entity/SignBlockEntity.java.patch @@ -0,0 +1,66 @@ +--- a/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -163,16 +_,32 @@ + return this.setText(updater.apply(text), isFrontText); + } + ++ // Purpur start - Signs allow color codes ++ private Component translateColors(org.bukkit.entity.Player player, String line, Style style) { ++ if (level.purpurConfig.signAllowColors) { ++ if (player.hasPermission("purpur.sign.color")) line = line.replaceAll("(?i)&([0-9a-fr])", "\u00a7$1"); ++ if (player.hasPermission("purpur.sign.style")) line = line.replaceAll("(?i)&([l-or])", "\u00a7$1"); ++ if (player.hasPermission("purpur.sign.magic")) line = line.replaceAll("(?i)&([kr])", "\u00a7$1"); ++ ++ return io.papermc.paper.adventure.PaperAdventure.asVanilla(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(line)); ++ } else { ++ return Component.literal(line).setStyle(style); ++ } ++ } ++ // Purpur end - Signs allow color codes ++ + private SignText setMessages(Player player, List filteredText, SignText text, boolean front) { // CraftBukkit + SignText originalText = text; // CraftBukkit + for (int i = 0; i < filteredText.size(); i++) { + FilteredText filteredText1 = filteredText.get(i); + Style style = text.getMessage(i, player.isTextFilteringEnabled()).getStyle(); ++ ++ org.bukkit.entity.Player craftPlayer = (org.bukkit.craftbukkit.entity.CraftPlayer) player.getBukkitEntity(); // Purpur - Signs allow color codes + if (player.isTextFilteringEnabled()) { +- text = text.setMessage(i, Component.literal(net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty())).setStyle(style)); // Paper - filter sign text to chat only ++ text = text.setMessage(i, translateColors(craftPlayer, net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty()), style)); // Paper - filter sign text to chat only // Purpur - Signs allow color codes + } else { + text = text.setMessage( +- i, Component.literal(filteredText1.raw()).setStyle(style), Component.literal(net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty())).setStyle(style) // Paper - filter sign text to chat only ++ i, translateColors(craftPlayer, net.minecraft.util.StringUtil.filterText(filteredText1.raw()), style), translateColors(craftPlayer, net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty()), style) // Paper - filter sign text to chat only // Purpur - Signs allow color codes + ); + } + } +@@ -310,6 +_,28 @@ + // CraftBukkit - this + return new CommandSourceStack(commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel) world, 2, string, component, world.getServer(), player); // Paper - Fix commands from signs not firing command events + } ++ ++ // Purpur start - Signs allow color codes ++ public ClientboundBlockEntityDataPacket getTranslatedUpdatePacket(boolean filtered, boolean front) { ++ final CompoundTag nbt = new CompoundTag(); ++ this.saveAdditional(nbt, this.getLevel().registryAccess()); ++ final Component[] lines = front ? frontText.getMessages(filtered) : backText.getMessages(filtered); ++ final String side = front ? "front_text" : "back_text"; ++ for (int i = 0; i < 4; i++) { ++ final var component = io.papermc.paper.adventure.PaperAdventure.asAdventure(lines[i]); ++ final String line = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacyAmpersand().serialize(component); ++ final var text = net.kyori.adventure.text.Component.text(line); ++ final String json = net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(text); ++ if (!nbt.contains(side)) nbt.put(side, new CompoundTag()); ++ final CompoundTag sideNbt = nbt.getCompound(side); ++ if (!sideNbt.contains("messages")) sideNbt.put("messages", new net.minecraft.nbt.ListTag()); ++ final net.minecraft.nbt.ListTag messagesNbt = sideNbt.getList("messages", Tag.TAG_STRING); ++ messagesNbt.set(i, net.minecraft.nbt.StringTag.valueOf(json)); ++ } ++ nbt.putString("PurpurEditor", "true"); ++ return ClientboundBlockEntityDataPacket.create(this, (blockEntity, registryAccess) -> nbt); ++ } ++ // Purpur end - Signs allow color codes + + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { diff --git a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java index 88efa2a1f..2cd083485 100644 --- a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -1008,6 +1008,11 @@ public class PurpurWorldConfig { } } + public boolean signAllowColors = false; + private void signSettings() { + signAllowColors = getBoolean("blocks.sign.allow-colors", signAllowColors); + } + public boolean slabHalfBreak = false; private void slabSettings() { slabHalfBreak = getBoolean("blocks.slab.break-individual-slabs-when-sneaking", slabHalfBreak);