aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0823-Custom-Potion-Mixes.patch
blob: 83f97585c55bd983db8d0320f3ee2a181d398128 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 7 Oct 2021 14:34:55 -0700
Subject: [PATCH] Custom Potion Mixes


diff --git a/src/main/java/io/papermc/paper/potion/PaperPotionMix.java b/src/main/java/io/papermc/paper/potion/PaperPotionMix.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b0bed550763f34e18c9e92f9a47ec0c945b2c8b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/potion/PaperPotionMix.java
@@ -0,0 +1,13 @@
+package io.papermc.paper.potion;
+
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.crafting.Ingredient;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.inventory.CraftRecipe;
+
+public record PaperPotionMix(ItemStack result, Ingredient input, Ingredient ingredient) {
+
+    public PaperPotionMix(PotionMix potionMix) {
+        this(CraftItemStack.asNMSCopy(potionMix.getResult()), CraftRecipe.toIngredient(potionMix.getInput(), true), CraftRecipe.toIngredient(potionMix.getIngredient(), true));
+    }
+}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 56c49187c63fd124738ed1efe634ddfcd0f846f9..41543b69934c5e5c050636482c7d2b93a6bab796 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2043,6 +2043,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
             this.worldData.setDataPackConfig(MinecraftServer.getSelectedPacks(this.packRepository));
             this.resources.managers.updateRegistryTags(this.registryAccess());
             io.papermc.paper.registry.PaperRegistry.clearCaches(); // Paper
+            net.minecraft.world.item.alchemy.PotionBrewing.reload(); // Paper
             new io.papermc.paper.event.server.ServerResourcesReloadedEvent(cause).callEvent(); // Paper
             // Paper start
             if (Thread.currentThread() != this.serverThread) {
diff --git a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
index a809e8a903f98fcbcea3184fac6dfd04adc735f9..13720c2df8ac37d020d4a785e48c45877edf74b9 100644
--- a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
@@ -168,7 +168,7 @@ public class BrewingStandMenu extends AbstractContainerMenu {
         }
 
         public static boolean mayPlaceItem(ItemStack stack) {
-            return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE);
+            return stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || PotionBrewing.isCustomInput(stack); // Paper
         }
     }
 
diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java b/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java
index eee96f87f68d9146b1d19d5923d073fb5c39d507..5d86895f93cadcf0b123263c2a6f718fedcb24ac 100644
--- a/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java
+++ b/src/main/java/net/minecraft/world/item/alchemy/PotionBrewing.java
@@ -14,6 +14,7 @@ public class PotionBrewing {
     public static final int BREWING_TIME_SECONDS = 20;
     private static final List<PotionBrewing.Mix<Potion>> POTION_MIXES = Lists.newArrayList();
     private static final List<PotionBrewing.Mix<Item>> CONTAINER_MIXES = Lists.newArrayList();
+    private static final it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<org.bukkit.NamespacedKey, io.papermc.paper.potion.PaperPotionMix> CUSTOM_MIXES = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>(); // Paper
     private static final List<Ingredient> ALLOWED_CONTAINERS = Lists.newArrayList();
     private static final Predicate<ItemStack> ALLOWED_CONTAINER = (stack) -> {
         for(Ingredient ingredient : ALLOWED_CONTAINERS) {
@@ -26,7 +27,7 @@ public class PotionBrewing {
     };
 
     public static boolean isIngredient(ItemStack stack) {
-        return isContainerIngredient(stack) || isPotionIngredient(stack);
+        return isContainerIngredient(stack) || isPotionIngredient(stack) || isCustomIngredient(stack); // Paper
     }
 
     protected static boolean isContainerIngredient(ItemStack stack) {
@@ -66,6 +67,11 @@ public class PotionBrewing {
     }
 
     public static boolean hasMix(ItemStack input, ItemStack ingredient) {
+        // Paper start
+        if (hasCustomMix(input, ingredient)) {
+            return true;
+        }
+        // Paper end
         if (!ALLOWED_CONTAINER.test(input)) {
             return false;
         } else {
@@ -103,6 +109,13 @@ public class PotionBrewing {
 
     public static ItemStack mix(ItemStack ingredient, ItemStack input) {
         if (!input.isEmpty()) {
+            // Paper start
+            for (var mix : CUSTOM_MIXES.values()) {
+                if (mix.input().test(input) && mix.ingredient().test(ingredient)) {
+                    return mix.result().copy();
+                }
+            }
+            // Paper end
             Potion potion = PotionUtils.getPotion(input);
             Item item = input.getItem();
             int i = 0;
@@ -127,6 +140,54 @@ public class PotionBrewing {
         return input;
     }
 
+    // Paper start
+    public static boolean isCustomIngredient(ItemStack stack) {
+        for (var mix : CUSTOM_MIXES.values()) {
+            if (mix.ingredient().test(stack)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean isCustomInput(ItemStack stack) {
+        for (var mix : CUSTOM_MIXES.values()) {
+            if (mix.input().test(stack)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean hasCustomMix(ItemStack input, ItemStack ingredient) {
+        for (var mix : CUSTOM_MIXES.values()) {
+            if (mix.input().test(input) && mix.ingredient().test(ingredient)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static void addPotionMix(io.papermc.paper.potion.PotionMix mix) {
+        if (CUSTOM_MIXES.containsKey(mix.getKey())) {
+            throw new IllegalArgumentException("Duplicate recipe ignored with ID " + mix.getKey());
+        }
+        CUSTOM_MIXES.putAndMoveToFirst(mix.getKey(), new io.papermc.paper.potion.PaperPotionMix(mix));
+    }
+
+    public static boolean removePotionMix(org.bukkit.NamespacedKey key) {
+        return CUSTOM_MIXES.remove(key) != null;
+    }
+
+    public static void reload() {
+        POTION_MIXES.clear();
+        CONTAINER_MIXES.clear();
+        ALLOWED_CONTAINERS.clear();
+        CUSTOM_MIXES.clear();
+        bootStrap();
+    }
+    // Paper end
+
     public static void bootStrap() {
         addContainer(Items.POTION);
         addContainer(Items.SPLASH_POTION);
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
index 3d688e334c7287f41460bd866bfd1155e8bb55d2..55006724ccec9f3de828ec18693728e9741ff65f 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
@@ -335,7 +335,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
 
     @Override
     public boolean canPlaceItem(int slot, ItemStack stack) {
-        return slot == 3 ? PotionBrewing.isIngredient(stack) : (slot == 4 ? stack.is(Items.BLAZE_POWDER) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE)) && this.getItem(slot).isEmpty());
+        return slot == 3 ? PotionBrewing.isIngredient(stack) : (slot == 4 ? stack.is(Items.BLAZE_POWDER) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || PotionBrewing.isCustomInput(stack)) && this.getItem(slot).isEmpty()); // Paper
     }
 
     @Override
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 418ec6b1fb062ad5b4642c2a5ccc32775f8c8b48..b819ec350d230ea9425b4c1512dba2438408f066 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -285,6 +285,7 @@ public final class CraftServer implements Server {
     private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper
     public static Exception excessiveVelEx; // Paper - Velocity warnings
     private final io.papermc.paper.logging.SysoutCatcher sysoutCatcher = new io.papermc.paper.logging.SysoutCatcher(); // Paper
+    private final CraftPotionBrewer potionBrewer = new CraftPotionBrewer(); // Paper
 
     static {
         ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
@@ -311,7 +312,7 @@ public final class CraftServer implements Server {
         Enchantments.SHARPNESS.getClass();
         org.bukkit.enchantments.Enchantment.stopAcceptingRegistrations();
 
-        Potion.setPotionBrewer(new CraftPotionBrewer());
+        Potion.setPotionBrewer(potionBrewer); // Paper
         MobEffects.BLINDNESS.getClass();
         PotionEffectType.stopAcceptingRegistrations();
         // Ugly hack :(
@@ -2896,5 +2897,10 @@ public final class CraftServer implements Server {
         return datapackManager;
     }
 
+    @Override
+    public CraftPotionBrewer getPotionBrewer() {
+        return this.potionBrewer;
+    }
+
     // Paper end
 }
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
index 10ace7bb17c36bfefc584a6322841ab6ea4c866f..71486c08db28caf89f2366e082f6f6fab5609b71 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
@@ -13,6 +13,11 @@ public interface CraftRecipe extends Recipe {
     void addToCraftingManager();
 
     default Ingredient toNMS(RecipeChoice bukkit, boolean requireNotEmpty) {
+        // Paper start
+        return toIngredient(bukkit, requireNotEmpty);
+    }
+    static Ingredient toIngredient(RecipeChoice bukkit, boolean requireNotEmpty) {
+        // Paper end
         Ingredient stack;
 
         if (bukkit == null) {
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
index 8fdc9a3bb2f1b6bdc6c2c96f8ade7e9cd88ea4e0..a0b0c64b819b8f713eeea78210e276664e30e66e 100644
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
@@ -49,4 +49,21 @@ public class CraftPotionBrewer implements PotionBrewer {
     public PotionEffect createEffect(PotionEffectType potion, int duration, int amplifier) {
         return new PotionEffect(potion, potion.isInstant() ? 1 : (int) (duration * potion.getDurationModifier()), amplifier);
     }
+
+    // Paper start
+    @Override
+    public void addPotionMix(io.papermc.paper.potion.PotionMix potionMix) {
+        net.minecraft.world.item.alchemy.PotionBrewing.addPotionMix(potionMix);
+    }
+
+    @Override
+    public void removePotionMix(org.bukkit.NamespacedKey key) {
+        net.minecraft.world.item.alchemy.PotionBrewing.removePotionMix(key);
+    }
+
+    @Override
+    public void resetPotionMixes() {
+        net.minecraft.world.item.alchemy.PotionBrewing.reload();
+    }
+    // Paper end
 }