From ca1bbde6e218492b822c984348e19e7d14ba3d59 Mon Sep 17 00:00:00 2001
From: Vitphire <mininjawasd@gmail.com>
Date: Tue, 9 Apr 2024 18:12:52 +0200
Subject: [PATCH 1/2] Fixed a crash (unhandled null check)

---
 src/main/java/anticope/rejects/modules/ColorSigns.java | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/main/java/anticope/rejects/modules/ColorSigns.java b/src/main/java/anticope/rejects/modules/ColorSigns.java
index 87b80e92..7ed4f3f5 100644
--- a/src/main/java/anticope/rejects/modules/ColorSigns.java
+++ b/src/main/java/anticope/rejects/modules/ColorSigns.java
@@ -6,6 +6,7 @@
 import meteordevelopment.orbit.EventHandler;
 import net.minecraft.network.packet.c2s.play.UpdateSignC2SPacket;
 import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
+import net.minecraft.server.MinecraftServer;
 
 public class ColorSigns extends Module {
 
@@ -35,7 +36,10 @@ public void onActivate() {
     }
 
     private void checkWarning() {
-        String brand = mc.player.getServer().getServerModName();
+        assert mc.player != null;
+        MinecraftServer server = mc.player.getServer();
+        if (server == null) return;
+        String brand = server.getServerModName();
         if (brand == null) return;
         if (brand.contains("Paper")) warning("You are on a paper server. Color signs won't work here");
     }

From 133eae92438ba17f79126576ee4447ddfaf2fea9 Mon Sep 17 00:00:00 2001
From: Vitphire <mininjawasd@gmail.com>
Date: Tue, 9 Apr 2024 18:16:53 +0200
Subject: [PATCH 2/2] Added book color functionality to ColorSigns

---
 .../anticope/rejects/modules/ColorSigns.java  | 46 ++++++++++++++++---
 1 file changed, 39 insertions(+), 7 deletions(-)

diff --git a/src/main/java/anticope/rejects/modules/ColorSigns.java b/src/main/java/anticope/rejects/modules/ColorSigns.java
index 7ed4f3f5..a130ba9d 100644
--- a/src/main/java/anticope/rejects/modules/ColorSigns.java
+++ b/src/main/java/anticope/rejects/modules/ColorSigns.java
@@ -2,31 +2,63 @@
 
 import anticope.rejects.MeteorRejectsAddon;
 import meteordevelopment.meteorclient.events.packets.PacketEvent;
+import meteordevelopment.meteorclient.settings.BoolSetting;
+import meteordevelopment.meteorclient.settings.Setting;
+import meteordevelopment.meteorclient.settings.SettingGroup;
 import meteordevelopment.meteorclient.systems.modules.Module;
 import meteordevelopment.orbit.EventHandler;
+import net.minecraft.network.packet.c2s.play.BookUpdateC2SPacket;
 import net.minecraft.network.packet.c2s.play.UpdateSignC2SPacket;
 import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
 import net.minecraft.server.MinecraftServer;
 
+import java.util.List;
+
 public class ColorSigns extends Module {
 
+    private final SettingGroup sgGeneral = settings.getDefaultGroup();
+
+    private final Setting<Boolean> signs = sgGeneral.add(new BoolSetting.Builder()
+            .name("signs")
+            .description("Allows you to use colors in signs.")
+            .defaultValue(true)
+            .build()
+    );
+
+    private final Setting<Boolean> books = sgGeneral.add(new BoolSetting.Builder()
+            .name("books")
+            .description("Allows you to use colors in books.")
+            .defaultValue(false)
+            .build()
+    );
+
     public ColorSigns() {
         super(MeteorRejectsAddon.CATEGORY, "color-signs", "Allows you to use colors on signs on NON-PAPER servers (use \"&\" for color symbols)");
     }
-    
+
     @EventHandler
     private void onPacketSend(PacketEvent.Send event) {
         if (event.packet instanceof GameJoinS2CPacket) {
             checkWarning();
             return;
         }
-        if (!(event.packet instanceof UpdateSignC2SPacket)) return;
-        UpdateSignC2SPacket p = (UpdateSignC2SPacket)event.packet;
-        for (int l = 0; l < p.getText().length; l++) {
-            String newText = p.getText()[l].replaceAll("(?i)\u00a7|&([0-9A-FK-OR])", "\u00a7\u00a7$1$1");
-            p.getText()[l] = newText;
+        if (signs.get() && event.packet instanceof UpdateSignC2SPacket packet) {
+            for (int line = 0; line < packet.getText().length; line++) {
+                packet.getText()[line] = packet.getText()[line]
+                        .replaceAll("(?i)(?:&|(?<!§)§)([0-9A-Z])", "§§$1$1");
+            }
+        }
+        if (books.get() && event.packet instanceof BookUpdateC2SPacket packet) {
+            List<String> newPages = packet.getPages().stream().map(text ->
+                    text.replaceAll("(?i)&([0-9A-Z])", "§$1")).toList();
+            // BookUpdateC2SPacket.pages is final, so we need to create a new packet
+            if (!packet.getPages().equals(newPages)) {
+                assert mc.getNetworkHandler() != null;
+                mc.getNetworkHandler().sendPacket(new BookUpdateC2SPacket(
+                        packet.getSlot(), newPages, packet.getTitle()));
+                event.cancel();
+            }
         }
-        event.packet = p;
     }
 
     @Override