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 05b834a99649e3f3e8e7759234006b1c0b799629..85b3bf7718e51ffa52799c0748843aaad3fd3813 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2059,6 +2059,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
if (Thread.currentThread() != this.serverThread) return; // Paper
//this.getPlayerList().saveAll(); // Paper - we don't need to do this
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 287205bce7f655f9a6b815f40d349c3db4c1e788..5c0f1488c8a8100cd39a03adeccded9984722249 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
@@ -336,7 +336,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 278a025f141b2011dc2b4e35e70a8013b918a33e..55c981f2c8070fc1bd9ecd4f4df140d9d0c68319 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -284,6 +284,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);
@@ -310,7 +311,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 :(
@@ -2846,5 +2847,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
}
|