Paper/patches/server/0763-Custom-Potion-Mixes.patch
Nassim Jahnke e035fd7034
Updated Upstream (Bukkit/CraftBukkit/Spigot)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
cc9aa21a SPIGOT-6399, SPIGOT-7344: Clarify collidable behavior for player entities
f23325b6 Add API for per-world simulation distances
26e1774e Add API for per-world view distances
0b541e60 Add PlayerLoginEvent#getRealAddress
5f027d2d PR-949: Add Vector#fromJOML() overloads for read-only vector types

CraftBukkit Changes:
bcf56171a PR-1321: Clean up some stuff which got missed during previous PRs
7f833a2d1 SPIGOT-7462: Players no longer drop XP after dying near a Sculk Catalyst
752aac669 Implement APIs for per world view and simulation distances
57d7ef433 Preserve empty enchantment tags for glow effect
465ec3fb4 Remove connected check on setScoreboard
f90ce621e Use one PermissibleBase for all command blocks
5876cca44 SPIGOT-7550: Fix creation of Arrow instances
f03fc3aa3 SPIGOT-7549: ServerTickManager#setTickRate incorrect Precondition
9d7f49b01 SPIGOT-7548: Fix wrong spawn location for experience orb and dropped item

Spigot Changes:
ed9ba9a4 Drop no longer required patch ignoring -o option
86b5dd6a SPIGOT-7546: Fix hardcoded check for outdated client message
aa7cde7a Remove obsolete APIs for per world view and simulation distances
6dff577e Remove obsolete patch preserving empty `ench` tags
a3bf95b8 Remove obsolete PlayerLoginEvent#getRealAddress
1b02f5d6 Remove obsolete connected check on setScoreboard patch
acf717eb Remove obsolete command block PermissibleBase patch
053fa2a9 Remove redundant patch dealing with null tile entities
2023-12-26 00:18:13 +01:00

248 lines
12 KiB
Diff

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..7ea357ac2f3a93db4ebdf24b5072be7d1cad3e33
--- /dev/null
+++ b/src/main/java/io/papermc/paper/potion/PaperPotionMix.java
@@ -0,0 +1,21 @@
+package io.papermc.paper.potion;
+
+import java.util.function.Predicate;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.inventory.CraftRecipe;
+import org.bukkit.inventory.RecipeChoice;
+
+public record PaperPotionMix(ItemStack result, Predicate<ItemStack> input, Predicate<ItemStack> ingredient) {
+
+ public PaperPotionMix(PotionMix potionMix) {
+ this(CraftItemStack.asNMSCopy(potionMix.getResult()), convert(potionMix.getInput()), convert(potionMix.getIngredient()));
+ }
+
+ static Predicate<ItemStack> convert(final RecipeChoice choice) {
+ if (choice instanceof PredicateRecipeChoice predicateRecipeChoice) {
+ return stack -> predicateRecipeChoice.test(CraftItemStack.asBukkitCopy(stack));
+ }
+ return CraftRecipe.toIngredient(choice, true);
+ }
+}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 330a7921849a4b3ab0d7ef156af4880ef602d5eb..3da647154516ded20fd18ee4baa7242e73ab91e8 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -2227,6 +2227,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.worldData.setDataConfiguration(worlddataconfiguration);
this.resources.managers.updateRegistryTags(this.registryAccess());
+ net.minecraft.world.item.alchemy.PotionBrewing.reload(); // Paper
// Paper start
if (Thread.currentThread() != this.serverThread) {
return;
diff --git a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
index ad012400d76c263bf26cfa07e2e24f26dc32276b..82311188348d673d83b70bf4d5357ecee562b6d6 100644
--- a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
@@ -169,7 +169,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 25e909b90293855321b8f05ab3488bad8c064853..ef798adc296ae1595cfcd33fed5aa71b9ad00037 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) {
@@ -60,6 +61,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 {
@@ -93,6 +99,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();
@@ -112,6 +125,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 424406d2692856cfd82b6f3b7b6228fa3bd20c2f..c57efcb9a79337ec791e4e8f6671612f0a82b441 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
@@ -341,7 +341,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 be57ec31869e2cf9db131ec64c7581564f2b42e6..37822390d9cf71890a81e66509fa9f5ef77b2f5d 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -304,6 +304,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);
@@ -330,7 +331,7 @@ public final class CraftServer implements Server {
CraftRegistry.setMinecraftRegistry(console.registryAccess());
- Potion.setPotionBrewer(new CraftPotionBrewer());
+ Potion.setPotionBrewer(potionBrewer); // Paper
// Ugly hack :(
if (!Main.useConsole) {
@@ -3073,5 +3074,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 28fac26aa8e4da52f3e5d8e5e0d2e2731bcf74e1..13d25d118eb4d3ef35a4cdfb9bbde9ed83f6c04b 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
@@ -16,6 +16,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 09ac71b6b41c757832792d9ea8ac9288f8a7404f..2909a2736a0c9d863c7ab01e0ec259f7952080cc 100644
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java
@@ -28,4 +28,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
}