diff --git a/patches/server/Fix-sendSignChange0-s-usage-of-SignText.patch b/patches/server/Fix-sendSignChange0-s-usage-of-SignText.patch
new file mode 100644
index 0000000000..8b0f92f0a9
--- /dev/null
+++ b/patches/server/Fix-sendSignChange0-s-usage-of-SignText.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Bjarne Koll <git@lynxplay.dev>
+Date: Sun, 11 Jun 2023 18:45:10 +0200
+Subject: [PATCH] Fix sendSignChange0's usage of SignText
+
+Minecraft 1.20 introduced the SignText class that holds onto the text of
+a single side of a minecraft sign.
+This type is immutable and any methods on it produce an updated, new
+instance of the class rather than mutating the called upon instance.
+
+Spigot does not respect this change as it does not re-assign the
+constructed sign text to the instance nor does it feed back said
+instance to the virtual sign block entity.
+
+diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
+     private void sendSignChange0(Component[] components, Location loc, DyeColor dyeColor, boolean hasGlowingText) {
+         SignBlockEntity sign = new SignBlockEntity(CraftLocation.toBlockPosition(loc), Blocks.OAK_SIGN.defaultBlockState());
+         SignText text = sign.getFrontText();
+-        text.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData()));
+-        text.setHasGlowingText(hasGlowingText);
++        // Paper start - fix sign change using immutable SignText type
++        text = text.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData()));
++        text = text.setHasGlowingText(hasGlowingText);
+         for (int i = 0; i < components.length; i++) {
+-            text.setMessage(i, components[i]);
++            text = text.setMessage(i, components[i]);
+         }
++        sign.setText(text, true);
++        // Paper end - fix sign change using immutable SignText type
+ 
+         getHandle().connection.send(sign.getUpdatePacket());
+         // Paper end