From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Thu, 7 Oct 2021 14:34:55 -0700 Subject: [PATCH] Custom Potion Mixes == AT == public-f net.minecraft.server.MinecraftServer potionBrewing diff --git a/src/main/java/io/papermc/paper/potion/PaperPotionBrewer.java b/src/main/java/io/papermc/paper/potion/PaperPotionBrewer.java new file mode 100644 index 0000000000000000000000000000000000000000..d9390227a2bba4e03aa9ee592ca157127633c41b --- /dev/null +++ b/src/main/java/io/papermc/paper/potion/PaperPotionBrewer.java @@ -0,0 +1,56 @@ +package io.papermc.paper.potion; + +import com.google.common.base.Preconditions; +import java.util.Collection; +import net.minecraft.server.MinecraftServer; +import org.bukkit.NamespacedKey; +import org.bukkit.potion.PotionBrewer; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionType; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +@DefaultQualifier(NonNull.class) +public class PaperPotionBrewer implements PotionBrewer { + + private final MinecraftServer minecraftServer; + + public PaperPotionBrewer(final MinecraftServer minecraftServer) { + this.minecraftServer = minecraftServer; + } + + @Override + @Deprecated(forRemoval = true) + public Collection getEffects(PotionType type, boolean upgraded, boolean extended) { + final org.bukkit.NamespacedKey key = type.getKey(); + + Preconditions.checkArgument(!key.getKey().startsWith("strong_"), "Strong potion type cannot be used directly, got %s", key); + Preconditions.checkArgument(!key.getKey().startsWith("long_"), "Extended potion type cannot be used directly, got %s", key); + + org.bukkit.NamespacedKey effectiveKey = key; + if (upgraded) { + effectiveKey = new org.bukkit.NamespacedKey(key.namespace(), "strong_" + key.key()); + } else if (extended) { + effectiveKey = new org.bukkit.NamespacedKey(key.namespace(), "long_" + key.key()); + } + + final org.bukkit.potion.PotionType effectivePotionType = org.bukkit.Registry.POTION.get(effectiveKey); + Preconditions.checkNotNull(type, "Unknown potion type from data " + effectiveKey.asMinimalString()); // Legacy error message in 1.20.4 + return effectivePotionType.getPotionEffects(); + } + + @Override + public void addPotionMix(final PotionMix potionMix) { + this.minecraftServer.potionBrewing().addPotionMix(potionMix); + } + + @Override + public void removePotionMix(final NamespacedKey key) { + this.minecraftServer.potionBrewing.removePotionMix(key); + } + + @Override + public void resetPotionMixes() { + this.minecraftServer.potionBrewing = this.minecraftServer.potionBrewing().reload(this.minecraftServer.getWorldData().enabledFeatures()); + } +} 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 input, Predicate ingredient) { + + public PaperPotionMix(PotionMix potionMix) { + this(CraftItemStack.asNMSCopy(potionMix.getResult()), convert(potionMix.getInput()), convert(potionMix.getIngredient())); + } + + static Predicate 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 04286e907ff14cc8c45dbfc6ab12f520afcca2ca..8142e4a238066404f3d1685f9cee1a2b91cdd371 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -2160,6 +2160,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop containers; private final List> potionMixes; private final List> containerMixes; + private final it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap customMixes = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>(); // Paper - Custom Potion Mixes PotionBrewing(List potionTypes, List> potionRecipes, List> itemRecipes) { this.containers = potionTypes; @@ -27,7 +28,7 @@ public class PotionBrewing { } public boolean isIngredient(ItemStack stack) { - return this.isContainerIngredient(stack) || this.isPotionIngredient(stack); + return this.isContainerIngredient(stack) || this.isPotionIngredient(stack) || this.isCustomIngredient(stack); // Paper - Custom Potion Mixes } private boolean isContainer(ItemStack stack) { @@ -71,6 +72,11 @@ public class PotionBrewing { } public boolean hasMix(ItemStack input, ItemStack ingredient) { + // Paper start - Custom Potion Mixes + if (this.hasCustomMix(input, ingredient)) { + return true; + } + // Paper end - Custom Potion Mixes return this.isContainer(input) && (this.hasContainerMix(input, ingredient) || this.hasPotionMix(input, ingredient)); } @@ -103,6 +109,13 @@ public class PotionBrewing { if (input.isEmpty()) { return input; } else { + // Paper start - Custom Potion Mixes + for (io.papermc.paper.potion.PaperPotionMix mix : this.customMixes.values()) { + if (mix.input().test(input) && mix.ingredient().test(ingredient)) { + return mix.result().copy(); + } + } + // Paper end - Custom Potion Mixes Optional> optional = input.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).potion(); if (optional.isEmpty()) { return input; @@ -190,6 +203,50 @@ public class PotionBrewing { builder.addMix(Potions.SLOW_FALLING, Items.REDSTONE, Potions.LONG_SLOW_FALLING); } + // Paper start - Custom Potion Mixes + public boolean isCustomIngredient(ItemStack stack) { + for (io.papermc.paper.potion.PaperPotionMix mix : this.customMixes.values()) { + if (mix.ingredient().test(stack)) { + return true; + } + } + return false; + } + + public boolean isCustomInput(ItemStack stack) { + for (io.papermc.paper.potion.PaperPotionMix mix : this.customMixes.values()) { + if (mix.input().test(stack)) { + return true; + } + } + return false; + } + + private boolean hasCustomMix(ItemStack input, ItemStack ingredient) { + for (io.papermc.paper.potion.PaperPotionMix mix : this.customMixes.values()) { + if (mix.input().test(input) && mix.ingredient().test(ingredient)) { + return true; + } + } + return false; + } + + public void addPotionMix(io.papermc.paper.potion.PotionMix mix) { + if (this.customMixes.containsKey(mix.getKey())) { + throw new IllegalArgumentException("Duplicate recipe ignored with ID " + mix.getKey()); + } + this.customMixes.putAndMoveToFirst(mix.getKey(), new io.papermc.paper.potion.PaperPotionMix(mix)); + } + + public boolean removePotionMix(org.bukkit.NamespacedKey key) { + return this.customMixes.remove(key) != null; + } + + public PotionBrewing reload(FeatureFlagSet flags) { + return bootstrap(flags); + } + // Paper end - Custom Potion Mixes + public static class Builder { private final List containers = new ArrayList<>(); private final List> potionMixes = new ArrayList<>(); 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 c8f9972ad1c2330908cc840d426f29c20b242ca8..a2fafef89d5354e2cb02f5672810909950a57777 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 @@ -315,12 +315,12 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements @Override public boolean canPlaceItem(int slot, ItemStack stack) { + PotionBrewing potionbrewer = this.level != null ? this.level.potionBrewing() : PotionBrewing.EMPTY; // Paper - move up if (slot == 3) { - PotionBrewing potionbrewer = this.level != null ? this.level.potionBrewing() : PotionBrewing.EMPTY; return potionbrewer.isIngredient(stack); } else { - return 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 == 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) || potionbrewer.isCustomInput(stack)) && this.getItem(slot).isEmpty(); // Paper - Custom Potion Mixes } } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 65cb367f0824b4045c436dd66809dd9a3eeccbcd..56fe4a91b557db7bd74c031046231a3bc7ba72c8 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -308,6 +308,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 io.papermc.paper.potion.PaperPotionBrewer potionBrewer; // Paper - Custom Potion Mixes static { ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); @@ -391,6 +392,7 @@ public final class CraftServer implements Server { if (this.configuration.getBoolean("settings.use-map-color-cache")) { MapPalette.setMapColorCache(new CraftMapColorCache(this.logger)); } + this.potionBrewer = new io.papermc.paper.potion.PaperPotionBrewer(console); // Paper - custom potion mixes datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper } @@ -3046,5 +3048,9 @@ public final class CraftServer implements Server { return datapackManager; } + @Override + public io.papermc.paper.potion.PaperPotionBrewer 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 139dff90561ac6c51954c6289918a07aeea13a1b..6ba29875d78ede4aa7978ff689e588f7fed11528 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java @@ -15,6 +15,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) {