From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 7 Oct 2021 14:34:59 -0700
Subject: [PATCH] Custom Potion Mixes


diff --git a/src/main/java/io/papermc/paper/potion/PotionMix.java b/src/main/java/io/papermc/paper/potion/PotionMix.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb6d93526b637946aec311bef103ad3096781113
--- /dev/null
+++ b/src/main/java/io/papermc/paper/potion/PotionMix.java
@@ -0,0 +1,91 @@
+package io.papermc.paper.potion;
+
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.RecipeChoice;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+/**
+ * Represents a potion mix made in a Brewing Stand.
+ */
+@ApiStatus.NonExtendable
+public class PotionMix implements Keyed {
+
+    private final NamespacedKey key;
+    private final ItemStack result;
+    private final RecipeChoice input;
+    private final RecipeChoice ingredient;
+
+    /**
+     * Creates a new potion mix. Add it to the server with {@link org.bukkit.potion.PotionBrewer#addPotionMix(PotionMix)}.
+     *
+     * @param key a unique key for the mix
+     * @param result the resulting itemstack that will appear in the 3 bottom slots
+     * @param input the input placed into the bottom 3 slots
+     * @param ingredient the ingredient placed into the top slot
+     */
+    public PotionMix(@NotNull NamespacedKey key, @NotNull ItemStack result, @NotNull RecipeChoice input, @NotNull RecipeChoice ingredient) {
+        this.key = key;
+        this.result = result;
+        this.input = input;
+        this.ingredient = ingredient;
+    }
+
+    @Override
+    public @NotNull NamespacedKey getKey() {
+        return this.key;
+    }
+
+    /**
+     * Gets the resulting itemstack after the brew has finished.
+     *
+     * @return the result itemstack
+     */
+    public @NotNull ItemStack getResult() {
+        return this.result;
+    }
+
+    /**
+     * Gets the input for the bottom 3 slots in the brewing stand.
+     *
+     * @return the bottom 3 slot ingredients
+     */
+    public @NotNull RecipeChoice getInput() {
+        return this.input;
+    }
+
+    /**
+     * Gets the ingredient in the top slot of the brewing stand.
+     *
+     * @return the top slot input
+     */
+    public @NotNull RecipeChoice getIngredient() {
+        return this.ingredient;
+    }
+
+    @Override
+    public String toString() {
+        return "PotionMix{" +
+            "result=" + this.result +
+            ", base=" + this.input +
+            ", addition=" + this.ingredient +
+            '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        PotionMix potionMix = (PotionMix) o;
+        return this.key.equals(potionMix.key) && this.result.equals(potionMix.result) && this.input.equals(potionMix.input) && this.ingredient.equals(potionMix.ingredient);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(this.key, this.result, this.input, this.ingredient);
+    }
+}
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 49decde8052425dcdaa865040f5aefa7a66667d5..3506a7fa07ee6e53704b1df8d8d2bb08704bfc37 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -2397,6 +2397,15 @@ public final class Bukkit {
     public static io.papermc.paper.datapack.DatapackManager getDatapackManager() {
         return server.getDatapackManager();
     }
+
+    /**
+     * Gets the potion brewer.
+     *
+     * @return the potion brewer
+     */
+    public static @NotNull org.bukkit.potion.PotionBrewer getPotionBrewer() {
+        return server.getPotionBrewer();
+    }
     // Paper end
 
     @NotNull
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index bd678287c89a2a9578b08399886333e4dc866583..e756edf56995f4552387c2e1082307eb3dd48bb3 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2082,5 +2082,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
      */
     @NotNull
     io.papermc.paper.datapack.DatapackManager getDatapackManager();
+
+    /**
+     * Gets the potion brewer.
+     *
+     * @return the potion brewer
+     */
+    @NotNull org.bukkit.potion.PotionBrewer getPotionBrewer();
     // Paper end
 }
diff --git a/src/main/java/org/bukkit/potion/PotionBrewer.java b/src/main/java/org/bukkit/potion/PotionBrewer.java
index d21f407cc16cfd709c1cabf408e8d8d16aba7e1a..1598f34d306fb34ff7ffe7886b0d6e4abe734b6b 100644
--- a/src/main/java/org/bukkit/potion/PotionBrewer.java
+++ b/src/main/java/org/bukkit/potion/PotionBrewer.java
@@ -43,4 +43,25 @@ public interface PotionBrewer {
      */
     @NotNull
     public Collection<PotionEffect> getEffects(@NotNull PotionType type, boolean upgraded, boolean extended);
+
+    // Paper start
+    /**
+     * Adds a new potion mix recipe.
+     *
+     * @param potionMix the potion mix to add
+     */
+    void addPotionMix(@NotNull io.papermc.paper.potion.PotionMix potionMix);
+
+    /**
+     * Removes a potion mix recipe.
+     *
+     * @param key the key of the mix to remove
+     */
+    void removePotionMix(@NotNull org.bukkit.NamespacedKey key);
+
+    /**
+     * Resets potion mixes to their default, removing all custom ones.
+     */
+    void resetPotionMixes();
+    // Paper end
 }