Skip to content

Commit

Permalink
Support brewing recipes in tags (#2423)
Browse files Browse the repository at this point in the history
* Support brewing recipes in recipe tags

* Move `BrewingRecipe`

* Impl on 1.18

* Minor cleanup

* Meta fix and cleanup

* Meta fix

* Better naming

* Minor cleanups
  • Loading branch information
tal5 committed Jan 2, 2023
1 parent f642744 commit 1349bf6
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 69 deletions.
Expand Up @@ -5,6 +5,7 @@
import com.denizenscript.denizen.nms.util.jnbt.IntArrayTag;
import com.denizenscript.denizen.nms.util.jnbt.Tag;
import com.denizenscript.denizen.objects.ItemTag;
import com.denizenscript.denizen.utilities.inventory.BrewingRecipe;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.data.BlockData;
Expand All @@ -13,6 +14,8 @@
import org.bukkit.inventory.ShapedRecipe;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

public abstract class ItemHelper {
Expand Down Expand Up @@ -72,4 +75,16 @@ public BlockData getPlacedBlock(Material material) {
}

public abstract boolean isValidMix(ItemStack input, ItemStack ingredient);

public Map<NamespacedKey, BrewingRecipe> getCustomBrewingRecipes() {
throw new UnsupportedOperationException();
}

public Set<NamespacedKey> getCustomBrewingRecipeIDs() {
throw new UnsupportedOperationException();
}

public BrewingRecipe getCustomBrewingRecipe(NamespacedKey recipeKey) {
throw new UnsupportedOperationException();
}
}
55 changes: 35 additions & 20 deletions plugin/src/main/java/com/denizenscript/denizen/objects/ItemTag.java
@@ -1,31 +1,34 @@
package com.denizenscript.denizen.objects;

import com.denizenscript.denizen.Denizen;
import com.denizenscript.denizen.events.BukkitScriptEvent;
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.nms.util.jnbt.StringTag;
import com.denizenscript.denizen.objects.properties.item.*;
import com.denizenscript.denizen.scripts.containers.core.BookScriptContainer;
import com.denizenscript.denizen.scripts.containers.core.ItemScriptContainer;
import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper;
import com.denizenscript.denizen.tags.BukkitTagContext;
import com.denizenscript.denizen.utilities.Utilities;
import com.denizenscript.denizen.utilities.inventory.BrewingRecipe;
import com.denizenscript.denizen.utilities.nbt.CustomNBT;
import com.denizenscript.denizencore.events.ScriptEvent;
import com.denizenscript.denizencore.flags.AbstractFlagTracker;
import com.denizenscript.denizencore.flags.FlaggableObject;
import com.denizenscript.denizencore.flags.MapTagFlagTracker;
import com.denizenscript.denizencore.objects.properties.Property;
import com.denizenscript.denizencore.utilities.CoreConfiguration;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizencore.objects.*;
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.util.jnbt.StringTag;
import com.denizenscript.denizen.tags.BukkitTagContext;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.objects.properties.Property;
import com.denizenscript.denizencore.objects.properties.PropertyParser;
import com.denizenscript.denizencore.scripts.ScriptRegistry;
import com.denizenscript.denizencore.tags.Attribute;
import com.denizenscript.denizencore.tags.ObjectTagProcessor;
import com.denizenscript.denizencore.tags.TagContext;
import com.denizenscript.denizencore.utilities.CoreConfiguration;
import com.denizenscript.denizencore.utilities.CoreUtilities;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizencore.utilities.debugging.Debuggable;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
Expand All @@ -34,7 +37,8 @@
import org.bukkit.block.data.BlockData;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
Expand All @@ -43,6 +47,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class ItemTag implements ObjectTag, Adjustable, FlaggableObject {
Expand Down Expand Up @@ -682,28 +687,38 @@ public static void register() {
// If the item is a scripted item, returns a list of all recipe IDs created by the item script.
// Others, returns a list of all recipe IDs that the server lists as capable of crafting the item.
// Returns a list in the Namespace:Key format, for example "minecraft:gold_nugget".
// Optionally, specify a recipe type (CRAFTING, FURNACE, COOKING, BLASTING, SHAPED, SHAPELESS, SMOKING, STONECUTTING)
// Optionally, specify a recipe type (CRAFTING, FURNACE, COOKING, BLASTING, SHAPED, SHAPELESS, SMOKING, STONECUTTING, BREWING)
// to limit to just recipes of that type.
// Brewing recipes are only supported on Paper, and only custom ones are available.
// -->
tagProcessor.registerTag(ListTag.class, "recipe_ids", (attribute, object) -> {
String type = attribute.hasParam() ? CoreUtilities.toLowerCase(attribute.getParam()) : null;
ItemScriptContainer container = ItemScriptHelper.getItemScriptContainer(object.getItemStack());
ListTag list = new ListTag();
for (Recipe recipe : Bukkit.getRecipesFor(object.getItemStack())) {
if (!Utilities.isRecipeOfType(recipe, type)) {
continue;
Consumer<NamespacedKey> addRecipe = (recipe) -> {
if (CoreUtilities.equalsIgnoreCase(recipe.getNamespace(), "denizen")) {
if (container != ItemScriptHelper.recipeIdToItemScript.get(recipe.toString())) {
return;
}
}
else if (container != null) {
return;
}
if (recipe instanceof Keyed) {
NamespacedKey key = ((Keyed) recipe).getKey();
if (key.getNamespace().equalsIgnoreCase("denizen")) {
if (container != ItemScriptHelper.recipeIdToItemScript.get(key.toString())) {
continue;
}
list.add(recipe.toString());
};
if (type == null || !type.equals("brewing")) {
for (Recipe recipe : Bukkit.getRecipesFor(object.getItemStack())) {
if (recipe instanceof Keyed keyedRecipe && Utilities.isRecipeOfType(recipe, type)) {
addRecipe.accept(keyedRecipe.getKey());
}
else if (container != null) {
continue;
}
}
if (Denizen.supportsPaper && NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18) && (type == null || type.equals("brewing"))) {
for (Map.Entry<NamespacedKey, BrewingRecipe> entry : NMSHandler.itemHelper.getCustomBrewingRecipes().entrySet()) {
ItemStack result = entry.getValue().result;
if (object.getBukkitMaterial() == result.getType() && (object.getItemStack().getDurability() == -1 || object.getItemStack().getDurability() == result.getDurability())) {
addRecipe.accept(entry.getKey());
}
list.add(key.toString());
}
}
return list;
Expand Down
@@ -1,34 +1,38 @@
package com.denizenscript.denizen.tags.core;

import com.denizenscript.denizen.Denizen;
import com.denizenscript.denizen.events.BukkitScriptEvent;
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.npc.traits.AssignmentTrait;
import com.denizenscript.denizen.objects.*;
import com.denizenscript.denizen.scripts.commands.server.BossBarCommand;
import com.denizenscript.denizen.scripts.containers.core.AssignmentScriptContainer;
import com.denizenscript.denizen.scripts.containers.core.CommandScriptHelper;
import com.denizenscript.denizen.utilities.*;
import com.denizenscript.denizencore.objects.notable.NoteManager;
import com.denizenscript.denizencore.tags.core.UtilTagBase;
import com.denizenscript.denizencore.utilities.CoreConfiguration;
import com.denizenscript.denizencore.utilities.Deprecations;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizen.utilities.depends.Depends;
import com.denizenscript.denizen.utilities.inventory.BrewingRecipe;
import com.denizenscript.denizen.utilities.inventory.SlotHelper;
import com.denizenscript.denizencore.objects.*;
import com.denizenscript.denizen.Denizen;
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.npc.traits.AssignmentTrait;
import com.denizenscript.denizencore.objects.core.*;
import com.denizenscript.denizencore.scripts.commands.core.SQLCommand;
import com.denizenscript.denizencore.DenizenCore;
import com.denizenscript.denizencore.events.ScriptEvent;
import com.denizenscript.denizencore.objects.Mechanism;
import com.denizenscript.denizencore.objects.ObjectFetcher;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.*;
import com.denizenscript.denizencore.objects.notable.Notable;
import com.denizenscript.denizencore.objects.notable.NoteManager;
import com.denizenscript.denizencore.scripts.ScriptRegistry;
import com.denizenscript.denizencore.scripts.commands.core.SQLCommand;
import com.denizenscript.denizencore.scripts.containers.ScriptContainer;
import com.denizenscript.denizencore.tags.Attribute;
import com.denizenscript.denizencore.tags.ReplaceableTagEvent;
import com.denizenscript.denizencore.tags.TagManager;
import com.denizenscript.denizencore.tags.TagRunnable;
import com.denizenscript.denizencore.tags.core.UtilTagBase;
import com.denizenscript.denizencore.utilities.CoreConfiguration;
import com.denizenscript.denizencore.utilities.CoreUtilities;
import com.denizenscript.denizencore.utilities.Deprecations;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizencore.utilities.text.StringHolder;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.citizensnpcs.Citizens;
Expand Down Expand Up @@ -203,19 +207,27 @@ public void serverTag(ReplaceableTagEvent event) {
// @description
// Returns a list of all recipe IDs on the server.
// Returns a list in the Namespace:Key format, for example "minecraft:gold_nugget".
// Optionally, specify a recipe type (CRAFTING, FURNACE, COOKING, BLASTING, SHAPED, SHAPELESS, SMOKING, CAMPFIRE, STONECUTTING)
// Optionally, specify a recipe type (CRAFTING, FURNACE, COOKING, BLASTING, SHAPED, SHAPELESS, SMOKING, CAMPFIRE, STONECUTTING, BREWING)
// to limit to just recipes of that type.
// Brewing recipes are only supported on Paper, and only custom ones are available.
// Note: this will produce an error if all recipes of any one type have been removed from the server, due to an error in Spigot.
// -->
if (attribute.startsWith("recipe_ids") || attribute.startsWith("list_recipe_ids")) {
listDeprecateWarn(attribute);
String type = attribute.hasParam() ? CoreUtilities.toLowerCase(attribute.getParam()) : null;
ListTag list = new ListTag();
Iterator<Recipe> recipeIterator = Bukkit.recipeIterator();
while (recipeIterator.hasNext()) {
Recipe recipe = recipeIterator.next();
if (Utilities.isRecipeOfType(recipe, type) && recipe instanceof Keyed) {
list.add(((Keyed) recipe).getKey().toString());
if (type == null || !type.equals("brewing")) {
Iterator<Recipe> recipeIterator = Bukkit.recipeIterator();
while (recipeIterator.hasNext()) {
Recipe recipe = recipeIterator.next();
if (Utilities.isRecipeOfType(recipe, type) && recipe instanceof Keyed keyedRecipe) {
list.add(keyedRecipe.getKey().toString());
}
}
}
if (Denizen.supportsPaper && NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18) && (type == null || type.equals("brewing"))) {
for (NamespacedKey brewingRecipe : NMSHandler.itemHelper.getCustomBrewingRecipeIDs()) {
list.add(brewingRecipe.toString());
}
}
event.setReplacedObject(list.getObjectAttribute(attribute.fulfill(1)));
Expand All @@ -229,12 +241,15 @@ public void serverTag(ReplaceableTagEvent event) {
// Returns a list of the items used as input to the recipe within the input ID.
// This is formatted equivalently to the item script recipe input, with "material:" for non-exact matches, and a full ItemTag for exact matches.
// Note that this won't represent all recipes perfectly (primarily those with multiple input choices per slot).
// Brewing recipes are only supported on Paper, and only custom ones are available.
// For furnace-style recipes, this will return a list with only 1 item.
// For shaped recipes, this will include 'air' for slots that are part of the shape but don't require an item.
// -->
if (attribute.startsWith("recipe_items") && attribute.hasParam()) {
Recipe recipe = Bukkit.getRecipe(Utilities.parseNamespacedKey(attribute.getParam()));
if (recipe == null) {
NamespacedKey recipeKey = Utilities.parseNamespacedKey(attribute.getParam());
Recipe recipe = Bukkit.getRecipe(recipeKey);
BrewingRecipe brewingRecipe = Denizen.supportsPaper && NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18) ? NMSHandler.itemHelper.getCustomBrewingRecipe(recipeKey) : null;
if (recipe == null && brewingRecipe == null) {
return;
}
ListTag result = new ListTag();
Expand All @@ -251,20 +266,25 @@ public void serverTag(ReplaceableTagEvent event) {
}
}
};
if (recipe instanceof ShapedRecipe) {
for (String row : ((ShapedRecipe) recipe).getShape()) {
if (recipe instanceof ShapedRecipe shapedRecipe) {
Map<Character, RecipeChoice> choiceMap = shapedRecipe.getChoiceMap();
for (String row : shapedRecipe.getShape()) {
for (char column : row.toCharArray()) {
addChoice.accept(((ShapedRecipe) recipe).getChoiceMap().get(column));
addChoice.accept(choiceMap.get(column));
}
}
}
else if (recipe instanceof ShapelessRecipe) {
for (RecipeChoice choice : ((ShapelessRecipe) recipe).getChoiceList()) {
else if (recipe instanceof ShapelessRecipe shapelessRecipe) {
for (RecipeChoice choice : shapelessRecipe.getChoiceList()) {
addChoice.accept(choice);
}
}
else if (recipe instanceof CookingRecipe<?>) {
addChoice.accept(((CookingRecipe) recipe).getInputChoice());
else if (recipe instanceof CookingRecipe<?> cookingRecipe) {
addChoice.accept(cookingRecipe.getInputChoice());
}
else if (brewingRecipe != null) {
addChoice.accept(brewingRecipe.ingredient);
addChoice.accept(brewingRecipe.input);
}
event.setReplacedObject(result.getObjectAttribute(attribute.fulfill(1)));
return;
Expand All @@ -278,10 +298,10 @@ else if (recipe instanceof CookingRecipe<?>) {
// -->
if (attribute.startsWith("recipe_shape") && attribute.hasParam()) {
Recipe recipe = Bukkit.getRecipe(Utilities.parseNamespacedKey(attribute.getParam()));
if (!(recipe instanceof ShapedRecipe)) {
if (!(recipe instanceof ShapedRecipe shapedRecipe)) {
return;
}
String[] shape = ((ShapedRecipe) recipe).getShape();
String[] shape = shapedRecipe.getShape();
event.setReplacedObject(new ElementTag(shape[0].length() + "x" + shape.length).getObjectAttribute(attribute.fulfill(1)));
return;
}
Expand All @@ -291,11 +311,16 @@ else if (recipe instanceof CookingRecipe<?>) {
// @returns ElementTag
// @description
// Returns the type of recipe that the given recipe ID is.
// Will be one of FURNACE, BLASTING, SHAPED, SHAPELESS, SMOKING, CAMPFIRE, STONECUTTING, SMITHING.
// Will be one of FURNACE, BLASTING, SHAPED, SHAPELESS, SMOKING, CAMPFIRE, STONECUTTING, SMITHING, BREWING.
// Brewing recipes are only supported on Paper, and only custom ones are available.
// -->
if (attribute.startsWith("recipe_type") && attribute.hasParam()) {
Recipe recipe = Bukkit.getRecipe(Utilities.parseNamespacedKey(attribute.getParam()));
NamespacedKey recipeKey = Utilities.parseNamespacedKey(attribute.getParam());
Recipe recipe = Bukkit.getRecipe(recipeKey);
if (recipe == null) {
if (Denizen.supportsPaper && NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18) && NMSHandler.itemHelper.getCustomBrewingRecipeIDs().contains(recipeKey)) {
event.setReplacedObject(new ElementTag("brewing").getObjectAttribute(attribute.fulfill(1)));
}
return;
}
event.setReplacedObject(new ElementTag(Utilities.getRecipeType(recipe)).getObjectAttribute(attribute.fulfill(1)));
Expand All @@ -307,10 +332,18 @@ else if (recipe instanceof CookingRecipe<?>) {
// @returns ItemTag
// @description
// Returns the item that a recipe will create when crafted.
// Brewing recipes are only supported on Paper, and only custom ones are available.
// -->
if (attribute.startsWith("recipe_result") && attribute.hasParam()) {
Recipe recipe = Bukkit.getRecipe(Utilities.parseNamespacedKey(attribute.getParam()));
NamespacedKey recipeKey = Utilities.parseNamespacedKey(attribute.getParam());
Recipe recipe = Bukkit.getRecipe(recipeKey);
if (recipe == null) {
if (Denizen.supportsPaper && NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) {
BrewingRecipe brewingRecipe = NMSHandler.itemHelper.getCustomBrewingRecipe(recipeKey);
if (brewingRecipe != null) {
event.setReplacedObject(new ItemTag(brewingRecipe.result).getObjectAttribute(attribute.fulfill(1)));
}
}
return;
}
event.setReplacedObject(new ItemTag(recipe.getResult()).getObjectAttribute(attribute.fulfill(1)));
Expand Down
@@ -0,0 +1,17 @@
package com.denizenscript.denizen.utilities.inventory;

import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.RecipeChoice;

public class BrewingRecipe {

public RecipeChoice input;
public RecipeChoice ingredient;
public ItemStack result;

public BrewingRecipe(RecipeChoice ingredient, RecipeChoice input, ItemStack result) {
this.ingredient = ingredient;
this.input = input;
this.result = result;
}
}

0 comments on commit 1349bf6

Please sign in to comment.