diff --git a/patches/server/0069-Allow-color-codes-in-books.patch b/patches/server/0069-Allow-color-codes-in-books.patch deleted file mode 100644 index f3acf2d4b..000000000 --- a/patches/server/0069-Allow-color-codes-in-books.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Tue, 3 Nov 2020 01:25:06 -0600 -Subject: [PATCH] Allow color codes in books - - -diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 830e0705f3a3d45fcf0eab6b8eea403c3023f3f9..0654c2753a44b4cda55fd92513fabc45ff4ab6c9 100644 ---- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -1302,10 +1302,14 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - Objects.requireNonNull(list); - optional.ifPresent(list::add); - list.addAll(packet.pages()); -+ // Purpur start -+ boolean hasEditPerm = getCraftPlayer().hasPermission("purpur.book.color.edit"); -+ boolean hasSignPerm = hasEditPerm || getCraftPlayer().hasPermission("purpur.book.color.sign"); -+ // Purpur end - Consumer> consumer = optional.isPresent() ? (list1) -> { -- this.signBook((FilteredText) list1.get(0), list1.subList(1, list1.size()), i); -+ this.signBook((FilteredText) list1.get(0), list1.subList(1, list1.size()), i, hasSignPerm); // Purpur - } : (list1) -> { -- this.updateBookContents(list1, i); -+ this.updateBookContents(list1, i, hasEditPerm); // Purpur - }; - - this.filterTextPacket((List) list).thenAcceptAsync(consumer, this.server); -@@ -1313,13 +1317,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - - private void updateBookContents(List pages, int slotId) { -+ // Purpur start -+ updateBookContents(pages, slotId, false); -+ } -+ private void updateBookContents(List pages, int slotId, boolean hasPerm) { -+ // Purpur end - // CraftBukkit start - ItemStack handItem = this.player.getInventory().getItem(slotId); - ItemStack itemstack = handItem.copy(); - // CraftBukkit end - - if (itemstack.has(DataComponents.WRITABLE_BOOK_CONTENT)) { -- List> list1 = pages.stream().map(this::filterableFromOutgoing).toList(); -+ List> list1 = pages.stream().map(filteredText -> filterableFromOutgoing(filteredText).map(s -> color(s, hasPerm))).toList(); // Purpur - - itemstack.set(DataComponents.WRITABLE_BOOK_CONTENT, new WritableBookContent(list1)); - this.player.getInventory().setItem(slotId, CraftEventFactory.handleEditBookEvent(this.player, slotId, handItem, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) -@@ -1327,6 +1336,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - - private void signBook(FilteredText title, List pages, int slotId) { -+ // Purpur start -+ signBook(title, pages, slotId, false); -+ } -+ private void signBook(FilteredText title, List pages, int slotId, boolean hasPerm) { -+ // Purpur end - ItemStack itemstack = this.player.getInventory().getItem(slotId); - - if (itemstack.has(DataComponents.WRITABLE_BOOK_CONTENT)) { -@@ -1334,10 +1348,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - - itemstack1.remove(DataComponents.WRITABLE_BOOK_CONTENT); - List> list1 = (List>) (List) pages.stream().map((filteredtext1) -> { // CraftBukkit - decompile error -- return this.filterableFromOutgoing(filteredtext1).map(Component::literal); -+ return this.filterableFromOutgoing(filteredtext1).map(s -> hexColor(s, hasPerm)); // Purpur - }).toList(); - -- itemstack1.set(DataComponents.WRITTEN_BOOK_CONTENT, new WrittenBookContent(this.filterableFromOutgoing(title), this.player.getName().getString(), 0, list1, true)); -+ itemstack1.set(DataComponents.WRITTEN_BOOK_CONTENT, new WrittenBookContent(this.filterableFromOutgoing(title).map(s -> color(s, hasPerm)), this.player.getName().getString(), 0, list1, true)); // Purpur - CraftEventFactory.handleEditBookEvent(this.player, slotId, itemstack, itemstack1); // CraftBukkit - this.player.getInventory().setItem(slotId, itemstack); // CraftBukkit - event factory updates the hand book - } -@@ -1347,6 +1361,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - return this.player.isTextFilteringEnabled() ? Filterable.passThrough(message.filteredOrEmpty()) : Filterable.from(message); - } - -+ // Purpur start -+ private Component hexColor(String str, boolean hasPerm) { -+ return hasPerm ? PaperAdventure.asVanilla(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacyAmpersand().deserialize(str)) : Component.literal(str); -+ } -+ -+ private String color(String str, boolean hasPerm) { -+ return hasPerm ? org.bukkit.ChatColor.color(str, false) : str; -+ } -+ // Purpur end -+ - @Override - public void handleEntityTagQuery(ServerboundEntityTagQueryPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); 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 cb49fb199..faa0f926d 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 @@ -31,6 +31,11 @@ public final class PurpurPermissions { DefaultPermissions.registerPermission(PREFIX + "debug.f3n", "Allows the user to use F3+N keybind to swap gamemodes", PermissionDefault.FALSE, purpur); + Permission book = DefaultPermissions.registerPermission(PREFIX + "book", "Allows the user to use color codes on books", PermissionDefault.FALSE, purpur); + DefaultPermissions.registerPermission(PREFIX + "book.color.edit", "Allows the user to use color codes on books when editing", PermissionDefault.FALSE, book); + DefaultPermissions.registerPermission(PREFIX + "book.color.sign", "Allows the user to use color codes on books when signing", PermissionDefault.FALSE, book); + book.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/features/0001-Ridables.patch b/purpur-server/minecraft-patches/features/0001-Ridables.patch index 23e6b76a8..4852a7b31 100644 --- a/purpur-server/minecraft-patches/features/0001-Ridables.patch +++ b/purpur-server/minecraft-patches/features/0001-Ridables.patch @@ -62,10 +62,10 @@ index 8be848d3aaa34be2fa9a9de8f9f2908f0903b60f..a1ebdd491e79fff8e224095ee6058cd5 private void updatePlayerAttributes() { diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index b083228bb3dc87794c6f177ad99832daf6925a39..bf863cfae63a50636c3fcc8fcf9761f1f117d218 100644 +index 8e3359e0d2b3ff0ecb5f736eed8e22133819fd36..413e47a0257a6d275fe389e5c249be34685e38cc 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2770,6 +2770,8 @@ public class ServerGamePacketListenerImpl +@@ -2794,6 +2794,8 @@ public class ServerGamePacketListenerImpl ServerGamePacketListenerImpl.this.cserver.getPluginManager().callEvent(event); @@ -177,7 +177,7 @@ index efee812785240c1ab1fd47514cfb236a3548f9cf..666455fff2b391b637cf1c07091e8810 protected ParticleOptions getInkParticle() { return ParticleTypes.GLOW_SQUID_INK; diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index f1f894db42ea71c21ac5d76223bc7208fb82dff3..5b27adec57614b6563f8ebb520035736708c195e 100644 +index fd518913a12651a6df719628dfedc88b70806567..3e85aa9f530bef69a678c9349f366d9c65c87311 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -250,9 +250,9 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -5032,7 +5032,7 @@ index 47c1ad2ef30d464abb3c804260f0fd7cde193ba5..c6b3894fe085c2b565651ab3ae2f1acb this.openTradingScreen(player, this.getDisplayName(), 1); } diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index a8a605188f42b7875e616424be34c4bca823dd38..f58c49e6b8f121ea56f11bc107aa236969aa3208 100644 +index 7305ef5af0b13cb40b9a881a0364895395ff2072..27a0cb04dd50974a96ed420ef811d9c9f3182e52 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java @@ -218,6 +218,19 @@ public abstract class Player extends LivingEntity { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch index 53c29b89e..79751c005 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -43,6 +43,73 @@ Location oldTo = to.clone(); PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); this.cserver.getPluginManager().callEvent(event); +@@ -1212,31 +_,45 @@ + Optional optional = packet.title(); + optional.ifPresent(list::add); + list.addAll(packet.pages()); ++ // Purpur start - Allow color codes in books ++ boolean hasEditPerm = getCraftPlayer().hasPermission("purpur.book.color.edit"); ++ boolean hasSignPerm = hasEditPerm || getCraftPlayer().hasPermission("purpur.book.color.sign"); ++ // Purpur end - Allow color codes in books + Consumer> consumer = optional.isPresent() +- ? texts -> this.signBook(texts.get(0), texts.subList(1, texts.size()), slot) +- : texts -> this.updateBookContents(texts, slot); ++ ? texts -> this.signBook(texts.get(0), texts.subList(1, texts.size()), slot, hasSignPerm) // Purpur - Allow color codes in books ++ : texts -> this.updateBookContents(texts, slot, hasEditPerm); // Purpur - Allow color codes in books + this.filterTextPacket(list).thenAcceptAsync(consumer, this.server); + } + } + + private void updateBookContents(List pages, int index) { ++ // Purpur start - Allow color codes in books ++ updateBookContents(pages, index, false); ++ } ++ private void updateBookContents(List pages, int index, boolean hasPerm) { ++ // Purpur end - Allow color codes in books + // CraftBukkit start + ItemStack handItem = this.player.getInventory().getItem(index); + ItemStack item = handItem.copy(); + // CraftBukkit end + if (item.has(DataComponents.WRITABLE_BOOK_CONTENT)) { +- List> list = pages.stream().map(this::filterableFromOutgoing).toList(); ++ List> list = pages.stream().map(filteredText -> filterableFromOutgoing(filteredText).map(s -> color(s, hasPerm))).toList(); // Purpur - Allow color codes in books + item.set(DataComponents.WRITABLE_BOOK_CONTENT, new WritableBookContent(list)); + this.player.getInventory().setItem(index, CraftEventFactory.handleEditBookEvent(this.player, index, handItem, item)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) + } + } + + private void signBook(FilteredText title, List pages, int index) { ++ // Purpur start - Allow color codes in books ++ signBook(title, pages, index, false); ++ } ++ private void signBook(FilteredText title, List pages, int index, boolean hasPerm) { ++ // Purpur end - Allow color codes in books + ItemStack item = this.player.getInventory().getItem(index); + if (item.has(DataComponents.WRITABLE_BOOK_CONTENT)) { + ItemStack itemStack = item.transmuteCopy(Items.WRITTEN_BOOK); + itemStack.remove(DataComponents.WRITABLE_BOOK_CONTENT); +- List> list = pages.stream().map(filteredText -> this.filterableFromOutgoing(filteredText).map(Component::literal)).toList(); ++ List> list = pages.stream().map((filteredText) -> this.filterableFromOutgoing(filteredText).map(s -> hexColor(s, hasPerm))).toList(); // Purpur - Allow color codes in books + itemStack.set( + DataComponents.WRITTEN_BOOK_CONTENT, + new WrittenBookContent(this.filterableFromOutgoing(title), this.player.getName().getString(), 0, list, true) +@@ -1250,6 +_,16 @@ + return this.player.isTextFilteringEnabled() ? Filterable.passThrough(filteredText.filteredOrEmpty()) : Filterable.from(filteredText); + } + ++ // Purpur start - Allow color codes in books ++ private Component hexColor(String str, boolean hasPerm) { ++ return hasPerm ? PaperAdventure.asVanilla(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacyAmpersand().deserialize(str)) : Component.literal(str); ++ } ++ ++ private String color(String str, boolean hasPerm) { ++ return hasPerm ? org.bukkit.ChatColor.color(str, false) : str; ++ } ++ // Purpur end - Allow color codes in books ++ + @Override + public void handleEntityTagQuery(ServerboundEntityTagQueryPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); @@ -1460,7 +_,7 @@ movedWrongly = true; if (event.getLogWarning())