From 1da2f0afbc0d906a537dd83fdda1ba2e579be00a Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Sat, 24 Apr 2021 15:16:41 -0700
Subject: [PATCH] Implement methods to convert between Component and
 Brigadier's Message (#5542)

---
 .../paper/brigadier/PaperBrigadier.java       | 42 ++++++++++++++
 .../brigadier/PaperBrigadierProvider.java     | 30 ++++++++++
 ...s-to-convert-between-Component-and-B.patch | 55 +++++++++++++++++++
 3 files changed, 127 insertions(+)
 create mode 100644 Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java
 create mode 100644 Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProvider.java
 create mode 100644 Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch

diff --git a/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java b/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java
new file mode 100644
index 0000000000..1ed5a6d271
--- /dev/null
+++ b/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadier.java
@@ -0,0 +1,42 @@
+package io.papermc.paper.brigadier;
+
+import com.mojang.brigadier.Message;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.ComponentLike;
+import net.kyori.adventure.text.TextComponent;
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+/**
+ * Helper methods to bridge the gaps between Brigadier and Paper-MojangAPI.
+ */
+public final class PaperBrigadier {
+    private PaperBrigadier() {
+        throw new RuntimeException("PaperBrigadier is not to be instantiated!");
+    }
+
+    /**
+     * Create a new Brigadier {@link Message} from a {@link ComponentLike}.
+     *
+     * <p>Mostly useful for creating rich suggestion tooltips in combination with other Paper-MojangAPI APIs.</p>
+     *
+     * @param componentLike The {@link ComponentLike} to use for the {@link Message} contents
+     * @return A new Brigadier {@link Message}
+     */
+    public static @NonNull Message message(final @NonNull ComponentLike componentLike) {
+        return PaperBrigadierProvider.instance().message(componentLike);
+    }
+
+    /**
+     * Create a new {@link Component} from a Brigadier {@link Message}.
+     *
+     * <p>If the {@link Message} was created from a {@link Component}, it will simply be
+     * converted back, otherwise a new {@link TextComponent} will be created with the
+     * content of {@link Message#getString()}</p>
+     *
+     * @param message The {@link Message} to create a {@link Component} from
+     * @return The created {@link Component}
+     */
+    public static @NonNull Component componentFromMessage(final @NonNull Message message) {
+        return PaperBrigadierProvider.instance().componentFromMessage(message);
+    }
+}
diff --git a/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProvider.java b/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProvider.java
new file mode 100644
index 0000000000..7f24806384
--- /dev/null
+++ b/Paper-MojangAPI/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProvider.java
@@ -0,0 +1,30 @@
+package io.papermc.paper.brigadier;
+
+import com.mojang.brigadier.Message;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.ComponentLike;
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+import static java.util.Objects.requireNonNull;
+
+interface PaperBrigadierProvider {
+    final class Holder {
+        private static @MonotonicNonNull PaperBrigadierProvider INSTANCE;
+    }
+
+    static @NonNull PaperBrigadierProvider instance() {
+        return requireNonNull(Holder.INSTANCE, "PaperBrigadierProvider has not yet been initialized!");
+    }
+
+    static void initialize(final @NonNull PaperBrigadierProvider instance) {
+        if (Holder.INSTANCE != null) {
+            throw new IllegalStateException("PaperBrigadierProvider has already been initialized!");
+        }
+        Holder.INSTANCE = instance;
+    }
+
+    @NonNull Message message(@NonNull ComponentLike componentLike);
+
+    @NonNull Component componentFromMessage(@NonNull Message message);
+}
diff --git a/Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch b/Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch
new file mode 100644
index 0000000000..6faedaa799
--- /dev/null
+++ b/Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch
@@ -0,0 +1,55 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
+Date: Sat, 24 Apr 2021 02:09:32 -0700
+Subject: [PATCH] Implement methods to convert between Component and
+ Brigadier's Message
+
+
+diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java
+@@ -0,0 +0,0 @@
++package io.papermc.paper.brigadier;
++
++import com.mojang.brigadier.Message;
++import io.papermc.paper.adventure.PaperAdventure;
++import net.kyori.adventure.text.Component;
++import net.kyori.adventure.text.ComponentLike;
++import net.minecraft.network.chat.ChatComponentUtils;
++import org.checkerframework.checker.nullness.qual.NonNull;
++
++import static java.util.Objects.requireNonNull;
++
++public enum PaperBrigadierProviderImpl implements PaperBrigadierProvider {
++    INSTANCE;
++
++    PaperBrigadierProviderImpl() {
++        PaperBrigadierProvider.initialize(this);
++    }
++
++    @Override
++    public @NonNull Message message(final @NonNull ComponentLike componentLike) {
++        requireNonNull(componentLike, "componentLike");
++        return PaperAdventure.asVanilla(componentLike.asComponent());
++    }
++
++    @Override
++    public @NonNull Component componentFromMessage(final @NonNull Message message) {
++        requireNonNull(message, "message");
++        return PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(message));
++    }
++}
+diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
+         }
+         com.destroystokyo.paper.PaperConfig.registerCommands();
+         com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
++        io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider
+         // Paper end
+ 
+         this.setPVP(dedicatedserverproperties.pvp);