From 2b18331dd77f01799c851a862d208cdf7cc77b5e Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:19:23 -0400 Subject: [PATCH 01/20] Starter Commit --- .../effects/EffRegisterRecipeValues.java | 123 +++++++++++++++ .../skript/sections/SecRegisterRecipe.java | 144 ++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java create mode 100644 src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java diff --git a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java new file mode 100644 index 00000000000..57045f698b9 --- /dev/null +++ b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java @@ -0,0 +1,123 @@ +package ch.njol.skript.effects; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.lang.Effect; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.sections.SecRegisterRecipe; +import ch.njol.util.Kleenean; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.Nullable; + +public class EffRegisterRecipeValues extends Effect { + + enum RecipeValues { + PATTERNS("set [the] recipe pattern[s] to %-strings%", "recipe patterns"), + FIRSTROW("set [the] recipe pattern[s] (first|1st) row to %-string%", "recipe pattern first row"), + SECONDROW("set [the] recipe pattern[s] (second|2nd) row to %-string%", "recipe pattern second row"), + THIRDROW("set [the] recipe pattern[s] (third|3rd) row to %-string%", "recipe pattern third row"), + ITEMSET("set [the] recipe char[acter] %string% to %itemstack/itemtype%", "recipe character"), + RESULT("set [the] recipe result to %itemstack/itemtype%", "recipe result"); + + private String pattern, toString; + + RecipeValues(String pattern, String toString) { + this.pattern = pattern; + this.toString = toString; + } + } + + private static RecipeValues[] recipeValues = RecipeValues.values(); + + static { + String[] patterns = new String[recipeValues.length]; + for (RecipeValues value : recipeValues) { + patterns[value.ordinal()] = value.pattern; + } + Skript.registerEffect(EffRegisterRecipeValues.class, patterns); + } + + private RecipeValues selectedValue; + private Expression stringValues; + private @Nullable Expression itemValues; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + selectedValue = recipeValues[matchedPattern]; + if (!getParser().isCurrentEvent(SecRegisterRecipe.RegisterRecipeEvent.class)) { + Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); + return false; + } + + if (selectedValue == RecipeValues.ITEMSET) { + stringValues = (Expression) exprs[0]; + itemValues = exprs[1]; + } else if (selectedValue == RecipeValues.RESULT) { + itemValues = exprs[0]; + } else { + stringValues = (Expression) exprs[0]; + } + return true; + } + + @Override + protected void execute(Event event) { + if (!(event instanceof SecRegisterRecipe.RegisterRecipeEvent recipeEvent)) + return; + + switch (selectedValue) { + case PATTERNS -> { + for (String string : stringValues.getArray(event)) { + if (string.length() > 3) { + Skript.error("Recipe pattern can only contain up to 3 characters."); + return; + } + } + recipeEvent.setRecipePatterns(stringValues.getArray(event), null); + } + case FIRSTROW, SECONDROW, THIRDROW -> { + String string = stringValues.getSingle(event); + if (string.length() > 3) { + Skript.error("Recipe pattern can only contain up to 3 characters."); + return; + } + recipeEvent.setRecipePatterns(new String[]{string}, selectedValue.ordinal() - 1); + } + case ITEMSET -> { + String string = stringValues.getSingle(event); + if (string.length() > 1) { + Skript.error("You can only set one character at a time to an item."); + return; + } + Character character = string.charAt(0); + Object item = itemValues.getSingle(event); + if (item instanceof ItemStack itemStack) { + recipeEvent.setIngredients(character, itemStack); + } else if (item instanceof ItemType itemType) { + ItemStack stack = new ItemStack(itemType.getMaterial()); + stack.setItemMeta(itemType.getItemMeta()); + recipeEvent.setIngredients(character, stack); + } + } + case RESULT -> { + Object item = itemValues.getSingle(event); + if (item instanceof ItemStack itemStack) { + recipeEvent.setResultItem(itemStack); + } else if (item instanceof ItemType itemType) { + ItemStack stack = new ItemStack(itemType.getMaterial()); + stack.setItemMeta(itemType.getItemMeta()); + recipeEvent.setResultItem(stack); + } + } + } + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return null; + } +} diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java new file mode 100644 index 00000000000..226167a90af --- /dev/null +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -0,0 +1,144 @@ +package ch.njol.skript.sections; + +import ch.njol.skript.Skript; +import ch.njol.skript.config.SectionNode; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.Section; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.Trigger; +import ch.njol.skript.lang.TriggerItem; +import ch.njol.skript.variables.Variables; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.ShapedRecipe; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +public class SecRegisterRecipe extends Section { + + private static final boolean SUPPORT_SHAPED_ITEMSTACK = Skript.methodExists(ShapedRecipe.class, "setIngredient", Character.class, ItemStack.class); + + public static class RegisterRecipeEvent extends Event { + private String[] recipePatterns = new String[3]; + private Map ingredients = new HashMap<>(); + private ItemStack resultItem; + + public RegisterRecipeEvent() {} + + public void setRecipePatterns(String @Nullable [] pattern, @Nullable Integer row) { + if (row != null) { + recipePatterns[row] = pattern[0]; + } else { + recipePatterns = pattern; + } + } + + public void setIngredients(Character character, ItemStack item) { + ingredients.put(character, item); + } + + public void setResultItem(ItemStack item) { + resultItem = item; + } + + public String[] getRecipePatterns() { + return recipePatterns; + } + + public Map getIngredients() { + return ingredients; + } + + public ItemStack getResultItem() { + return resultItem; + } + + @Override + public @NotNull HandlerList getHandlers() { + throw new IllegalStateException(); + } + } + + static { + Skript.registerSection(SecRegisterRecipe.class, + "(register|create) [a] [new] shaped recipe with [the] name[space[key]] %string%"); + } + + private Expression providedName; + private Trigger trigger; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult, SectionNode sectionNode, List triggerItems) { + providedName = (Expression) exprs[0]; + + AtomicBoolean delayed = new AtomicBoolean(false); + Runnable afterLoading = () -> delayed.set(!getParser().getHasDelayBefore().isFalse()); + trigger = loadCode(sectionNode, "register recipe", afterLoading, RegisterRecipeEvent.class); + if (delayed.get()) { + Skript.error("Delays cannot be used within a 'register recipe' section."); + return false; + } + + return true; + } + + @Override + protected @Nullable TriggerItem walk(Event event) { + String name = providedName.getSingle(event); + NamespacedKey namespacedKey = NamespacedKey.fromString(name, Skript.getInstance()); + if (Bukkit.getRecipe(namespacedKey) != null) { + Skript.error("The namespace '" + name + "' is already registered."); + return null; + } + RegisterRecipeEvent recipeEvent = new RegisterRecipeEvent(); + Variables.setLocalVariables(recipeEvent, Variables.copyLocalVariables(event)); + TriggerItem.walk(trigger, recipeEvent); + Variables.setLocalVariables(event, Variables.copyLocalVariables(recipeEvent)); + Variables.removeLocals(recipeEvent); + + String[] patterns = recipeEvent.getRecipePatterns(); + Map ingredients = recipeEvent.getIngredients(); + for (String string : patterns) { + for (Character character : string.toCharArray()) { + if (ingredients.get(character) == null) { + ingredients.put(character, new ItemStack(Material.AIR)); + } + } + } + ItemStack result = recipeEvent.getResultItem(); + if (result == null) { + Skript.error("Registering a recipe requires a resulting item"); + return null; + } + ShapedRecipe shapedRecipe = new ShapedRecipe(namespacedKey, result); + shapedRecipe.shape(patterns); + for (Character character : ingredients.keySet()) { + if (SUPPORT_SHAPED_ITEMSTACK) { + shapedRecipe.setIngredient(character, ingredients.get(character)); + } else { + shapedRecipe.setIngredient(character, ingredients.get(character).getType()); + } + } + Bukkit.addRecipe(shapedRecipe); + + return super.walk(event, false); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return null; + } + +} From 53014013232f5561fde5f26ceb0c08b6477fb26f Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:03:21 -0400 Subject: [PATCH 02/20] Shapeless Addition --- .../effects/EffRegisterRecipeValues.java | 85 ++++++------ .../skript/sections/SecRegisterRecipe.java | 131 ++++++++++++------ 2 files changed, 132 insertions(+), 84 deletions(-) diff --git a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java index 57045f698b9..0e5180438c5 100644 --- a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java +++ b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java @@ -7,19 +7,22 @@ import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.sections.SecRegisterRecipe; import ch.njol.util.Kleenean; +import ch.njol.util.Predicate; +import org.bukkit.Material; import org.bukkit.event.Event; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; + public class EffRegisterRecipeValues extends Effect { enum RecipeValues { - PATTERNS("set [the] recipe pattern[s] to %-strings%", "recipe patterns"), - FIRSTROW("set [the] recipe pattern[s] (first|1st) row to %-string%", "recipe pattern first row"), - SECONDROW("set [the] recipe pattern[s] (second|2nd) row to %-string%", "recipe pattern second row"), - THIRDROW("set [the] recipe pattern[s] (third|3rd) row to %-string%", "recipe pattern third row"), - ITEMSET("set [the] recipe char[acter] %string% to %itemstack/itemtype%", "recipe character"), + INGREDIENTS("set [the] recipe ingredient[s] to %itemstacks/itemtypes%", "recipe ingredients"), + FIRSTROW("set [the] recipe ingredients of (first|1st) row to %itemstacks/itemtypes%", "recipe pattern first row"), + SECONDROW("set [the] recipe ingredients of (second|2nd) row to %itemstacks/itemtypes%", "recipe pattern second row"), + THIRDROW("set [the] recipe ingredients of (third|3rd) row to %itemstacks/itemtypes%", "recipe pattern third row"), RESULT("set [the] recipe result to %itemstack/itemtype%", "recipe result"); private String pattern, toString; @@ -41,26 +44,16 @@ enum RecipeValues { } private RecipeValues selectedValue; - private Expression stringValues; - private @Nullable Expression itemValues; + private Expression itemValues; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { selectedValue = recipeValues[matchedPattern]; if (!getParser().isCurrentEvent(SecRegisterRecipe.RegisterRecipeEvent.class)) { Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); return false; } - - if (selectedValue == RecipeValues.ITEMSET) { - stringValues = (Expression) exprs[0]; - itemValues = exprs[1]; - } else if (selectedValue == RecipeValues.RESULT) { - itemValues = exprs[0]; - } else { - stringValues = (Expression) exprs[0]; - } + itemValues = exprs[0]; return true; } @@ -70,37 +63,45 @@ protected void execute(Event event) { return; switch (selectedValue) { - case PATTERNS -> { - for (String string : stringValues.getArray(event)) { - if (string.length() > 3) { - Skript.error("Recipe pattern can only contain up to 3 characters."); - return; + case INGREDIENTS -> { + Object[] items = itemValues.getArray(event); + if (items.length > recipeEvent.getMaxIngredients()) { + Skript.adminBroadcast("You can only provide up to " + recipeEvent.getMaxIngredients() + + " items when setting the ingredients for a '" + recipeEvent.getRecipeType() + "' recipe."); + return; + } + for (int i = 0; i < items.length; i++) { + Object thisItem = items[i]; + if (thisItem instanceof ItemStack itemStack) { + recipeEvent.setIngredients(i, itemStack); + } else if (thisItem instanceof ItemType itemType) { + ItemStack stack = new ItemStack(itemType.getMaterial()); + stack.setItemMeta(itemType.getItemMeta()); + recipeEvent.setIngredients(i, stack); } } - recipeEvent.setRecipePatterns(stringValues.getArray(event), null); } case FIRSTROW, SECONDROW, THIRDROW -> { - String string = stringValues.getSingle(event); - if (string.length() > 3) { - Skript.error("Recipe pattern can only contain up to 3 characters."); - return; - } - recipeEvent.setRecipePatterns(new String[]{string}, selectedValue.ordinal() - 1); - } - case ITEMSET -> { - String string = stringValues.getSingle(event); - if (string.length() > 1) { - Skript.error("You can only set one character at a time to an item."); + Object[] items = itemValues.getArray(event); + if (items.length > recipeEvent.getMaxRowIngredients()) { + if (recipeEvent.getMaxRowIngredients() == 0) { + Skript.error("You can not use '" + selectedValue.toString + "' when registering a '" + recipeEvent.getRecipeType() + "' recipe."); + } else { + Skript.error("You can only provide up to " + recipeEvent.getMaxRowIngredients() + + " items when setting the ingredients of a row for a '" + recipeEvent.getRecipeType() + "' recipe."); + } return; } - Character character = string.charAt(0); - Object item = itemValues.getSingle(event); - if (item instanceof ItemStack itemStack) { - recipeEvent.setIngredients(character, itemStack); - } else if (item instanceof ItemType itemType) { - ItemStack stack = new ItemStack(itemType.getMaterial()); - stack.setItemMeta(itemType.getItemMeta()); - recipeEvent.setIngredients(character, stack); + for (int i = 0; i < items.length; i++) { + Object thisItem = items[i]; + int placement = (3 * (selectedValue.ordinal() - 1)) + i; + if (thisItem instanceof ItemStack itemStack) { + recipeEvent.setIngredients(placement, itemStack); + } else if (thisItem instanceof ItemType itemType) { + ItemStack stack = new ItemStack(itemType.getMaterial()); + stack.setItemMeta(itemType.getItemMeta()); + recipeEvent.setIngredients(placement, stack); + } } } case RESULT -> { diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 226167a90af..32abaacd918 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -16,47 +16,56 @@ import org.bukkit.event.HandlerList; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ShapedRecipe; +import org.bukkit.inventory.ShapelessRecipe; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; public class SecRegisterRecipe extends Section { private static final boolean SUPPORT_SHAPED_ITEMSTACK = Skript.methodExists(ShapedRecipe.class, "setIngredient", Character.class, ItemStack.class); + private static final boolean SUPPORT_SHAPELESS_ITEMSTACK = Skript.methodExists(ShapelessRecipe.class, "addIngredient", ItemStack.class); + + enum RecipeTypes { + SHAPED("shaped", 9, 3, 2, "shaped"), + SHAPELESS("shapeless", 9, 0, 2, "shapeless"); + + + private String pattern, toString; + private int maxIngredients, maxRowIngredients, minIngredients; + + RecipeTypes(String pattern, int maxIngredients, int maxRowIngredients, int minIngredients, String toString) { + this.pattern = pattern; + this.maxIngredients = maxIngredients; + this.maxRowIngredients = maxRowIngredients; + this.minIngredients = minIngredients; + this.toString = toString; + } + } + + private static final RecipeTypes[] recipeTypes = RecipeTypes.values(); public static class RegisterRecipeEvent extends Event { - private String[] recipePatterns = new String[3]; - private Map ingredients = new HashMap<>(); private ItemStack resultItem; + private ItemStack[] ingredients = new ItemStack[9]; + private RecipeTypes recipeType; - public RegisterRecipeEvent() {} - - public void setRecipePatterns(String @Nullable [] pattern, @Nullable Integer row) { - if (row != null) { - recipePatterns[row] = pattern[0]; - } else { - recipePatterns = pattern; - } + @SuppressWarnings("ClassEscapesDefinedScope") + public RegisterRecipeEvent(RecipeTypes recipeType) { + this.recipeType = recipeType; } - public void setIngredients(Character character, ItemStack item) { - ingredients.put(character, item); + public void setIngredients(int placement, ItemStack item) { + ingredients[placement] = item; } public void setResultItem(ItemStack item) { resultItem = item; } - public String[] getRecipePatterns() { - return recipePatterns; - } - - public Map getIngredients() { + public ItemStack[] getIngredients() { return ingredients; } @@ -64,6 +73,18 @@ public ItemStack getResultItem() { return resultItem; } + public RecipeTypes getRecipeType() { + return recipeType; + } + + public int getMaxIngredients() { + return recipeType.maxIngredients; + } + + public int getMaxRowIngredients() { + return recipeType.maxRowIngredients; + } + @Override public @NotNull HandlerList getHandlers() { throw new IllegalStateException(); @@ -71,18 +92,22 @@ public ItemStack getResultItem() { } static { - Skript.registerSection(SecRegisterRecipe.class, - "(register|create) [a] [new] shaped recipe with [the] name[space[key]] %string%"); + String[] patterns = new String[recipeTypes.length]; + for (RecipeTypes type : recipeTypes) { + patterns[type.ordinal()] = "(register|create) [a] [new] " + type.pattern + " recipe with [the] name[space[key]] %string%"; + } + Skript.registerSection(SecRegisterRecipe.class, patterns); } + private RecipeTypes recipeType; private Expression providedName; private Trigger trigger; @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult, SectionNode sectionNode, List triggerItems) { + recipeType = recipeTypes[matchedPattern]; providedName = (Expression) exprs[0]; - AtomicBoolean delayed = new AtomicBoolean(false); Runnable afterLoading = () -> delayed.set(!getParser().getHasDelayBefore().isFalse()); trigger = loadCode(sectionNode, "register recipe", afterLoading, RegisterRecipeEvent.class); @@ -102,38 +127,60 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye Skript.error("The namespace '" + name + "' is already registered."); return null; } - RegisterRecipeEvent recipeEvent = new RegisterRecipeEvent(); + RegisterRecipeEvent recipeEvent = new RegisterRecipeEvent(recipeType); Variables.setLocalVariables(recipeEvent, Variables.copyLocalVariables(event)); TriggerItem.walk(trigger, recipeEvent); Variables.setLocalVariables(event, Variables.copyLocalVariables(recipeEvent)); Variables.removeLocals(recipeEvent); - String[] patterns = recipeEvent.getRecipePatterns(); - Map ingredients = recipeEvent.getIngredients(); - for (String string : patterns) { - for (Character character : string.toCharArray()) { - if (ingredients.get(character) == null) { - ingredients.put(character, new ItemStack(Material.AIR)); - } - } - } ItemStack result = recipeEvent.getResultItem(); if (result == null) { Skript.error("Registering a recipe requires a resulting item"); return null; } - ShapedRecipe shapedRecipe = new ShapedRecipe(namespacedKey, result); - shapedRecipe.shape(patterns); - for (Character character : ingredients.keySet()) { - if (SUPPORT_SHAPED_ITEMSTACK) { - shapedRecipe.setIngredient(character, ingredients.get(character)); - } else { - shapedRecipe.setIngredient(character, ingredients.get(character).getType()); + ItemStack[] ingredients = recipeEvent.getIngredients(); + if (ingredients.length < recipeType.minIngredients || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < recipeType.minIngredients) { + Skript.error("You must have at least " + recipeType.minIngredients + " ingredients when registering a '" + recipeType.toString + "' recipe."); + return null; + } + switch (recipeType) { + case SHAPED -> createShapedRecipe(namespacedKey, result, ingredients); + case SHAPELESS -> createShapelessRecipe(namespacedKey, result, ingredients); + } + + return super.walk(event, false); + } + + private void createShapedRecipe(NamespacedKey key, ItemStack result, ItemStack[] ingredients) { + ShapedRecipe shapedRecipe = new ShapedRecipe(key, result); + Character[] characters = new Character[]{'a','b','c','d','e','f','g','h','i'}; + shapedRecipe.shape("abc","def","ghi"); + for (int i = 0; i < ingredients.length; i++) { + ItemStack thisItem = ingredients[i]; + if (thisItem != null) { + if (SUPPORT_SHAPED_ITEMSTACK) { + shapedRecipe.setIngredient(characters[i], thisItem); + } else { + shapedRecipe.setIngredient(characters[i], thisItem.getType()); + } } } Bukkit.addRecipe(shapedRecipe); + } - return super.walk(event, false); + private void createShapelessRecipe(NamespacedKey key, ItemStack result, ItemStack[] ingredients) { + ShapelessRecipe shapelessRecipe = new ShapelessRecipe(key, result); + for (int i = 0; i < ingredients.length; i++) { + ItemStack thisItem = ingredients[i]; + if (thisItem != null) { + if (SUPPORT_SHAPED_ITEMSTACK) { + shapelessRecipe.addIngredient(thisItem); + } else { + shapelessRecipe.addIngredient(thisItem.getAmount(), thisItem.getType()); + } + } + } + Bukkit.addRecipe(shapelessRecipe); } @Override From 5aaf2a63463c859cff356d2cbf297a2f7477a105 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:58:20 -0400 Subject: [PATCH 03/20] Testing Stuff --- .../effects/EffCraftingRecipeValues.java | 135 ++++++++++ .../effects/EffRegisterRecipeValues.java | 77 ++---- .../skript/sections/SecRegisterRecipe.java | 119 ++++----- .../njol/skript/util/RegisterRecipeEvent.java | 247 ++++++++++++++++++ 4 files changed, 462 insertions(+), 116 deletions(-) create mode 100644 src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java create mode 100644 src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java diff --git a/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java new file mode 100644 index 00000000000..fd60ad67f0b --- /dev/null +++ b/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java @@ -0,0 +1,135 @@ +package ch.njol.skript.effects; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.config.Node; +import ch.njol.skript.lang.Effect; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.skript.util.RegisterRecipeEvent.CraftingEventRecipe.*; +import ch.njol.util.Kleenean; +import org.bukkit.Material; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +public class EffCraftingRecipeValues extends Effect { + + enum RecipeValues { + INGREDIENTS("set [the] recipe ingredients to %itemstacks/itemtypes%", "recipe ingredients", + CraftingEventRecipe.class, "This can only be used when registering a Crafting, Shaped, or Shapeless Recipe"), + FIRSTROW("set [the] recipe ingredients of (first|1st) row to %itemstacks/itemtypes%", "recipe ingredients first row", + ShapedRecipeEvent.class, "This can only be used when registering a Shaped Recipe."), + SECONDROW("set [the] recipe ingredients of (second|2nd) row to %itemstacks/itemtypes%", "recipe ingredients second row", + ShapedRecipeEvent.class, "This can only be used when registering a Shaped Recipe."), + THIRDROW("set [the] recipe ingredients of (third|3rd) row to %itemstacks/itemtypes%", "recipe ingredients third row", + ShapedRecipeEvent.class, "This can only be used when registering a Shaped Recipe."); + + private String pattern, toString, error; + private Class eventClass; + + RecipeValues(String pattern, String toString, Class eventClass, String error) { + this.pattern = pattern; + this.toString = toString; + this.eventClass = eventClass; + this.error = error; + } + } + + private static RecipeValues[] recipeValues = RecipeValues.values(); + + static { + String[] patterns = new String[recipeValues.length]; + for (RecipeValues value : recipeValues) { + patterns[value.ordinal()] = value.pattern; + } + Skript.registerEffect(EffCraftingRecipeValues.class, patterns); + } + + private RecipeValues selectedValue; + private Expression itemValues; + private Node thisNode; + private String thisScript; + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + selectedValue = recipeValues[matchedPattern]; + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { + Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); + return false; + } + if (!getParser().isCurrentEvent(selectedValue.eventClass)) { + Skript.error(selectedValue.error); + return false; + } + itemValues = exprs[0]; + thisNode = getParser().getNode(); + thisScript = getParser().getCurrentScript().getConfig().getFileName(); + return true; + } + + @Override + protected void execute(Event event) { + if (!(event instanceof CraftingEventRecipe recipeEvent)) + return; + + switch (selectedValue) { + case INGREDIENTS -> { + Object[] items = itemValues.getArray(event); + if (items.length > recipeEvent.getMaxIngredients()) { + customError("You can only provide up to " + recipeEvent.getMaxIngredients() + + " items when setting the ingredients for a '" + recipeEvent.getRecipeName() + "' recipe."); + recipeEvent.setErrorInEffect(); + return; + } + for (int i = 0; i < items.length; i++) { + Object thisItem = items[i]; + if (thisItem instanceof ItemStack itemStack && itemStack.getType() != Material.AIR) { + recipeEvent.setIngredients(i, itemStack); + } else if (thisItem instanceof ItemType itemType && itemType.getMaterial() != Material.AIR) { + ItemStack stack = new ItemStack(itemType.getMaterial()); + stack.setItemMeta(itemType.getItemMeta()); + recipeEvent.setIngredients(i, stack); + } + } + } + case FIRSTROW, SECONDROW, THIRDROW -> { + Object[] items = itemValues.getArray(event); + if (items.length > recipeEvent.getMaxRowIngredients()) { + if (recipeEvent.getMaxRowIngredients() == 0) { + customError("You can not use '" + selectedValue.toString + "' when registering a '" + recipeEvent.getRecipeName() + "' recipe."); + } else { + customError("You can only provide up to " + recipeEvent.getMaxRowIngredients() + + " items when setting the ingredients of a row for a '" + recipeEvent.getRecipeName() + "' recipe."); + } + recipeEvent.setErrorInEffect(); + return; + } + for (int i = 0; i < items.length; i++) { + Object thisItem = items[i]; + int placement = (3 * (selectedValue.ordinal() - 1)) + i; + if (thisItem instanceof ItemStack itemStack && itemStack.getType() != Material.AIR) { + recipeEvent.setIngredients(placement, itemStack); + } else if (thisItem instanceof ItemType itemType && itemType.getMaterial() != Material.AIR) { + ItemStack stack = new ItemStack(itemType.getMaterial()); + stack.setItemMeta(itemType.getItemMeta()); + recipeEvent.setIngredients(placement, stack); + } + } + } + } + } + + private void customError(String message) { + Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return null; + } +} diff --git a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java index 0e5180438c5..75eef2ec5b9 100644 --- a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java +++ b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java @@ -2,16 +2,17 @@ import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.config.Node; import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.sections.SecRegisterRecipe; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.skript.util.RegisterRecipeEvent.CraftingEventRecipe.*; import ch.njol.util.Kleenean; -import ch.njol.util.Predicate; import org.bukkit.Material; import org.bukkit.event.Event; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -19,17 +20,15 @@ public class EffRegisterRecipeValues extends Effect { enum RecipeValues { - INGREDIENTS("set [the] recipe ingredient[s] to %itemstacks/itemtypes%", "recipe ingredients"), - FIRSTROW("set [the] recipe ingredients of (first|1st) row to %itemstacks/itemtypes%", "recipe pattern first row"), - SECONDROW("set [the] recipe ingredients of (second|2nd) row to %itemstacks/itemtypes%", "recipe pattern second row"), - THIRDROW("set [the] recipe ingredients of (third|3rd) row to %itemstacks/itemtypes%", "recipe pattern third row"), - RESULT("set [the] recipe result to %itemstack/itemtype%", "recipe result"); + RESULT("set [the] recipe result to %itemstack/itemtype%", "recipe result", RegisterRecipeEvent.class); private String pattern, toString; + private Class eventClass; - RecipeValues(String pattern, String toString) { + RecipeValues(String pattern, String toString, Class eventClass) { this.pattern = pattern; this.toString = toString; + this.eventClass = eventClass; } } @@ -45,78 +44,48 @@ enum RecipeValues { private RecipeValues selectedValue; private Expression itemValues; + private Node thisNode; + private String thisScript; @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { selectedValue = recipeValues[matchedPattern]; - if (!getParser().isCurrentEvent(SecRegisterRecipe.RegisterRecipeEvent.class)) { + if (!getParser().isCurrentEvent(selectedValue.eventClass)) { Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); return false; } itemValues = exprs[0]; + thisNode = getParser().getNode(); + thisScript = getParser().getCurrentScript().getConfig().getFileName(); return true; } @Override protected void execute(Event event) { - if (!(event instanceof SecRegisterRecipe.RegisterRecipeEvent recipeEvent)) + if (!(event instanceof RegisterRecipeEvent recipeEvent)) return; switch (selectedValue) { - case INGREDIENTS -> { - Object[] items = itemValues.getArray(event); - if (items.length > recipeEvent.getMaxIngredients()) { - Skript.adminBroadcast("You can only provide up to " + recipeEvent.getMaxIngredients() + - " items when setting the ingredients for a '" + recipeEvent.getRecipeType() + "' recipe."); - return; - } - for (int i = 0; i < items.length; i++) { - Object thisItem = items[i]; - if (thisItem instanceof ItemStack itemStack) { - recipeEvent.setIngredients(i, itemStack); - } else if (thisItem instanceof ItemType itemType) { - ItemStack stack = new ItemStack(itemType.getMaterial()); - stack.setItemMeta(itemType.getItemMeta()); - recipeEvent.setIngredients(i, stack); - } - } - } - case FIRSTROW, SECONDROW, THIRDROW -> { - Object[] items = itemValues.getArray(event); - if (items.length > recipeEvent.getMaxRowIngredients()) { - if (recipeEvent.getMaxRowIngredients() == 0) { - Skript.error("You can not use '" + selectedValue.toString + "' when registering a '" + recipeEvent.getRecipeType() + "' recipe."); - } else { - Skript.error("You can only provide up to " + recipeEvent.getMaxRowIngredients() + - " items when setting the ingredients of a row for a '" + recipeEvent.getRecipeType() + "' recipe."); - } - return; - } - for (int i = 0; i < items.length; i++) { - Object thisItem = items[i]; - int placement = (3 * (selectedValue.ordinal() - 1)) + i; - if (thisItem instanceof ItemStack itemStack) { - recipeEvent.setIngredients(placement, itemStack); - } else if (thisItem instanceof ItemType itemType) { - ItemStack stack = new ItemStack(itemType.getMaterial()); - stack.setItemMeta(itemType.getItemMeta()); - recipeEvent.setIngredients(placement, stack); - } - } - } case RESULT -> { Object item = itemValues.getSingle(event); - if (item instanceof ItemStack itemStack) { + if (item instanceof ItemStack itemStack && itemStack.getType() != Material.AIR) { recipeEvent.setResultItem(itemStack); - } else if (item instanceof ItemType itemType) { + } else if (item instanceof ItemType itemType && itemType.getMaterial() != Material.AIR) { ItemStack stack = new ItemStack(itemType.getMaterial()); stack.setItemMeta(itemType.getItemMeta()); recipeEvent.setResultItem(stack); + } else { + customError("The result item can not be null and/or air."); + recipeEvent.setErrorInEffect(); } } } } + private void customError(String message) { + Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); + } + @Override public String toString(@Nullable Event event, boolean debug) { return null; diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 32abaacd918..212cbfcfe3d 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -1,23 +1,24 @@ package ch.njol.skript.sections; import ch.njol.skript.Skript; +import ch.njol.skript.config.Node; import ch.njol.skript.config.SectionNode; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.Section; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.Trigger; import ch.njol.skript.lang.TriggerItem; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.skript.util.RegisterRecipeEvent.CraftingEventRecipe.*; import ch.njol.skript.variables.Variables; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapelessRecipe; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -28,69 +29,43 @@ public class SecRegisterRecipe extends Section { private static final boolean SUPPORT_SHAPED_ITEMSTACK = Skript.methodExists(ShapedRecipe.class, "setIngredient", Character.class, ItemStack.class); private static final boolean SUPPORT_SHAPELESS_ITEMSTACK = Skript.methodExists(ShapelessRecipe.class, "addIngredient", ItemStack.class); - enum RecipeTypes { - SHAPED("shaped", 9, 3, 2, "shaped"), - SHAPELESS("shapeless", 9, 0, 2, "shapeless"); + public enum RecipeTypes { + SHAPED("shaped", 9, 3, 2, "shaped", ShapedRecipeEvent.class), + SHAPELESS("shapeless", 9, 0, 2, "shapeless", ShapelessRecipeEvent.class); private String pattern, toString; private int maxIngredients, maxRowIngredients, minIngredients; + private Class eventClass; - RecipeTypes(String pattern, int maxIngredients, int maxRowIngredients, int minIngredients, String toString) { + RecipeTypes(String pattern, int maxIngredients, int maxRowIngredients, int minIngredients, String toString, Class eventClass) { this.pattern = pattern; this.maxIngredients = maxIngredients; this.maxRowIngredients = maxRowIngredients; this.minIngredients = minIngredients; this.toString = toString; - } - } - - private static final RecipeTypes[] recipeTypes = RecipeTypes.values(); - - public static class RegisterRecipeEvent extends Event { - private ItemStack resultItem; - private ItemStack[] ingredients = new ItemStack[9]; - private RecipeTypes recipeType; - - @SuppressWarnings("ClassEscapesDefinedScope") - public RegisterRecipeEvent(RecipeTypes recipeType) { - this.recipeType = recipeType; - } - - public void setIngredients(int placement, ItemStack item) { - ingredients[placement] = item; + this.eventClass = eventClass; } - public void setResultItem(ItemStack item) { - resultItem = item; - } - - public ItemStack[] getIngredients() { - return ingredients; - } - - public ItemStack getResultItem() { - return resultItem; - } - - public RecipeTypes getRecipeType() { - return recipeType; + public String getToString() { + return toString; } public int getMaxIngredients() { - return recipeType.maxIngredients; + return maxIngredients; } public int getMaxRowIngredients() { - return recipeType.maxRowIngredients; + return maxRowIngredients; } - @Override - public @NotNull HandlerList getHandlers() { - throw new IllegalStateException(); + public int getMinIngredients() { + return minIngredients; } } + private static final RecipeTypes[] recipeTypes = RecipeTypes.values(); + static { String[] patterns = new String[recipeTypes.length]; for (RecipeTypes type : recipeTypes) { @@ -102,6 +77,8 @@ public int getMaxRowIngredients() { private RecipeTypes recipeType; private Expression providedName; private Trigger trigger; + private Node thisNode; + private String thisScript; @Override @SuppressWarnings("unchecked") @@ -110,12 +87,13 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye providedName = (Expression) exprs[0]; AtomicBoolean delayed = new AtomicBoolean(false); Runnable afterLoading = () -> delayed.set(!getParser().getHasDelayBefore().isFalse()); - trigger = loadCode(sectionNode, "register recipe", afterLoading, RegisterRecipeEvent.class); + trigger = loadCode(sectionNode, "register recipe", afterLoading, recipeType.eventClass); if (delayed.get()) { Skript.error("Delays cannot be used within a 'register recipe' section."); return false; } - + thisNode = getParser().getNode(); + thisScript = getParser().getCurrentScript().getConfig().getFileName(); return true; } @@ -123,31 +101,43 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye protected @Nullable TriggerItem walk(Event event) { String name = providedName.getSingle(event); NamespacedKey namespacedKey = NamespacedKey.fromString(name, Skript.getInstance()); - if (Bukkit.getRecipe(namespacedKey) != null) { - Skript.error("The namespace '" + name + "' is already registered."); - return null; - } - RegisterRecipeEvent recipeEvent = new RegisterRecipeEvent(recipeType); + RegisterRecipeEvent recipeEvent = switch (recipeType) { + case SHAPED -> new ShapedRecipeEvent(recipeType); + case SHAPELESS -> new ShapelessRecipeEvent(recipeType); + }; Variables.setLocalVariables(recipeEvent, Variables.copyLocalVariables(event)); TriggerItem.walk(trigger, recipeEvent); Variables.setLocalVariables(event, Variables.copyLocalVariables(recipeEvent)); Variables.removeLocals(recipeEvent); - + if (recipeEvent.getErrorInEffect()) + return super.walk(event, false); ItemStack result = recipeEvent.getResultItem(); if (result == null) { - Skript.error("Registering a recipe requires a resulting item"); - return null; - } - ItemStack[] ingredients = recipeEvent.getIngredients(); - if (ingredients.length < recipeType.minIngredients || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < recipeType.minIngredients) { - Skript.error("You must have at least " + recipeType.minIngredients + " ingredients when registering a '" + recipeType.toString + "' recipe."); - return null; + customError("You must provide a result item when registering a recipe."); + return super.walk(event, false); } + if (Bukkit.getRecipe(namespacedKey) != null) + Bukkit.removeRecipe(namespacedKey); switch (recipeType) { - case SHAPED -> createShapedRecipe(namespacedKey, result, ingredients); - case SHAPELESS -> createShapelessRecipe(namespacedKey, result, ingredients); + case SHAPED, SHAPELESS -> { + if (!(recipeEvent instanceof CraftingEventRecipe craftingRecipe)) + return super.walk(event, false); + ItemStack[] ingredients = craftingRecipe.getIngredients(); + if (ingredients.length < recipeType.minIngredients || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < recipeType.minIngredients) { + customError("You must have at least " + recipeType.minIngredients + " ingredients when registering a '" + recipeType.toString + "' recipe."); + return super.walk(event, false); + } + switch (recipeType) { + case SHAPED -> createShapedRecipe(namespacedKey, result, ingredients); + case SHAPELESS -> createShapelessRecipe(namespacedKey, result, ingredients); + } + } } + + + + return super.walk(event, false); } @@ -155,6 +145,7 @@ private void createShapedRecipe(NamespacedKey key, ItemStack result, ItemStack[] ShapedRecipe shapedRecipe = new ShapedRecipe(key, result); Character[] characters = new Character[]{'a','b','c','d','e','f','g','h','i'}; shapedRecipe.shape("abc","def","ghi"); + Skript.adminBroadcast("Ingredients: " + Arrays.toString(ingredients)); for (int i = 0; i < ingredients.length; i++) { ItemStack thisItem = ingredients[i]; if (thisItem != null) { @@ -173,7 +164,7 @@ private void createShapelessRecipe(NamespacedKey key, ItemStack result, ItemStac for (int i = 0; i < ingredients.length; i++) { ItemStack thisItem = ingredients[i]; if (thisItem != null) { - if (SUPPORT_SHAPED_ITEMSTACK) { + if (SUPPORT_SHAPELESS_ITEMSTACK) { shapelessRecipe.addIngredient(thisItem); } else { shapelessRecipe.addIngredient(thisItem.getAmount(), thisItem.getType()); @@ -183,9 +174,13 @@ private void createShapelessRecipe(NamespacedKey key, ItemStack result, ItemStac Bukkit.addRecipe(shapelessRecipe); } + private void customError(String message) { + Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); + } + @Override public String toString(@Nullable Event event, boolean debug) { - return null; + return "register a new " + recipeType.toString + " recipe with the namespacekey " + providedName.toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java b/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java new file mode 100644 index 00000000000..a56aa4cf7bd --- /dev/null +++ b/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java @@ -0,0 +1,247 @@ +package ch.njol.skript.util; + +import ch.njol.skript.sections.SecRegisterRecipe.RecipeTypes; +import org.bukkit.Material; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.RecipeChoice; +import org.bukkit.inventory.recipe.CookingBookCategory; +import org.bukkit.inventory.recipe.CraftingBookCategory; +import org.jetbrains.annotations.NotNull; + +public class RegisterRecipeEvent extends Event { + + private ItemStack resultItem; + private boolean errorInEffect = false; + private RecipeTypes recipeType; + + public RegisterRecipeEvent(RecipeTypes recipeType) { + this.recipeType = recipeType; + } + + public void setResultItem(ItemStack resultItem) { + this.resultItem = resultItem; + } + + public void setErrorInEffect() { + this.errorInEffect = true; + } + + public ItemStack getResultItem() { + return resultItem; + } + + public boolean getErrorInEffect() { + return errorInEffect; + } + + public RecipeTypes getRecipeType() { + return recipeType; + } + + public String getRecipeName() { + return recipeType.getToString(); + } + + public static class CraftingEventRecipe extends RegisterRecipeEvent { + private ItemStack[] ingredients = new ItemStack[9]; + private CraftingBookCategory category = CraftingBookCategory.MISC; + private String group; + + public CraftingEventRecipe(RecipeTypes recipeType) { + super(recipeType); + }; + + public void setIngredients(int placement, ItemStack item) { + ingredients[placement] = item; + } + + public void setCategory(CraftingBookCategory category) { + this.category = category; + } + + public void setGroup(String group) { + this.group = group; + } + + public ItemStack[] getIngredients() { + return ingredients; + } + + public int getMaxIngredients() { + return getRecipeType().getMaxIngredients(); + } + + public int getMaxRowIngredients() { + return getRecipeType().getMaxRowIngredients(); + } + + public int getMinIngredients() { + return getRecipeType().getMinIngredients(); + } + + public CraftingBookCategory getCategory() { + return category; + } + + public String getGroup() { + return group; + } + + public static class ShapedRecipeEvent extends CraftingEventRecipe { + public ShapedRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + }; + } + + public static class ShapelessRecipeEvent extends CraftingEventRecipe { + public ShapelessRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + }; + } + } + + public static class CookingRecipeEvent extends RegisterRecipeEvent { + private Material inputItem; + private CookingBookCategory category = CookingBookCategory.MISC; + private String group; + private int cookingTime = 10; + private float experience = 0; + + public CookingRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + }; + + public void setInputItem(Material item) { + inputItem = item; + } + + public void setCategory(CookingBookCategory category) { + this.category = category; + } + + public void setGroup(String group) { + this.group = group; + } + + public void setCookingTime(int cookingTime) { + this.cookingTime = cookingTime; + } + + public void setExperience(float experience) { + this.experience = experience; + } + + public CookingBookCategory getCategory() { + return category; + } + + public String getGroup() { + return group; + } + + public Material getInputItem() { + return inputItem; + } + + public int getCookingTime() { + return cookingTime; + } + + public float getExperience() { + return experience; + } + + public static class BlastingRecipeEvent extends CookingRecipeEvent { + public BlastingRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + } + } + + public static class CampfireRecipeEvent extends CookingRecipeEvent { + public CampfireRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + } + } + + public static class FurnaceRecipeEvent extends CookingRecipeEvent { + public FurnaceRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + } + } + + public static class SmokingRecipeEvent extends CookingRecipeEvent { + public SmokingRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + } + } + } + + public static class SmithingRecipeEvent extends RegisterRecipeEvent { + + private RecipeChoice base, addition, template; + + public SmithingRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + } + + public void setBase(RecipeChoice base) { + this.base = base; + } + + public void setAddition(RecipeChoice addition) { + this.addition = addition; + } + + public void setTemplate(RecipeChoice template) { + this.template = template; + } + + public RecipeChoice getBase() { + return base; + } + + public RecipeChoice getAddition() { + return base; + } + + public RecipeChoice getTemplate() { + return base; + } + + public static class SmithingTransformRecipeEvent extends SmithingRecipeEvent { + public SmithingTransformRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + } + } + + public static class SmithingTrimRecipeEvent extends SmithingRecipeEvent { + public SmithingTrimRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + } + } + } + + public static class StonecuttingRecipeEvent extends RegisterRecipeEvent { + + private Material inputItem; + + public StonecuttingRecipeEvent(RecipeTypes recipeType) { + super(recipeType); + } + + public void setInputItem(Material item) { + this.inputItem = item; + } + + public Material getInputItem() { + return inputItem; + } + } + + @Override + public @NotNull HandlerList getHandlers() { + throw new IllegalStateException(); + } +} From bd2c23f73a94d643ff3b2c37f18dea30353f7af6 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Wed, 9 Oct 2024 17:37:57 -0400 Subject: [PATCH 04/20] Testing Fix --- .../ch/njol/skript/effects/EffCraftingRecipeValues.java | 6 +++--- .../ch/njol/skript/effects/EffRegisterRecipeValues.java | 2 +- .../java/ch/njol/skript/sections/SecRegisterRecipe.java | 4 ++-- .../java/ch/njol/skript/util/RegisterRecipeEvent.java | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java index fd60ad67f0b..c67a7edc7ee 100644 --- a/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java +++ b/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java @@ -8,7 +8,7 @@ import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.util.RegisterRecipeEvent; import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.skript.util.RegisterRecipeEvent.CraftingEventRecipe.*; +import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; import ch.njol.util.Kleenean; import org.bukkit.Material; import org.bukkit.event.Event; @@ -21,7 +21,7 @@ public class EffCraftingRecipeValues extends Effect { enum RecipeValues { INGREDIENTS("set [the] recipe ingredients to %itemstacks/itemtypes%", "recipe ingredients", - CraftingEventRecipe.class, "This can only be used when registering a Crafting, Shaped, or Shapeless Recipe"), + CraftingRecipeEvent.class, "This can only be used when registering a Crafting, Shaped, or Shapeless Recipe"), FIRSTROW("set [the] recipe ingredients of (first|1st) row to %itemstacks/itemtypes%", "recipe ingredients first row", ShapedRecipeEvent.class, "This can only be used when registering a Shaped Recipe."), SECONDROW("set [the] recipe ingredients of (second|2nd) row to %itemstacks/itemtypes%", "recipe ingredients second row", @@ -74,7 +74,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected void execute(Event event) { - if (!(event instanceof CraftingEventRecipe recipeEvent)) + if (!(event instanceof CraftingRecipeEvent recipeEvent)) return; switch (selectedValue) { diff --git a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java index 75eef2ec5b9..9299819798d 100644 --- a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java +++ b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java @@ -8,7 +8,7 @@ import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.util.RegisterRecipeEvent; import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.skript.util.RegisterRecipeEvent.CraftingEventRecipe.*; +import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; import ch.njol.util.Kleenean; import org.bukkit.Material; import org.bukkit.event.Event; diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 212cbfcfe3d..4d2e613f302 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -10,7 +10,7 @@ import ch.njol.skript.lang.TriggerItem; import ch.njol.skript.util.RegisterRecipeEvent; import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.skript.util.RegisterRecipeEvent.CraftingEventRecipe.*; +import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; import ch.njol.skript.variables.Variables; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; @@ -120,7 +120,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye Bukkit.removeRecipe(namespacedKey); switch (recipeType) { case SHAPED, SHAPELESS -> { - if (!(recipeEvent instanceof CraftingEventRecipe craftingRecipe)) + if (!(recipeEvent instanceof CraftingRecipeEvent craftingRecipe)) return super.walk(event, false); ItemStack[] ingredients = craftingRecipe.getIngredients(); if (ingredients.length < recipeType.minIngredients || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < recipeType.minIngredients) { diff --git a/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java b/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java index a56aa4cf7bd..5eb81c6a74c 100644 --- a/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java +++ b/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java @@ -44,12 +44,12 @@ public String getRecipeName() { return recipeType.getToString(); } - public static class CraftingEventRecipe extends RegisterRecipeEvent { + public static class CraftingRecipeEvent extends RegisterRecipeEvent { private ItemStack[] ingredients = new ItemStack[9]; private CraftingBookCategory category = CraftingBookCategory.MISC; private String group; - public CraftingEventRecipe(RecipeTypes recipeType) { + public CraftingRecipeEvent(RecipeTypes recipeType) { super(recipeType); }; @@ -89,13 +89,13 @@ public String getGroup() { return group; } - public static class ShapedRecipeEvent extends CraftingEventRecipe { + public static class ShapedRecipeEvent extends CraftingRecipeEvent { public ShapedRecipeEvent(RecipeTypes recipeType) { super(recipeType); }; } - public static class ShapelessRecipeEvent extends CraftingEventRecipe { + public static class ShapelessRecipeEvent extends CraftingRecipeEvent { public ShapelessRecipeEvent(RecipeTypes recipeType) { super(recipeType); }; From 50bb13905270cfe2dc6b6bb72b72ea9c4f4a0cb6 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:23:36 -0400 Subject: [PATCH 05/20] More additions --- .../effects/EffCookingRecipeValues.java | 148 +++++++++++++++ .../effects/EffCraftingRecipeValues.java | 22 +-- .../effects/EffRegisterRecipeValues.java | 68 +++++-- .../effects/EffSmithingRecipeValues.java | 109 +++++++++++ .../skript/sections/SecRegisterRecipe.java | 179 +++++++++++------- .../njol/skript/util/RegisterRecipeEvent.java | 68 ++++++- 6 files changed, 494 insertions(+), 100 deletions(-) create mode 100644 src/main/java/ch/njol/skript/effects/EffCookingRecipeValues.java create mode 100644 src/main/java/ch/njol/skript/effects/EffSmithingRecipeValues.java diff --git a/src/main/java/ch/njol/skript/effects/EffCookingRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffCookingRecipeValues.java new file mode 100644 index 00000000000..3629e1ccabe --- /dev/null +++ b/src/main/java/ch/njol/skript/effects/EffCookingRecipeValues.java @@ -0,0 +1,148 @@ +package ch.njol.skript.effects; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.config.Node; +import ch.njol.skript.lang.Effect; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.skript.util.Timespan; +import ch.njol.util.Kleenean; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.RecipeChoice; +import org.jetbrains.annotations.Nullable; + +public class EffCookingRecipeValues extends Effect { + + enum CookingRecipeValues { + EXPERIENCE("set [the] recipe experience to %integer%", "recipe experience", CookingRecipeEvent.class, + "This can only be used when registering a Blasting, Furnace, Campfire, or Smoking Recipe."), + COOKINGTIME("set [the] recipe cook[ing] time to %timespan%", "recipe cooking time", CookingRecipeEvent.class, + "This can only be used when registering a Blasting, Furnace, Campfire, or Smoking Recipe."), + INPUT("set [the] recipe (input|source) [item] to %itemstack/itemtype%", "recipe input item", new Class[]{CookingRecipeEvent.class, StonecuttingRecipeEvent.class}, + "This can only be used when registering a Blasting, Furnace, Campfire, Smoking, or Stonecutting Recipe."); + + private String pattern, toString, error; + private Class eventClass; + private Class[] eventClasses; + + CookingRecipeValues(String pattern, String toString, Class eventClass, String error) { + this.pattern = pattern; + this.toString = toString; + this.eventClass = eventClass; + this.error = error; + } + + CookingRecipeValues(String pattern, String toString, Class[] eventClasses, String error) { + this.pattern = pattern; + this.toString = toString; + this.eventClasses = eventClasses; + this.error = error; + } + } + + private static CookingRecipeValues[] recipeValues = CookingRecipeValues.values(); + + static { + String[] patterns = new String[recipeValues.length]; + for (CookingRecipeValues value : recipeValues) { + patterns[value.ordinal()] = value.pattern; + } + Skript.registerEffect(EffCookingRecipeValues.class, patterns); + } + + private CookingRecipeValues selectedValue; + private @Nullable Expression itemExpr; + private @Nullable Expression intExpr; + private @Nullable Expression timeExpr; + private Node thisNode; + private String thisScript; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + selectedValue = recipeValues[matchedPattern]; + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { + Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); + return false; + } + if (selectedValue.eventClass != null && !getParser().isCurrentEvent(selectedValue.eventClass)) { + Skript.error(selectedValue.error); + return false; + } else if (selectedValue.eventClasses != null) { + boolean classFound = false; + for (Class clazz : selectedValue.eventClasses) { + if (getParser().isCurrentEvent(clazz)) { + classFound = true; + break; + } + } + if (!classFound) { + Skript.error(selectedValue.error); + return false; + } + } + switch (selectedValue) { + case INPUT -> itemExpr = exprs[0]; + case EXPERIENCE -> intExpr = (Expression) exprs[0]; + case COOKINGTIME -> timeExpr = (Expression) exprs[0]; + } + thisNode = getParser().getNode(); + thisScript = getParser().getCurrentScript().getConfig().getFileName(); + return true; + } + + @Override + protected void execute(Event event) { + if (event instanceof CookingRecipeEvent cookingEvent) { + switch (selectedValue) { + case EXPERIENCE -> { + Integer experience = intExpr.getSingle(event); + if (experience != null) + cookingEvent.setExperience(experience.floatValue()); + } + case INPUT -> { + Object inputItem = itemExpr.getSingle(event); + if (inputItem instanceof ItemStack itemStack) { + cookingEvent.setInputItem(itemStack.getType()); + } else if (inputItem instanceof ItemType itemType) { + cookingEvent.setInputItem(itemType.getMaterial()); + } + } + case COOKINGTIME -> { + Timespan cookingTime = timeExpr.getSingle(event); + if (cookingTime != null) { + cookingEvent.setCookingTime((int) cookingTime.getAs(Timespan.TimePeriod.TICK)); + } + } + } + } else if (event instanceof StonecuttingRecipeEvent stonecuttingEvent) { + if (selectedValue == CookingRecipeValues.INPUT) { + RecipeChoice choice = null; + Object inputItem = itemExpr.getSingle(event); + if (inputItem instanceof ItemStack itemStack) { + choice = new RecipeChoice.ExactChoice(itemStack); + } else if (inputItem instanceof ItemType itemType) { + ItemStack stack = new ItemStack(itemType.getMaterial()); + stack.setItemMeta(itemType.getItemMeta()); + choice = new RecipeChoice.ExactChoice(stack); + } + if (choice != null) { + stonecuttingEvent.setInput(choice); + } + } + } + } + + private void customError(String message) { + Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return null; + } +} diff --git a/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java index c67a7edc7ee..f9ca56f502a 100644 --- a/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java +++ b/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java @@ -15,13 +15,11 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; - public class EffCraftingRecipeValues extends Effect { - enum RecipeValues { + enum CraftingRecipeValues { INGREDIENTS("set [the] recipe ingredients to %itemstacks/itemtypes%", "recipe ingredients", - CraftingRecipeEvent.class, "This can only be used when registering a Crafting, Shaped, or Shapeless Recipe"), + CraftingRecipeEvent.class, "This can only be used when registering a Shaped or Shapeless Recipe"), FIRSTROW("set [the] recipe ingredients of (first|1st) row to %itemstacks/itemtypes%", "recipe ingredients first row", ShapedRecipeEvent.class, "This can only be used when registering a Shaped Recipe."), SECONDROW("set [the] recipe ingredients of (second|2nd) row to %itemstacks/itemtypes%", "recipe ingredients second row", @@ -32,7 +30,7 @@ enum RecipeValues { private String pattern, toString, error; private Class eventClass; - RecipeValues(String pattern, String toString, Class eventClass, String error) { + CraftingRecipeValues(String pattern, String toString, Class eventClass, String error) { this.pattern = pattern; this.toString = toString; this.eventClass = eventClass; @@ -40,18 +38,18 @@ enum RecipeValues { } } - private static RecipeValues[] recipeValues = RecipeValues.values(); + private static CraftingRecipeValues[] recipeValues = CraftingRecipeValues.values(); static { String[] patterns = new String[recipeValues.length]; - for (RecipeValues value : recipeValues) { + for (CraftingRecipeValues value : recipeValues) { patterns[value.ordinal()] = value.pattern; } Skript.registerEffect(EffCraftingRecipeValues.class, patterns); } - private RecipeValues selectedValue; - private Expression itemValues; + private CraftingRecipeValues selectedValue; + private Expression itemExpr; private Node thisNode; private String thisScript; @@ -66,7 +64,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye Skript.error(selectedValue.error); return false; } - itemValues = exprs[0]; + itemExpr = exprs[0]; thisNode = getParser().getNode(); thisScript = getParser().getCurrentScript().getConfig().getFileName(); return true; @@ -79,7 +77,7 @@ protected void execute(Event event) { switch (selectedValue) { case INGREDIENTS -> { - Object[] items = itemValues.getArray(event); + Object[] items = itemExpr.getArray(event); if (items.length > recipeEvent.getMaxIngredients()) { customError("You can only provide up to " + recipeEvent.getMaxIngredients() + " items when setting the ingredients for a '" + recipeEvent.getRecipeName() + "' recipe."); @@ -98,7 +96,7 @@ protected void execute(Event event) { } } case FIRSTROW, SECONDROW, THIRDROW -> { - Object[] items = itemValues.getArray(event); + Object[] items = itemExpr.getArray(event); if (items.length > recipeEvent.getMaxRowIngredients()) { if (recipeEvent.getMaxRowIngredients() == 0) { customError("You can not use '" + selectedValue.toString + "' when registering a '" + recipeEvent.getRecipeName() + "' recipe."); diff --git a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java index 9299819798d..b8b1c10f6e8 100644 --- a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java +++ b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java @@ -8,53 +8,81 @@ import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.util.RegisterRecipeEvent; import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; import ch.njol.util.Kleenean; import org.bukkit.Material; import org.bukkit.event.Event; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; - public class EffRegisterRecipeValues extends Effect { - enum RecipeValues { - RESULT("set [the] recipe result to %itemstack/itemtype%", "recipe result", RegisterRecipeEvent.class); + enum RegisterRecipeValues { + RESULT("set [the] recipe result to %itemstack/itemtype%", "recipe result", RegisterRecipeEvent.class), + GROUP("set [the] recipe group to %string%", "recipe group", new Class[]{CraftingRecipeEvent.class, CookingRecipeEvent.class}, + "This can only be used when registering a Shaped, Shapeless, Blasting, Furnace, Campfire, or Smoking Recipe."); - private String pattern, toString; + private String pattern, toString, error; private Class eventClass; + private Class[] eventClasses; - RecipeValues(String pattern, String toString, Class eventClass) { + RegisterRecipeValues(String pattern, String toString, Class eventClass) { this.pattern = pattern; this.toString = toString; this.eventClass = eventClass; } + + RegisterRecipeValues(String pattern, String toString, Class[] eventClasses, String error) { + this.pattern = pattern; + this.toString = toString; + this.eventClasses = eventClasses; + this.error = error; + } } - private static RecipeValues[] recipeValues = RecipeValues.values(); + private static RegisterRecipeValues[] recipeValues = RegisterRecipeValues.values(); static { String[] patterns = new String[recipeValues.length]; - for (RecipeValues value : recipeValues) { + for (RegisterRecipeValues value : recipeValues) { patterns[value.ordinal()] = value.pattern; } Skript.registerEffect(EffRegisterRecipeValues.class, patterns); } - private RecipeValues selectedValue; - private Expression itemValues; + private RegisterRecipeValues selectedValue; + private @Nullable Expression itemExpr; + private @Nullable Expression groupExpr; private Node thisNode; private String thisScript; @Override + @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { selectedValue = recipeValues[matchedPattern]; - if (!getParser().isCurrentEvent(selectedValue.eventClass)) { + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); return false; } - itemValues = exprs[0]; + if (selectedValue.eventClass != null && !getParser().isCurrentEvent(selectedValue.eventClass)) { + Skript.error(selectedValue.error); + return false; + } else if (selectedValue.eventClasses != null) { + boolean classFound = false; + for (Class clazz : selectedValue.eventClasses) { + if (getParser().isCurrentEvent(clazz)) { + classFound = true; + break; + } + } + if (!classFound) { + Skript.error(selectedValue.error); + return false; + } + } + switch (selectedValue) { + case RESULT -> itemExpr = exprs[0]; + case GROUP -> groupExpr = (Expression) exprs[0]; + } thisNode = getParser().getNode(); thisScript = getParser().getCurrentScript().getConfig().getFileName(); return true; @@ -67,7 +95,7 @@ protected void execute(Event event) { switch (selectedValue) { case RESULT -> { - Object item = itemValues.getSingle(event); + Object item = itemExpr.getSingle(event); if (item instanceof ItemStack itemStack && itemStack.getType() != Material.AIR) { recipeEvent.setResultItem(itemStack); } else if (item instanceof ItemType itemType && itemType.getMaterial() != Material.AIR) { @@ -79,6 +107,18 @@ protected void execute(Event event) { recipeEvent.setErrorInEffect(); } } + case GROUP -> { + String group = groupExpr.getSingle(event); + if (group == null || group.isEmpty()) { + customError("The group can not be null or blank."); + return; + } + if (event instanceof CookingRecipeEvent cookingEvent) { + cookingEvent.setGroup(group); + } else if (event instanceof CraftingRecipeEvent craftingEvent) { + craftingEvent.setGroup(group); + } + } } } diff --git a/src/main/java/ch/njol/skript/effects/EffSmithingRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffSmithingRecipeValues.java new file mode 100644 index 00000000000..6196ac47c07 --- /dev/null +++ b/src/main/java/ch/njol/skript/effects/EffSmithingRecipeValues.java @@ -0,0 +1,109 @@ +package ch.njol.skript.effects; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.config.Node; +import ch.njol.skript.lang.Effect; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; +import ch.njol.util.Kleenean; +import org.bukkit.Material; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.RecipeChoice; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class EffSmithingRecipeValues extends Effect { + + enum SmithingRecipeValues { + BASE("set [the] recipe base item[s] to %itemstacks/itemtypes%", "recipe base item", SmithingRecipeEvent.class, + "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), + TEMPLATE("set [the] recipe template item[s] to %itemstacks/itemtypes%", "recipe template item", SmithingRecipeEvent.class, + "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), + ADDITION("set [the] recipe addition[al] item[s] to %itemstacks/itemtypes%", "recipe additional item", SmithingRecipeEvent.class, + "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."); + + private String pattern, toString, error; + private Class eventClass; + + SmithingRecipeValues(String pattern, String toString, Class eventClass, String error) { + this.pattern = pattern; + this.toString = toString; + this.eventClass = eventClass; + this.error = error; + } + } + + private static SmithingRecipeValues[] recipeValues = SmithingRecipeValues.values(); + + static { + String[] patterns = new String[recipeValues.length]; + for (SmithingRecipeValues value : recipeValues) { + patterns[value.ordinal()] = value.pattern; + } + Skript.registerEffect(EffSmithingRecipeValues.class, patterns); + } + + private SmithingRecipeValues selectedValue; + private Expression itemExpr; + private Node thisNode; + private String thisScript; + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + selectedValue = recipeValues[matchedPattern]; + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { + Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); + return false; + } + if (!getParser().isCurrentEvent(selectedValue.eventClass)) { + Skript.error(selectedValue.error); + return false; + } + itemExpr = exprs[0]; + thisNode = getParser().getNode(); + thisScript = getParser().getCurrentScript().getConfig().getFileName(); + return true; + } + + @Override + protected void execute(Event event) { + if (!(event instanceof SmithingRecipeEvent smithingEvent)) + return; + List items = new ArrayList<>(); + for (Object item : itemExpr.getArray(event)) { + if (item instanceof ItemStack itemStack) { + items.add(itemStack); + } else if (item instanceof ItemType itemType) { + ItemStack stack = new ItemStack(itemType.getMaterial()); + stack.setItemMeta(itemType.getItemMeta()); + items.add(stack); + } + } + if (items.isEmpty()) { + customError("You must provide valid items when setting the " + selectedValue.toString + " of a recipe."); + return; + } + RecipeChoice choice = new RecipeChoice.ExactChoice(items); + switch (selectedValue) { + case BASE -> smithingEvent.setBase(choice); + case TEMPLATE -> smithingEvent.setTemplate(choice); + case ADDITION -> smithingEvent.setAddition(choice); + } + } + + private void customError(String message) { + Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return null; + } +} diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 4d2e613f302..771bd493efc 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -9,67 +9,41 @@ import ch.njol.skript.lang.Trigger; import ch.njol.skript.lang.TriggerItem; import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.RecipeTypes; import ch.njol.skript.util.RegisterRecipeEvent.*; import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; import ch.njol.skript.variables.Variables; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.event.Event; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.ShapedRecipe; -import org.bukkit.inventory.ShapelessRecipe; +import org.bukkit.inventory.*; +import org.bukkit.inventory.recipe.CookingBookCategory; +import org.bukkit.inventory.recipe.CraftingBookCategory; import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; public class SecRegisterRecipe extends Section { - + /* + TODO: + set category effect + CondDiscoveredRecipe + EffDiscoverRecipe + Tests + Maybe CraftingBookCategory and CookingBookCategory lang + */ private static final boolean SUPPORT_SHAPED_ITEMSTACK = Skript.methodExists(ShapedRecipe.class, "setIngredient", Character.class, ItemStack.class); private static final boolean SUPPORT_SHAPELESS_ITEMSTACK = Skript.methodExists(ShapelessRecipe.class, "addIngredient", ItemStack.class); - public enum RecipeTypes { - SHAPED("shaped", 9, 3, 2, "shaped", ShapedRecipeEvent.class), - SHAPELESS("shapeless", 9, 0, 2, "shapeless", ShapelessRecipeEvent.class); - - - private String pattern, toString; - private int maxIngredients, maxRowIngredients, minIngredients; - private Class eventClass; - - RecipeTypes(String pattern, int maxIngredients, int maxRowIngredients, int minIngredients, String toString, Class eventClass) { - this.pattern = pattern; - this.maxIngredients = maxIngredients; - this.maxRowIngredients = maxRowIngredients; - this.minIngredients = minIngredients; - this.toString = toString; - this.eventClass = eventClass; - } - - public String getToString() { - return toString; - } - - public int getMaxIngredients() { - return maxIngredients; - } - - public int getMaxRowIngredients() { - return maxRowIngredients; - } - - public int getMinIngredients() { - return minIngredients; - } - } - private static final RecipeTypes[] recipeTypes = RecipeTypes.values(); static { String[] patterns = new String[recipeTypes.length]; for (RecipeTypes type : recipeTypes) { - patterns[type.ordinal()] = "(register|create) [a] [new] " + type.pattern + " recipe with [the] name[space[key]] %string%"; + patterns[type.ordinal()] = "(register|create) [a] [new] " + type.getPattern() + " recipe with [the] name[space[key]] %string%"; } Skript.registerSection(SecRegisterRecipe.class, patterns); } @@ -87,7 +61,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye providedName = (Expression) exprs[0]; AtomicBoolean delayed = new AtomicBoolean(false); Runnable afterLoading = () -> delayed.set(!getParser().getHasDelayBefore().isFalse()); - trigger = loadCode(sectionNode, "register recipe", afterLoading, recipeType.eventClass); + trigger = loadCode(sectionNode, "register recipe", afterLoading, recipeType.getEventClass()); if (delayed.get()) { Skript.error("Delays cannot be used within a 'register recipe' section."); return false; @@ -100,10 +74,13 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected @Nullable TriggerItem walk(Event event) { String name = providedName.getSingle(event); - NamespacedKey namespacedKey = NamespacedKey.fromString(name, Skript.getInstance()); + NamespacedKey key = NamespacedKey.fromString(name, Skript.getInstance()); RegisterRecipeEvent recipeEvent = switch (recipeType) { case SHAPED -> new ShapedRecipeEvent(recipeType); case SHAPELESS -> new ShapelessRecipeEvent(recipeType); + case COOKING, BLASTING, FURNACE, CAMPFIRE, SMOKING -> new CookingRecipeEvent(recipeType); + case SMITHINGTRANSFORM, SMITHINGTRIM -> new SmithingRecipeEvent(recipeType); + case STONECUTTING -> new StonecuttingRecipeEvent(recipeType); }; Variables.setLocalVariables(recipeEvent, Variables.copyLocalVariables(event)); TriggerItem.walk(trigger, recipeEvent); @@ -112,40 +89,69 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye if (recipeEvent.getErrorInEffect()) return super.walk(event, false); ItemStack result = recipeEvent.getResultItem(); - if (result == null) { + if (result == null && (recipeType != RecipeTypes.SMITHINGTRIM)) { customError("You must provide a result item when registering a recipe."); return super.walk(event, false); } - if (Bukkit.getRecipe(namespacedKey) != null) - Bukkit.removeRecipe(namespacedKey); switch (recipeType) { case SHAPED, SHAPELESS -> { - if (!(recipeEvent instanceof CraftingRecipeEvent craftingRecipe)) - return super.walk(event, false); - ItemStack[] ingredients = craftingRecipe.getIngredients(); - if (ingredients.length < recipeType.minIngredients || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < recipeType.minIngredients) { - customError("You must have at least " + recipeType.minIngredients + " ingredients when registering a '" + recipeType.toString + "' recipe."); - return super.walk(event, false); + if (recipeEvent instanceof CraftingRecipeEvent craftingRecipe) { + ItemStack[] ingredients = craftingRecipe.getIngredients(); + if (ingredients.length < 2 || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < 2) { + customError("You must have at least 2 ingredients when registering a '" + recipeType.getToString() + "' recipe."); + return super.walk(event, false); + } + String group = craftingRecipe.getGroup(); + CraftingBookCategory category = craftingRecipe.getCategory(); + switch (recipeType) { + case SHAPED -> createShapedRecipe(key, result, ingredients, group, category); + case SHAPELESS -> createShapelessRecipe(key, result, ingredients, group, category); + } + } + } + case COOKING, BLASTING, FURNACE, CAMPFIRE, SMOKING -> { + if (recipeEvent instanceof CookingRecipeEvent cookingRecipe) { + Material inputItem = cookingRecipe.getInputItem(); + String group = cookingRecipe.getGroup(); + CookingBookCategory category = cookingRecipe.getCategory(); + int cookingTime = cookingRecipe.getCookingTime(); + float experience = cookingRecipe.getExperience(); + createCookingRecipe(recipeType, key, result, inputItem, group, category, cookingTime, experience); + } + } + case SMITHINGTRANSFORM, SMITHINGTRIM -> { + if (recipeEvent instanceof SmithingRecipeEvent smithingRecipe) { + RecipeChoice base = smithingRecipe.getBase(); + RecipeChoice template = smithingRecipe.getTemplate(); + RecipeChoice addition = smithingRecipe.getAddition(); + createSmithingRecipe(recipeType, key, result, base, template, addition); } - switch (recipeType) { - case SHAPED -> createShapedRecipe(namespacedKey, result, ingredients); - case SHAPELESS -> createShapelessRecipe(namespacedKey, result, ingredients); + } + case STONECUTTING -> { + if (recipeEvent instanceof StonecuttingRecipeEvent stonecuttingRecipe) { + RecipeChoice input = stonecuttingRecipe.getInput(); + createStonecuttingRecipe(key, result, input); } } } - - - - return super.walk(event, false); } - private void createShapedRecipe(NamespacedKey key, ItemStack result, ItemStack[] ingredients) { + private void completeRecipe(NamespacedKey key, Recipe recipe) { + if (Bukkit.getRecipe(key) != null) + Bukkit.removeRecipe(key); + Bukkit.addRecipe(recipe); + } + + private void createShapedRecipe(NamespacedKey key, ItemStack result, ItemStack[] ingredients, String group, CraftingBookCategory category) { ShapedRecipe shapedRecipe = new ShapedRecipe(key, result); + if (category != null) + shapedRecipe.setCategory(category); + if (group != null && !group.isEmpty()) + shapedRecipe.setGroup(group); Character[] characters = new Character[]{'a','b','c','d','e','f','g','h','i'}; shapedRecipe.shape("abc","def","ghi"); - Skript.adminBroadcast("Ingredients: " + Arrays.toString(ingredients)); for (int i = 0; i < ingredients.length; i++) { ItemStack thisItem = ingredients[i]; if (thisItem != null) { @@ -156,11 +162,15 @@ private void createShapedRecipe(NamespacedKey key, ItemStack result, ItemStack[] } } } - Bukkit.addRecipe(shapedRecipe); + completeRecipe(key, shapedRecipe); } - private void createShapelessRecipe(NamespacedKey key, ItemStack result, ItemStack[] ingredients) { + private void createShapelessRecipe(NamespacedKey key, ItemStack result, ItemStack[] ingredients, String group, CraftingBookCategory category) { ShapelessRecipe shapelessRecipe = new ShapelessRecipe(key, result); + if (category != null) + shapelessRecipe.setCategory(category); + if (group != null && !group.isEmpty()) + shapelessRecipe.setGroup(group); for (int i = 0; i < ingredients.length; i++) { ItemStack thisItem = ingredients[i]; if (thisItem != null) { @@ -171,7 +181,48 @@ private void createShapelessRecipe(NamespacedKey key, ItemStack result, ItemStac } } } - Bukkit.addRecipe(shapelessRecipe); + completeRecipe(key, shapelessRecipe); + } + + private void createCookingRecipe(RecipeTypes recipeType, NamespacedKey key, ItemStack result, Material inputItem, String group, CookingBookCategory category, int cookingTime, float experience) { + var recipe = switch (recipeType) { + case BLASTING -> new BlastingRecipe(key, result, inputItem, experience, cookingTime); + case CAMPFIRE -> new CampfireRecipe(key, result, inputItem, experience, cookingTime); + case FURNACE -> new FurnaceRecipe(key, result, inputItem, experience, cookingTime); + case SMOKING -> new SmokingRecipe(key, result, inputItem, experience, cookingTime); + default -> null; + }; + if (recipe == null) + return; + if (category != null) + recipe.setCategory(category); + if (group != null && !group.isEmpty()) + recipe.setGroup(group); + completeRecipe(key, recipe); + } + + private void createSmithingRecipe(RecipeTypes recipeType, NamespacedKey key, ItemStack result, RecipeChoice base, RecipeChoice template, RecipeChoice addition) { + if (base == null || template == null || addition == null) { + customError("Unable to create " + recipeType.getToString() + " recipe, missing data."); + return; + } + var recipe = switch (recipeType) { + case SMITHINGTRANSFORM -> new SmithingTransformRecipe(key, result, template, base, addition); + case SMITHINGTRIM -> new SmithingTrimRecipe(key, template, base, addition); + default -> null; + }; + if (recipe == null) + return; + completeRecipe(key, recipe); + } + + private void createStonecuttingRecipe(NamespacedKey key, ItemStack result, RecipeChoice input) { + if (input == null) { + customError("Unable to create a stonecutting recipe, missing data."); + return; + } + StonecuttingRecipe recipe = new StonecuttingRecipe(key, result, input); + completeRecipe(key, recipe); } private void customError(String message) { @@ -180,7 +231,7 @@ private void customError(String message) { @Override public String toString(@Nullable Event event, boolean debug) { - return "register a new " + recipeType.toString + " recipe with the namespacekey " + providedName.toString(event, debug); + return "register a new " + recipeType.getToString() + " recipe with the namespacekey " + providedName.toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java b/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java index 5eb81c6a74c..947524ba333 100644 --- a/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java +++ b/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java @@ -1,6 +1,5 @@ package ch.njol.skript.util; -import ch.njol.skript.sections.SecRegisterRecipe.RecipeTypes; import org.bukkit.Material; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; @@ -12,6 +11,59 @@ public class RegisterRecipeEvent extends Event { + public enum RecipeTypes { + SHAPED("shaped [crafting]", 9, 3, "shaped", CraftingRecipeEvent.ShapedRecipeEvent.class), + SHAPELESS("shapeless [crafting]", 9, 0, "shapeless", CraftingRecipeEvent.ShapelessRecipeEvent.class), + BLASTING("blast[ing]", "blasting", CookingRecipeEvent.BlastingRecipeEvent.class), + CAMPFIRE("campfire", "campfire", CookingRecipeEvent.CampfireRecipeEvent.class), + FURNACE("furnace", "furnace", CookingRecipeEvent.FurnaceRecipeEvent.class), + SMOKING("smoking", "smoking", CookingRecipeEvent.SmokingRecipeEvent.class), + COOKING("cooking", "cooking", CookingRecipeEvent.class), + SMITHINGTRANSFORM("smith[ing] transform", "smithing transform", SmithingRecipeEvent.SmithingTransformRecipeEvent.class), + SMITHINGTRIM("smith[ing] trim", "smithing trim", SmithingRecipeEvent.SmithingTrimRecipeEvent.class), + STONECUTTING("stone cutting", "stone cutting", StonecuttingRecipeEvent.class); + + + private String pattern, toString; + private int maxIngredients, maxRowIngredients; + private Class eventClass; + + RecipeTypes(String pattern, int maxIngredients, int maxRowIngredients, String toString, Class eventClass) { + this.pattern = pattern; + this.maxIngredients = maxIngredients; + this.maxRowIngredients = maxRowIngredients; + this.toString = toString; + this.eventClass = eventClass; + } + + RecipeTypes(String pattern, String toString, Class eventClass) { + this.pattern = pattern; + this.toString = toString; + this.eventClass = eventClass; + } + + public String getPattern() { + return pattern; + } + + public Class getEventClass() { + return eventClass; + } + + public String getToString() { + return toString; + } + + public int getMaxIngredients() { + return maxIngredients; + } + + public int getMaxRowIngredients() { + return maxRowIngredients; + } + + } + private ItemStack resultItem; private boolean errorInEffect = false; private RecipeTypes recipeType; @@ -77,10 +129,6 @@ public int getMaxRowIngredients() { return getRecipeType().getMaxRowIngredients(); } - public int getMinIngredients() { - return getRecipeType().getMinIngredients(); - } - public CraftingBookCategory getCategory() { return category; } @@ -225,18 +273,18 @@ public SmithingTrimRecipeEvent(RecipeTypes recipeType) { public static class StonecuttingRecipeEvent extends RegisterRecipeEvent { - private Material inputItem; + private RecipeChoice input; public StonecuttingRecipeEvent(RecipeTypes recipeType) { super(recipeType); } - public void setInputItem(Material item) { - this.inputItem = item; + public void setInput(RecipeChoice input) { + this.input = input; } - public Material getInputItem() { - return inputItem; + public RecipeChoice getInput() { + return input; } } From 29bc2e88e9ad77eec9d2dee51cb3716dd02e0962 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:53:32 -0400 Subject: [PATCH 06/20] Additional Updates + Changes --- .../skript/classes/data/BukkitClasses.java | 30 +- .../conditions/CondDiscoveredRecipes.java | 66 ++++ .../effects/EffCookingRecipeValues.java | 148 -------- .../effects/EffCraftingRecipeValues.java | 133 ------- .../skript/effects/EffDiscoverRecipe.java | 71 ++++ .../effects/EffRegisterRecipeValues.java | 133 ------- .../njol/skript/effects/EffRemoveRecipe.java | 53 +++ .../njol/skript/effects/EffResetRecipes.java | 41 +++ .../effects/EffSmithingRecipeValues.java | 109 ------ .../expressions/ExprRecipeCategory.java | 105 ++++++ .../expressions/ExprRecipeCookingTime.java | 99 +++++ .../expressions/ExprRecipeExperience.java | 98 +++++ .../skript/expressions/ExprRecipeGroup.java | 104 ++++++ .../expressions/ExprRecipeIngredients.java | 346 ++++++++++++++++++ .../skript/expressions/ExprRecipeResult.java | 87 +++++ .../skript/sections/SecRegisterRecipe.java | 118 ++++-- .../njol/skript/util/RegisterRecipeEvent.java | 74 ++-- src/main/resources/lang/default.lang | 16 + 18 files changed, 1222 insertions(+), 609 deletions(-) create mode 100644 src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java delete mode 100644 src/main/java/ch/njol/skript/effects/EffCookingRecipeValues.java delete mode 100644 src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java create mode 100644 src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java delete mode 100644 src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java create mode 100644 src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java create mode 100644 src/main/java/ch/njol/skript/effects/EffResetRecipes.java delete mode 100644 src/main/java/ch/njol/skript/effects/EffSmithingRecipeValues.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index 94b5fe789c4..54a5a3ab899 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -71,10 +71,9 @@ import org.bukkit.event.player.PlayerQuitEvent.QuitReason; import org.bukkit.event.player.PlayerResourcePackStatusEvent.Status; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.inventory.BlockInventoryHolder; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.*; +import org.bukkit.inventory.recipe.CookingBookCategory; +import org.bukkit.inventory.recipe.CraftingBookCategory; import org.bukkit.metadata.Metadatable; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -1532,6 +1531,29 @@ public String toVariableNameString(EnchantmentOffer eo) { .name("Entity Potion Cause") .description("Represents the cause of the action of a potion effect on an entity, e.g. arrow, command") .since("INSERT VERSION")); + + Classes.registerClass(new ClassInfo<>(Recipe.class, "recipe") + .user("recipes?") + .name("Recipe") + .description("") + .usage("") + .examples("") + .since("INSERT VERSION") + .defaultExpression(new EventValueExpression<>(Recipe.class))); + + Classes.registerClass(new EnumClassInfo<>(CraftingBookCategory.class, "craftingbookcategory", "crafting book categories") + .user("crafting book category") + .name("Crafting Book Category") + .description("Represents a category for crafting recipe types") + .since("INSERT VERSION") + ); + + Classes.registerClass(new EnumClassInfo<>(CookingBookCategory.class, "cookingbookcategory", "cooking book categories") + .user("cooking book category") + .name("Cooking Book Category") + .description("Represents a category for cooking recipe types") + .since("INSERT VERSION") + ); } } diff --git a/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java b/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java new file mode 100644 index 00000000000..82a829ec71d --- /dev/null +++ b/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java @@ -0,0 +1,66 @@ +package ch.njol.skript.conditions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Condition; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +@Name("Has Discovered Recipe") +@Description("Checks whether a player or players have discovered a recipe.") +@Examples({ + "if player has discovered recipe \"custom_recipe\":", + "\tgive player 1 diamond", + "", + "if all players have not found recipe \"custom_recipe\":", + "\tkill all players", +}) +@Since("INSERT VERSION") +public class CondDiscoveredRecipes extends Condition { + + static { + Skript.registerCondition(CondDiscoveredRecipes.class, + "%players% (has|have) (discovered|unlocked| recipe[s] %strings%", + "%players% (hasn't|has not|haven't|have not) (discovered|unlocked| recipe[s] %strings%"); + } + + private Expression players; + private Expression recipes; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + players = (Expression) exprs[0]; + recipes = (Expression) exprs[1]; + setNegated(matchedPattern == 1); + return true; + } + + @Override + public boolean check(Event event) { + return players.check(event, + player -> recipes.check(event, + recipe -> { + NamespacedKey key = NamespacedKey.fromString(recipe, Skript.getInstance()); + if (Bukkit.getRecipe(key) != null) + return player.hasDiscoveredRecipe(key); + return false; + } + ) + ); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return players.toString(event, debug) + (isNegated() ? "have not" : "have") + " found recipes " + recipes.toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/effects/EffCookingRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffCookingRecipeValues.java deleted file mode 100644 index 3629e1ccabe..00000000000 --- a/src/main/java/ch/njol/skript/effects/EffCookingRecipeValues.java +++ /dev/null @@ -1,148 +0,0 @@ -package ch.njol.skript.effects; - -import ch.njol.skript.Skript; -import ch.njol.skript.aliases.ItemType; -import ch.njol.skript.config.Node; -import ch.njol.skript.lang.Effect; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.skript.util.Timespan; -import ch.njol.util.Kleenean; -import org.bukkit.event.Event; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.RecipeChoice; -import org.jetbrains.annotations.Nullable; - -public class EffCookingRecipeValues extends Effect { - - enum CookingRecipeValues { - EXPERIENCE("set [the] recipe experience to %integer%", "recipe experience", CookingRecipeEvent.class, - "This can only be used when registering a Blasting, Furnace, Campfire, or Smoking Recipe."), - COOKINGTIME("set [the] recipe cook[ing] time to %timespan%", "recipe cooking time", CookingRecipeEvent.class, - "This can only be used when registering a Blasting, Furnace, Campfire, or Smoking Recipe."), - INPUT("set [the] recipe (input|source) [item] to %itemstack/itemtype%", "recipe input item", new Class[]{CookingRecipeEvent.class, StonecuttingRecipeEvent.class}, - "This can only be used when registering a Blasting, Furnace, Campfire, Smoking, or Stonecutting Recipe."); - - private String pattern, toString, error; - private Class eventClass; - private Class[] eventClasses; - - CookingRecipeValues(String pattern, String toString, Class eventClass, String error) { - this.pattern = pattern; - this.toString = toString; - this.eventClass = eventClass; - this.error = error; - } - - CookingRecipeValues(String pattern, String toString, Class[] eventClasses, String error) { - this.pattern = pattern; - this.toString = toString; - this.eventClasses = eventClasses; - this.error = error; - } - } - - private static CookingRecipeValues[] recipeValues = CookingRecipeValues.values(); - - static { - String[] patterns = new String[recipeValues.length]; - for (CookingRecipeValues value : recipeValues) { - patterns[value.ordinal()] = value.pattern; - } - Skript.registerEffect(EffCookingRecipeValues.class, patterns); - } - - private CookingRecipeValues selectedValue; - private @Nullable Expression itemExpr; - private @Nullable Expression intExpr; - private @Nullable Expression timeExpr; - private Node thisNode; - private String thisScript; - - @Override - @SuppressWarnings("unchecked") - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - selectedValue = recipeValues[matchedPattern]; - if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { - Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); - return false; - } - if (selectedValue.eventClass != null && !getParser().isCurrentEvent(selectedValue.eventClass)) { - Skript.error(selectedValue.error); - return false; - } else if (selectedValue.eventClasses != null) { - boolean classFound = false; - for (Class clazz : selectedValue.eventClasses) { - if (getParser().isCurrentEvent(clazz)) { - classFound = true; - break; - } - } - if (!classFound) { - Skript.error(selectedValue.error); - return false; - } - } - switch (selectedValue) { - case INPUT -> itemExpr = exprs[0]; - case EXPERIENCE -> intExpr = (Expression) exprs[0]; - case COOKINGTIME -> timeExpr = (Expression) exprs[0]; - } - thisNode = getParser().getNode(); - thisScript = getParser().getCurrentScript().getConfig().getFileName(); - return true; - } - - @Override - protected void execute(Event event) { - if (event instanceof CookingRecipeEvent cookingEvent) { - switch (selectedValue) { - case EXPERIENCE -> { - Integer experience = intExpr.getSingle(event); - if (experience != null) - cookingEvent.setExperience(experience.floatValue()); - } - case INPUT -> { - Object inputItem = itemExpr.getSingle(event); - if (inputItem instanceof ItemStack itemStack) { - cookingEvent.setInputItem(itemStack.getType()); - } else if (inputItem instanceof ItemType itemType) { - cookingEvent.setInputItem(itemType.getMaterial()); - } - } - case COOKINGTIME -> { - Timespan cookingTime = timeExpr.getSingle(event); - if (cookingTime != null) { - cookingEvent.setCookingTime((int) cookingTime.getAs(Timespan.TimePeriod.TICK)); - } - } - } - } else if (event instanceof StonecuttingRecipeEvent stonecuttingEvent) { - if (selectedValue == CookingRecipeValues.INPUT) { - RecipeChoice choice = null; - Object inputItem = itemExpr.getSingle(event); - if (inputItem instanceof ItemStack itemStack) { - choice = new RecipeChoice.ExactChoice(itemStack); - } else if (inputItem instanceof ItemType itemType) { - ItemStack stack = new ItemStack(itemType.getMaterial()); - stack.setItemMeta(itemType.getItemMeta()); - choice = new RecipeChoice.ExactChoice(stack); - } - if (choice != null) { - stonecuttingEvent.setInput(choice); - } - } - } - } - - private void customError(String message) { - Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return null; - } -} diff --git a/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java deleted file mode 100644 index f9ca56f502a..00000000000 --- a/src/main/java/ch/njol/skript/effects/EffCraftingRecipeValues.java +++ /dev/null @@ -1,133 +0,0 @@ -package ch.njol.skript.effects; - -import ch.njol.skript.Skript; -import ch.njol.skript.aliases.ItemType; -import ch.njol.skript.config.Node; -import ch.njol.skript.lang.Effect; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; -import ch.njol.util.Kleenean; -import org.bukkit.Material; -import org.bukkit.event.Event; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; - -public class EffCraftingRecipeValues extends Effect { - - enum CraftingRecipeValues { - INGREDIENTS("set [the] recipe ingredients to %itemstacks/itemtypes%", "recipe ingredients", - CraftingRecipeEvent.class, "This can only be used when registering a Shaped or Shapeless Recipe"), - FIRSTROW("set [the] recipe ingredients of (first|1st) row to %itemstacks/itemtypes%", "recipe ingredients first row", - ShapedRecipeEvent.class, "This can only be used when registering a Shaped Recipe."), - SECONDROW("set [the] recipe ingredients of (second|2nd) row to %itemstacks/itemtypes%", "recipe ingredients second row", - ShapedRecipeEvent.class, "This can only be used when registering a Shaped Recipe."), - THIRDROW("set [the] recipe ingredients of (third|3rd) row to %itemstacks/itemtypes%", "recipe ingredients third row", - ShapedRecipeEvent.class, "This can only be used when registering a Shaped Recipe."); - - private String pattern, toString, error; - private Class eventClass; - - CraftingRecipeValues(String pattern, String toString, Class eventClass, String error) { - this.pattern = pattern; - this.toString = toString; - this.eventClass = eventClass; - this.error = error; - } - } - - private static CraftingRecipeValues[] recipeValues = CraftingRecipeValues.values(); - - static { - String[] patterns = new String[recipeValues.length]; - for (CraftingRecipeValues value : recipeValues) { - patterns[value.ordinal()] = value.pattern; - } - Skript.registerEffect(EffCraftingRecipeValues.class, patterns); - } - - private CraftingRecipeValues selectedValue; - private Expression itemExpr; - private Node thisNode; - private String thisScript; - - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - selectedValue = recipeValues[matchedPattern]; - if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { - Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); - return false; - } - if (!getParser().isCurrentEvent(selectedValue.eventClass)) { - Skript.error(selectedValue.error); - return false; - } - itemExpr = exprs[0]; - thisNode = getParser().getNode(); - thisScript = getParser().getCurrentScript().getConfig().getFileName(); - return true; - } - - @Override - protected void execute(Event event) { - if (!(event instanceof CraftingRecipeEvent recipeEvent)) - return; - - switch (selectedValue) { - case INGREDIENTS -> { - Object[] items = itemExpr.getArray(event); - if (items.length > recipeEvent.getMaxIngredients()) { - customError("You can only provide up to " + recipeEvent.getMaxIngredients() + - " items when setting the ingredients for a '" + recipeEvent.getRecipeName() + "' recipe."); - recipeEvent.setErrorInEffect(); - return; - } - for (int i = 0; i < items.length; i++) { - Object thisItem = items[i]; - if (thisItem instanceof ItemStack itemStack && itemStack.getType() != Material.AIR) { - recipeEvent.setIngredients(i, itemStack); - } else if (thisItem instanceof ItemType itemType && itemType.getMaterial() != Material.AIR) { - ItemStack stack = new ItemStack(itemType.getMaterial()); - stack.setItemMeta(itemType.getItemMeta()); - recipeEvent.setIngredients(i, stack); - } - } - } - case FIRSTROW, SECONDROW, THIRDROW -> { - Object[] items = itemExpr.getArray(event); - if (items.length > recipeEvent.getMaxRowIngredients()) { - if (recipeEvent.getMaxRowIngredients() == 0) { - customError("You can not use '" + selectedValue.toString + "' when registering a '" + recipeEvent.getRecipeName() + "' recipe."); - } else { - customError("You can only provide up to " + recipeEvent.getMaxRowIngredients() + - " items when setting the ingredients of a row for a '" + recipeEvent.getRecipeName() + "' recipe."); - } - recipeEvent.setErrorInEffect(); - return; - } - for (int i = 0; i < items.length; i++) { - Object thisItem = items[i]; - int placement = (3 * (selectedValue.ordinal() - 1)) + i; - if (thisItem instanceof ItemStack itemStack && itemStack.getType() != Material.AIR) { - recipeEvent.setIngredients(placement, itemStack); - } else if (thisItem instanceof ItemType itemType && itemType.getMaterial() != Material.AIR) { - ItemStack stack = new ItemStack(itemType.getMaterial()); - stack.setItemMeta(itemType.getItemMeta()); - recipeEvent.setIngredients(placement, stack); - } - } - } - } - } - - private void customError(String message) { - Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return null; - } -} diff --git a/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java b/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java new file mode 100644 index 00000000000..cb036e87ac4 --- /dev/null +++ b/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java @@ -0,0 +1,71 @@ +package ch.njol.skript.effects; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Effect; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +@Name("Discover Recipe") +@Description("Discover or undiscover recipes for players.") +@Examples({ + "make player discover recipe \"my_recipe\"", + "make player undiscover recipe \"my_recipe\"", + "unlock recipe \"my_recipe\" for all players", + "lock recipe \"my_recipe\" for all players" +}) +@Since("INSERT VERSION") +public class EffDiscoverRecipe extends Effect { + + static { + Skript.registerEffect(EffDiscoverRecipe.class, + "make %players% (discover|unlock) recipe[s] %strings%", + "make %players% (undiscover|lock) recipe[s] %strings%", + "(discover|unlock) recipe[s] %strings% for %players%", + "(undiscover|lock) recipe[s] %strings% for %players%"); + } + + private Expression players; + private Expression recipes; + private boolean isDiscover = false; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + isDiscover = matchedPattern == 0 || matchedPattern == 2; + players = (Expression) (matchedPattern <= 1 ? exprs[0] : exprs[1]); + recipes = (Expression) (matchedPattern <= 1 ? exprs[1] : exprs[0]); + return true; + } + + @Override + protected void execute(Event event) { + for (Player player : players.getArray(event)) { + for (String recipe : recipes.getArray(event)) { + NamespacedKey key = NamespacedKey.fromString(recipe, Skript.getInstance()); + if (Bukkit.getRecipe(key) != null) { + if (isDiscover) + player.discoverRecipe(key); + else + player.undiscoverRecipe(key); + } else { + break; + } + } + } + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "make " + players.toString(event, debug) + (isDiscover ? " discover" : " undiscover") + " recipes " + recipes.toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java deleted file mode 100644 index b8b1c10f6e8..00000000000 --- a/src/main/java/ch/njol/skript/effects/EffRegisterRecipeValues.java +++ /dev/null @@ -1,133 +0,0 @@ -package ch.njol.skript.effects; - -import ch.njol.skript.Skript; -import ch.njol.skript.aliases.ItemType; -import ch.njol.skript.config.Node; -import ch.njol.skript.lang.Effect; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.util.Kleenean; -import org.bukkit.Material; -import org.bukkit.event.Event; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; - -public class EffRegisterRecipeValues extends Effect { - - enum RegisterRecipeValues { - RESULT("set [the] recipe result to %itemstack/itemtype%", "recipe result", RegisterRecipeEvent.class), - GROUP("set [the] recipe group to %string%", "recipe group", new Class[]{CraftingRecipeEvent.class, CookingRecipeEvent.class}, - "This can only be used when registering a Shaped, Shapeless, Blasting, Furnace, Campfire, or Smoking Recipe."); - - private String pattern, toString, error; - private Class eventClass; - private Class[] eventClasses; - - RegisterRecipeValues(String pattern, String toString, Class eventClass) { - this.pattern = pattern; - this.toString = toString; - this.eventClass = eventClass; - } - - RegisterRecipeValues(String pattern, String toString, Class[] eventClasses, String error) { - this.pattern = pattern; - this.toString = toString; - this.eventClasses = eventClasses; - this.error = error; - } - } - - private static RegisterRecipeValues[] recipeValues = RegisterRecipeValues.values(); - - static { - String[] patterns = new String[recipeValues.length]; - for (RegisterRecipeValues value : recipeValues) { - patterns[value.ordinal()] = value.pattern; - } - Skript.registerEffect(EffRegisterRecipeValues.class, patterns); - } - - private RegisterRecipeValues selectedValue; - private @Nullable Expression itemExpr; - private @Nullable Expression groupExpr; - private Node thisNode; - private String thisScript; - - @Override - @SuppressWarnings("unchecked") - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - selectedValue = recipeValues[matchedPattern]; - if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { - Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); - return false; - } - if (selectedValue.eventClass != null && !getParser().isCurrentEvent(selectedValue.eventClass)) { - Skript.error(selectedValue.error); - return false; - } else if (selectedValue.eventClasses != null) { - boolean classFound = false; - for (Class clazz : selectedValue.eventClasses) { - if (getParser().isCurrentEvent(clazz)) { - classFound = true; - break; - } - } - if (!classFound) { - Skript.error(selectedValue.error); - return false; - } - } - switch (selectedValue) { - case RESULT -> itemExpr = exprs[0]; - case GROUP -> groupExpr = (Expression) exprs[0]; - } - thisNode = getParser().getNode(); - thisScript = getParser().getCurrentScript().getConfig().getFileName(); - return true; - } - - @Override - protected void execute(Event event) { - if (!(event instanceof RegisterRecipeEvent recipeEvent)) - return; - - switch (selectedValue) { - case RESULT -> { - Object item = itemExpr.getSingle(event); - if (item instanceof ItemStack itemStack && itemStack.getType() != Material.AIR) { - recipeEvent.setResultItem(itemStack); - } else if (item instanceof ItemType itemType && itemType.getMaterial() != Material.AIR) { - ItemStack stack = new ItemStack(itemType.getMaterial()); - stack.setItemMeta(itemType.getItemMeta()); - recipeEvent.setResultItem(stack); - } else { - customError("The result item can not be null and/or air."); - recipeEvent.setErrorInEffect(); - } - } - case GROUP -> { - String group = groupExpr.getSingle(event); - if (group == null || group.isEmpty()) { - customError("The group can not be null or blank."); - return; - } - if (event instanceof CookingRecipeEvent cookingEvent) { - cookingEvent.setGroup(group); - } else if (event instanceof CraftingRecipeEvent craftingEvent) { - craftingEvent.setGroup(group); - } - } - } - } - - private void customError(String message) { - Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return null; - } -} diff --git a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java new file mode 100644 index 00000000000..f17bedf0476 --- /dev/null +++ b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java @@ -0,0 +1,53 @@ +package ch.njol.skript.effects; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Effect; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +@Name("Remove Recipe") +@Description({ + "Remove a recipe or multiple recipes from the server", + "Removing a recipe from a server will cause all players who have discovered the recipe to be undiscovered." +}) +@Examples("remove recipe \"my_recipe\" from the server") +@Since("INSERT VERSION") +public class EffRemoveRecipe extends Effect { + + static { + Skript.registerEffect(EffRemoveRecipe.class, + "(remove|delete|clear) recipe[s] %strings% [from the server]"); + } + + private Expression recipes; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + recipes = (Expression) exprs[0]; + return true; + } + + @Override + protected void execute(Event event) { + for (String recipe : recipes.getArray(event)) { + NamespacedKey key = NamespacedKey.fromString(recipe, Skript.getInstance()); + if (Bukkit.getRecipe(key) != null) + Bukkit.removeRecipe(key); + } + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "remove recipes " + recipes.toString(event, debug) + " from the server"; + } +} diff --git a/src/main/java/ch/njol/skript/effects/EffResetRecipes.java b/src/main/java/ch/njol/skript/effects/EffResetRecipes.java new file mode 100644 index 00000000000..1a91b5fad49 --- /dev/null +++ b/src/main/java/ch/njol/skript/effects/EffResetRecipes.java @@ -0,0 +1,41 @@ +package ch.njol.skript.effects; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Effect; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +@Name("Reset Recipes") +@Description("Resets recipes of server to default.") +@Examples("reset server recipes") +@Since("INSERT VERSION") +public class EffResetRecipes extends Effect { + + static { + Skript.registerEffect(EffResetRecipes.class, + "reset server recipes"); + } + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + return true; + } + + @Override + protected void execute(Event event) { + Bukkit.resetRecipes(); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "reset server recipes"; + } +} diff --git a/src/main/java/ch/njol/skript/effects/EffSmithingRecipeValues.java b/src/main/java/ch/njol/skript/effects/EffSmithingRecipeValues.java deleted file mode 100644 index 6196ac47c07..00000000000 --- a/src/main/java/ch/njol/skript/effects/EffSmithingRecipeValues.java +++ /dev/null @@ -1,109 +0,0 @@ -package ch.njol.skript.effects; - -import ch.njol.skript.Skript; -import ch.njol.skript.aliases.ItemType; -import ch.njol.skript.config.Node; -import ch.njol.skript.lang.Effect; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; -import ch.njol.util.Kleenean; -import org.bukkit.Material; -import org.bukkit.event.Event; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.RecipeChoice; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -public class EffSmithingRecipeValues extends Effect { - - enum SmithingRecipeValues { - BASE("set [the] recipe base item[s] to %itemstacks/itemtypes%", "recipe base item", SmithingRecipeEvent.class, - "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), - TEMPLATE("set [the] recipe template item[s] to %itemstacks/itemtypes%", "recipe template item", SmithingRecipeEvent.class, - "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), - ADDITION("set [the] recipe addition[al] item[s] to %itemstacks/itemtypes%", "recipe additional item", SmithingRecipeEvent.class, - "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."); - - private String pattern, toString, error; - private Class eventClass; - - SmithingRecipeValues(String pattern, String toString, Class eventClass, String error) { - this.pattern = pattern; - this.toString = toString; - this.eventClass = eventClass; - this.error = error; - } - } - - private static SmithingRecipeValues[] recipeValues = SmithingRecipeValues.values(); - - static { - String[] patterns = new String[recipeValues.length]; - for (SmithingRecipeValues value : recipeValues) { - patterns[value.ordinal()] = value.pattern; - } - Skript.registerEffect(EffSmithingRecipeValues.class, patterns); - } - - private SmithingRecipeValues selectedValue; - private Expression itemExpr; - private Node thisNode; - private String thisScript; - - @Override - public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - selectedValue = recipeValues[matchedPattern]; - if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { - Skript.error("You can only use '" + selectedValue.toString + "' in a Register Recipe Section."); - return false; - } - if (!getParser().isCurrentEvent(selectedValue.eventClass)) { - Skript.error(selectedValue.error); - return false; - } - itemExpr = exprs[0]; - thisNode = getParser().getNode(); - thisScript = getParser().getCurrentScript().getConfig().getFileName(); - return true; - } - - @Override - protected void execute(Event event) { - if (!(event instanceof SmithingRecipeEvent smithingEvent)) - return; - List items = new ArrayList<>(); - for (Object item : itemExpr.getArray(event)) { - if (item instanceof ItemStack itemStack) { - items.add(itemStack); - } else if (item instanceof ItemType itemType) { - ItemStack stack = new ItemStack(itemType.getMaterial()); - stack.setItemMeta(itemType.getItemMeta()); - items.add(stack); - } - } - if (items.isEmpty()) { - customError("You must provide valid items when setting the " + selectedValue.toString + " of a recipe."); - return; - } - RecipeChoice choice = new RecipeChoice.ExactChoice(items); - switch (selectedValue) { - case BASE -> smithingEvent.setBase(choice); - case TEMPLATE -> smithingEvent.setTemplate(choice); - case ADDITION -> smithingEvent.setAddition(choice); - } - } - - private void customError(String message) { - Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return null; - } -} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java new file mode 100644 index 00000000000..9f40ae208cf --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java @@ -0,0 +1,105 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.expressions.base.EventValueExpression; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.event.Event; +import org.bukkit.inventory.CookingRecipe; +import org.bukkit.inventory.CraftingRecipe; +import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.recipe.CookingBookCategory; +import org.bukkit.inventory.recipe.CraftingBookCategory; +import org.jetbrains.annotations.Nullable; + +public class ExprRecipeCategory extends PropertyExpression { + + static { + Skript.registerExpression(ExprRecipeCategory.class, String.class, ExpressionType.PROPERTY, + "[the] recipe crafting category [of %recipes%]", + "[the] recipe cooking category [of %recipes%]"); + } + + private boolean isCrafting = false; + private boolean isEvent = false; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + isCrafting = matchedPattern == 0; + if (!exprs[0].isDefault()) { + setExpr((Expression) exprs[0]); + } else { + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { + Skript.error("There is no 'recipe' in a " + getParser().getCurrentEventName() + " event."); + return false; + } + if (isCrafting && !getParser().isCurrentEvent(CraftingRecipeEvent.class)) { + Skript.error("This can only be used when registering a Shaped or Shapeless Recipe."); + return false; + } else if (!isCrafting && !getParser().isCurrentEvent(CookingRecipeEvent.class)) { + Skript.error("This can only be used when registering a Cooking, Blasting, Furnace, Campfire or Smoking Recipe."); + return false; + } + isEvent = true; + setExpr(new EventValueExpression<>(Recipe.class)); + } + return true; + } + + @Override + protected String @Nullable [] get(Event event, Recipe[] source) { + if (isEvent) + return null; + + return get(source, recipe -> { + if (isCrafting && recipe instanceof CraftingRecipe craftingRecipe) { + return craftingRecipe.getCategory().name(); + } else if (!isCrafting && recipe instanceof CookingRecipe cookingRecipe) { + return cookingRecipe.getCategory().name(); + } + return null; + }); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET && isEvent) { + if (isCrafting) + return CollectionUtils.array(CraftingBookCategory.class); + return CollectionUtils.array(CookingBookCategory.class); + } + + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + if (isCrafting && event instanceof RegisterRecipeEvent.CraftingRecipeEvent craftingEvent) { + if (!(delta[0] instanceof CraftingBookCategory category)) + return; + craftingEvent.setCategory(category); + } else if (!isCrafting && event instanceof RegisterRecipeEvent.CookingRecipeEvent cookingEvent) { + if (!(delta[0] instanceof CookingBookCategory category)) + return; + cookingEvent.setCategory(category); + } + } + + @Override + public Class getReturnType() { + return String.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return null; + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java new file mode 100644 index 00000000000..1605f720cfa --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java @@ -0,0 +1,99 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.EventValueExpression; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.CookingRecipeEvent; +import ch.njol.skript.util.Timespan; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.event.Event; +import org.bukkit.inventory.CookingRecipe; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +@Name("Recipe Cooking Time") +@Description("The cooking time of a Cooking, Blasting, Furnace, Campfire and Smoking Recipe.") +@Examples({ + "register a new cooking recipe with the name \"my_recipe\":", + "\tset the recipe input item to raw gold named \"Impure Gold\"", + "\tset the recipe cooking time to 10 seconds", + "\tset the recipe result to gold ingot named \"Pure Gold\"" +}) +@Since("INSERT VERSION") +public class ExprRecipeCookingTime extends PropertyExpression { + + static { + Skript.registerExpression(ExprRecipeCookingTime.class, Timespan.class, ExpressionType.PROPERTY, "[the] recipe cook[ing] time [of %recipes%]"); + } + + private boolean isEvent = false; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + if (!exprs[0].isDefault()) { + setExpr((Expression) exprs[0]); + } else { + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { + Skript.error("There is no 'recipe' in a " + getParser().getCurrentEventName() + " event."); + return false; + } + if (!getParser().isCurrentEvent(CookingRecipeEvent.class)) { + Skript.error("This can only be used when registering a Cooking, Blasting, Furnace, Campfire or Smoking Recipe."); + return false; + } + isEvent = true; + setExpr(new EventValueExpression<>(Recipe.class)); + } + return true; + } + + @Override + protected Timespan @Nullable [] get(Event event, Recipe[] source) { + if (isEvent) + return null; + + return get(source, recipe -> { + if (recipe instanceof CookingRecipe cookingRecipe) { + return new Timespan(Timespan.TimePeriod.TICK, cookingRecipe.getCookingTime()); + } + return null; + }); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET && isEvent) + return CollectionUtils.array(Timespan.class); + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + if (!(event instanceof CookingRecipeEvent cookingEvent)) + return; + + Timespan timespan = (Timespan) delta[0]; + cookingEvent.setCookingTime((int) timespan.getAs(Timespan.TimePeriod.TICK)); + } + + @Override + public Class getReturnType() { + return Timespan.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the recipe cooking time of " + getExpr().toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java new file mode 100644 index 00000000000..dcd43426374 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java @@ -0,0 +1,98 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.EventValueExpression; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.CookingRecipeEvent; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.event.Event; +import org.bukkit.inventory.CookingRecipe; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +@Name("Recipe Experience") +@Description("The experience of a Cooking, Blasting, Furnace, Campfire, and Smoking Recipe.") +@Examples({ + "register a new blasting recipe with the name \"my_recipe\":", + "\tset the recipe input item to a raw copper named \"Impure Copper\"", + "\tset the recipe experience to 20", + "\tset the recipe result to copper ingot named \"Pure Copper\"" +}) +@Since("INSERT VERSION") +public class ExprRecipeExperience extends PropertyExpression { + + static { + Skript.registerExpression(ExprRecipeExperience.class, Float.class, ExpressionType.PROPERTY, "[the] recipe [e]xp[erience] [of %recipes%]"); + } + + private boolean isEvent = false; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + if (!exprs[0].isDefault()) { + setExpr((Expression) exprs[0]); + } else { + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { + Skript.error("There is no 'recipe' in a " + getParser().getCurrentEventName() + " event."); + return false; + } + if (!getParser().isCurrentEvent(CookingRecipeEvent.class)) { + Skript.error("This can only be used when registering a Cooking, Blasting, Furnace, Campfire or Smoking Recipe."); + return false; + } + isEvent = true; + setExpr(new EventValueExpression<>(Recipe.class)); + } + return true; + } + + @Override + protected Float @Nullable [] get(Event event, Recipe[] source) { + if (isEvent) + return null; + + return get(source, recipe -> { + if (recipe instanceof CookingRecipe cookingRecipe) { + return cookingRecipe.getExperience(); + } + return null; + }); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET && isEvent) + return CollectionUtils.array(Float.class); + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + if (!(event instanceof CookingRecipeEvent cookingEvent)) + return; + + float experience = (float) delta[0]; + cookingEvent.setExperience(experience); + } + + @Override + public Class getReturnType() { + return Float.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the recipe experience of " + getExpr().toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java new file mode 100644 index 00000000000..8a9ead51007 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java @@ -0,0 +1,104 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.EventValueExpression; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.event.Event; +import org.bukkit.inventory.CookingRecipe; +import org.bukkit.inventory.CraftingRecipe; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +@Name("Recipe Group") +@Description("The recipe group of a Shaped, Shapeless, Cooking, Blasting, Furnace, Campfire and Smoking Recipe.") +@Examples({ + "register a new shapeless recipe with the name \"my_recipe\":", + "\tset the recipe ingredients to 3 diamonds, 3 emeralds and 3 netherite ingots", + "\tset the recipe group to \"my group\"", + "\tset the recipe result to nether star" +}) +@Since("INSERT VERSION") +public class ExprRecipeGroup extends PropertyExpression { + + static { + Skript.registerExpression(ExprRecipeGroup.class, String.class, ExpressionType.PROPERTY, "[the] recipe group [of %recipes%]"); + } + + private boolean isEvent = false; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + if (!exprs[0].isDefault()) { + setExpr((Expression) exprs[0]); + } else { + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { + Skript.error("There is no 'recipe' in a " + getParser().getCurrentEventName() + " event."); + return false; + } + if (!getParser().isCurrentEvent(CraftingRecipeEvent.class, CookingRecipeEvent.class)) { + Skript.error("This can only be used when registering a Shaped, Shapeless, Cooking, Blasting, Furnace, Campfire or Smoking Recipe."); + return false; + } + isEvent = true; + setExpr(new EventValueExpression<>(Recipe.class)); + } + return true; + } + + @Override + protected String[] get(Event event, Recipe[] source) { + if (isEvent) + return null; + + return get(source, recipe -> { + if (recipe instanceof CraftingRecipe craftingRecipe) { + return craftingRecipe.getGroup(); + } else if (recipe instanceof CookingRecipe cookingRecipe) { + return cookingRecipe.getGroup(); + } + return null; + }); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET && isEvent) + return CollectionUtils.array(String.class); + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + String group = (String) delta[0]; + if (group.isEmpty()) + return; + + if (event instanceof CookingRecipeEvent cookingEvent) + cookingEvent.setGroup(group); + else if (event instanceof CraftingRecipeEvent craftingEvent) + craftingEvent.setGroup(group); + } + + @Override + public Class getReturnType() { + return String.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the recipe group of " + getExpr().toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java new file mode 100644 index 00000000000..5c48207547f --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java @@ -0,0 +1,346 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.config.Node; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.expressions.base.EventValueExpression; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.Material; +import org.bukkit.event.Event; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; +import org.bukkit.inventory.*; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +@Name("Recipe Ingredients") +@Description({ + "The ingredients of a Shaped or Shapeless recipe", + "The ingredients of a row for a Shaped recipe", + "The input item of a Cooking, Blasting, Furnace, Campfire, Smoking and Stonecutting recipe", + "The base, template, addition items of a Smithing Transform and Smithing Trim recipe" +}) +@Examples({ + "register a new shaped recipe with the name \"my_recipe\":", + "\tset the recipe ingredients to diamond, air, diamond, air, emerald, air, diamond, air and diamond", + "\t#OR", + "\tset the recipe ingredients of the 1st row to diamond, air and diamond", + "\tset the recipe ingredients of second row to air, emerald and air", + "\tset the recipe ingredients of the third row to diamond, air and diamond", + "\tset the recipe result to beacon", + "", + "create a shapeless recipe with namespace \"my_recipe\":", + "\tset recipe ingredients to iron ingot, gold ingot, iron ingot, nether star, 5 obsidian, nether star, iron ingot, gold ingot and iron ingot", + "\tset recipe resulting item to beacon named \"OP Beacon\"", + "", + "register new cooking recipe with the namespacekey \"my_recipe\":", + "\tset the recipe input item to netherite ingot named \"Impure Netherite\"", + "\tset the recipe result item to netherite ingot named \"Pure Netherite\"", + "", + "create a new smithing transform recipe with name \"my_recipe\":", + "\tset the recipe base item to diamond helmet", + "\tset the recipe template item to paper named \"Blueprint\"", + "\tset the recipe addition item to netherite ingot named \"Pure Netherite\"", + "\tset the recipe result to netherite helmet named \"Pure Helmet\"" +}) +public class ExprRecipeIngredients extends PropertyExpression { + + enum RecipePattern { + INGREDIENTS("recipe ingredients", "recipe ingredients", CraftingRecipeEvent.class, "This can only be used when registering a Shaped or Shapeless Recipe."), + FIRSTROW("recipe ingredients of [the] (1st|first) row", "recipe ingredients of the first row", ShapedRecipeEvent.class, + "This can only be used when registering a Shaped Recipe."), + SECONDROW("recipe ingredients of [the] (2nd|second) row", "recipe ingredients of the first row", ShapedRecipeEvent.class, + "This can only be used when registering a Shaped Recipe."), + THIRDROW("recipe ingredients of [the] (3rd|third) row", "recipe ingredients of the first row", ShapedRecipeEvent.class, + "This can only be used when registering a Shaped Recipe."), + INPUT("recipe (input|source) [item]", "recipe input item", new Class[]{CookingRecipeEvent.class, StonecuttingRecipeEvent.class}, + "This can only be used when registering a Cooking, Blasting, Furnace, Campfire, Smoking or Stonecutting Recipe."), + BASE("recipe base item[s]", "recipe base items", SmithingRecipeEvent.class, + "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), + TEMPLATE("recipe template item[s]", "recipe template items", SmithingRecipeEvent.class, + "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), + ADDITION("recipe addition[al] item[s]", "recipe additional items", SmithingRecipeEvent.class, + "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."); + + + private String pattern, toString, error; + private Class eventClass; + private Class[] eventClasses; + + RecipePattern(String pattern, String toString, Class eventClass, String error) { + this.pattern = "[the] " + pattern + " [of %recipes%]"; + this.toString = toString; + this.eventClass = eventClass; + this.error = error; + } + + RecipePattern(String pattern, String toString, Class[] eventClasses, String error) { + this.pattern = "[the] " + pattern + " [of %recipes%]"; + this.toString = toString; + this.eventClasses = eventClasses; + this.error = error; + } + } + + private static final RecipePattern[] recipePatterns = RecipePattern.values(); + + static { + String[] patterns = new String[recipePatterns.length]; + for (RecipePattern pattern : recipePatterns) { + patterns[pattern.ordinal()] = pattern.pattern; + } + Skript.registerExpression(ExprRecipeIngredients.class, ItemStack.class, ExpressionType.PROPERTY, patterns); + } + + private boolean isEvent = false; + private RecipePattern selectedChoice; + private Node thisNode; + private String thisScript; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + selectedChoice = recipePatterns[matchedPattern]; + if (!exprs[0].isDefault()) { + setExpr((Expression) exprs[0]); + } else { + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { + Skript.error("There is no 'recipe' in a " + getParser().getCurrentEventName() + " event."); + return false; + } + if (selectedChoice.eventClass != null) { + if (!getParser().isCurrentEvent(selectedChoice.eventClass)) { + Skript.error(selectedChoice.error); + return false; + } + } else if (selectedChoice.eventClasses != null) { + boolean classFound = false; + for (Class eventClass : selectedChoice.eventClasses) { + if (getParser().isCurrentEvent(eventClass)) { + classFound = true; + break; + } + } + if (!classFound) { + Skript.error(selectedChoice.error); + return false; + } + } + isEvent = true; + setExpr(new EventValueExpression<>(Recipe.class)); + } + thisNode = getParser().getNode(); + thisScript = getParser().getCurrentScript().getConfig().getFileName(); + return true; + } + + @Override + protected ItemStack @Nullable [] get(Event event, Recipe[] source) { + if (isEvent) + return null; + + List ingredients = new ArrayList<>(); + for (Recipe recipe : source) { + switch (selectedChoice) { + case INGREDIENTS -> { + if (recipe instanceof ShapedRecipe shapedRecipe) { + Map ingredientMap = shapedRecipe.getIngredientMap(); + ingredients.addAll(ingredientMap.values().stream() + .map(itemStack -> { + if (itemStack == null) return new ItemStack(Material.AIR); + return itemStack; + }).toList()); + } else if (recipe instanceof ShapelessRecipe shapelessRecipe) { + ingredients.addAll(shapelessRecipe.getIngredientList()); + } + } + case FIRSTROW, SECONDROW, THIRDROW -> { + if (recipe instanceof ShapedRecipe shapedRecipe) { + String[] shape = shapedRecipe.getShape(); + Map ingredientMap = shapedRecipe.getIngredientMap(); + String row = shape[selectedChoice.ordinal() - 1]; + for (Character character : row.toCharArray()) { + ItemStack stack = ingredientMap.get(character); + if (stack == null) stack = new ItemStack(Material.AIR); + ingredients.add(stack); + } + } + } + case BASE, TEMPLATE, ADDITION -> { + if (recipe instanceof SmithingRecipe smithingRecipe) { + RecipeChoice choice = switch (selectedChoice) { + case BASE -> smithingRecipe.getBase(); + case TEMPLATE -> { + if (recipe instanceof SmithingTransformRecipe transformRecipe) yield transformRecipe.getTemplate(); + else if (recipe instanceof SmithingTrimRecipe trimRecipe) yield trimRecipe.getTemplate(); + yield null; + } + case ADDITION -> smithingRecipe.getAddition(); + default -> null; + }; + if (choice instanceof RecipeChoice.ExactChoice exactChoice) { + ingredients.addAll(exactChoice.getChoices()); + } else if (choice instanceof RecipeChoice.MaterialChoice materialChoice) { + ingredients.addAll( + materialChoice.getChoices().stream().map(ItemStack::new).toList() + ); + } + } + } + case INPUT -> { + RecipeChoice choice = null; + if (recipe instanceof CookingRecipe cookingRecipe) { + choice = cookingRecipe.getInputChoice(); + } else if (recipe instanceof StonecuttingRecipe stonecuttingRecipe) { + choice = stonecuttingRecipe.getInputChoice(); + } + if (choice instanceof RecipeChoice.ExactChoice exactChoice) { + ingredients.addAll(exactChoice.getChoices()); + } else if (choice instanceof RecipeChoice.MaterialChoice materialChoice) { + ingredients.addAll(materialChoice.getChoices().stream().map(ItemStack::new).toList()); + } + } + } + } + return ingredients.toArray(ItemStack[]::new); + } + + @Override + public Class getReturnType() { + return ItemStack.class; + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET && isEvent) + return CollectionUtils.array(ItemType[].class); + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + if (!(event instanceof RegisterRecipeEvent recipeEvent)) + return; + + Map items = new HashMap<>(); + for (int i = 0; i < delta.length; i++) { + Object object = delta[i]; + if (object instanceof ItemType itemType) { + List thisItems = new ArrayList<>(); + itemType.getAll().forEach(thisItems::add); + items.put(i, thisItems.toArray(ItemStack[]::new)); + } + } + + switch (selectedChoice) { + case INGREDIENTS -> { + if (!(event instanceof CraftingRecipeEvent craftingEvent)) + return; + + if (items.size() > 9) { + customError("You can only provide up to 9 items when setting the ingredients for a '" + recipeEvent.getRecipeName() + "' recipe."); + recipeEvent.setErrorInEffect(); + return; + } + for (Map.Entry entry : items.entrySet()) { + ItemStack[] ingredients = entry.getValue(); + if (Arrays.stream(ingredients).anyMatch(itemStack -> itemStack.getType().isAir())) { + if (ingredients.length > 1) { + customError("You can not provide air with a list of other items."); + recipeEvent.setErrorInEffect(); + return; + } else { + continue; + } + } + RecipeChoice choice = new RecipeChoice.ExactChoice(ingredients); + craftingEvent.setIngredients(entry.getKey(), choice); + } + } + case FIRSTROW, SECONDROW, THIRDROW -> { + if (!(event instanceof ShapedRecipeEvent shapedEvent)) + return; + if (items.size() > 3) { + customError("You can only provide up to 3 items when setting the ingredients of a row for a '" + recipeEvent.getRecipeName() + "' recipe."); + recipeEvent.setErrorInEffect(); + return; + } + for (Map.Entry entry : items.entrySet()) { + ItemStack[] ingredients = entry.getValue(); + if (Arrays.stream(ingredients).anyMatch(itemStack -> itemStack.getType().isAir())) { + if (ingredients.length > 1) { + customError("You can not provide 'air' with a list of other items."); + recipeEvent.setErrorInEffect(); + return; + } else { + continue; + } + } + RecipeChoice choice = new RecipeChoice.ExactChoice(ingredients); + shapedEvent.setIngredients(((3 * (selectedChoice.ordinal() - 1)) + entry.getKey()), choice); + } + } + case BASE, TEMPLATE, ADDITION -> { + if (!(event instanceof SmithingRecipeEvent smithingEvent)) + return; + List stackList = new ArrayList<>(); + items.entrySet().stream().forEach(entry -> stackList.addAll(Arrays.asList(entry.getValue()))); + if (stackList.stream().anyMatch(itemStack -> itemStack.getType().isAir())) { + customError("You can not provide 'air' with this expression."); + recipeEvent.setErrorInEffect(); + return; + } + RecipeChoice choice = new RecipeChoice.ExactChoice(stackList); + switch (selectedChoice) { + case BASE -> smithingEvent.setBase(choice); + case TEMPLATE -> smithingEvent.setTemplate(choice); + case ADDITION -> smithingEvent.setAddition(choice); + } + } + case INPUT -> { + List stackList = new ArrayList<>(); + items.entrySet().stream().forEach(entry -> stackList.addAll(Arrays.asList(entry.getValue()))); + if (stackList.stream().anyMatch(itemStack -> itemStack.getType().isAir())) { + customError("You can not provide 'air' with this expression."); + recipeEvent.setErrorInEffect(); + return; + } + RecipeChoice choice = new RecipeChoice.ExactChoice(stackList); + if (recipeEvent instanceof CookingRecipeEvent cookingEvent) { + cookingEvent.setInput(choice); + } else if (recipeEvent instanceof StonecuttingRecipeEvent stonecuttingEvent) { + stonecuttingEvent.setInput(choice); + } + } + } + } + + private void customError(String message) { + Skript.info("Line " + thisNode.getLine() + ": (" + thisScript + ")\n\t" + message + "\n\t" + thisNode.getKey()); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the recipe " + switch (selectedChoice) { + case INGREDIENTS -> "ingredients"; + case FIRSTROW -> "ingredients of first row"; + case SECONDROW -> "ingredients of second row"; + case THIRDROW -> "ingredients of third row"; + case BASE -> "base item"; + case TEMPLATE -> "template item"; + case ADDITION -> "addition item"; + case INPUT -> "input item"; + } + " of " + getExpr().toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java new file mode 100644 index 00000000000..b8a05c5c888 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java @@ -0,0 +1,87 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.EventValueExpression; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +@Name("Recipe Result") +@Description("The result item for a recipe") +@Examples({ + "register a new shaped recipe with the name \"my_recipe\":", + "\tset the recipe ingredients of 1st row to diamond, air and diamond", + "\tset the recipe result to diamond sword named \"Chosen One\"" +}) +@Since("INSERT VERSION") +public class ExprRecipeResult extends PropertyExpression { + + static { + Skript.registerExpression(ExprRecipeResult.class, ItemStack.class, ExpressionType.PROPERTY, "[the] recipe result[ing] [item] [of %recipes%]"); + } + + private boolean isEvent = false; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + if (!exprs[0].isDefault()) { + setExpr((Expression) exprs[0]); + } else { + if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { + Skript.error("There is no 'recipe' in a " + getParser().getCurrentEventName() + " event."); + return false; + } + isEvent = true; + setExpr(new EventValueExpression<>(Recipe.class)); + } + return true; + } + + @Override + protected ItemStack @Nullable [] get(Event event, Recipe[] source) { + if (isEvent) + return null; + + return get(source, recipe -> recipe.getResult()); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (mode == ChangeMode.SET && isEvent) + return CollectionUtils.array(ItemStack.class); + return null; + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + if (!(event instanceof RegisterRecipeEvent recipeEvent)) + return; + + ItemStack result = (ItemStack) delta[0]; + recipeEvent.setResultItem(result); + } + + @Override + public Class getReturnType() { + return ItemStack.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the recipe result item of " + getExpr().toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 771bd493efc..438fafaac4c 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -3,11 +3,17 @@ import ch.njol.skript.Skript; import ch.njol.skript.config.Node; import ch.njol.skript.config.SectionNode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.Section; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.Trigger; import ch.njol.skript.lang.TriggerItem; +import ch.njol.skript.registrations.EventValues; +import ch.njol.skript.util.Getter; import ch.njol.skript.util.RegisterRecipeEvent; import ch.njol.skript.util.RegisterRecipeEvent.RecipeTypes; import ch.njol.skript.util.RegisterRecipeEvent.*; @@ -26,18 +32,64 @@ import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; +@Name("Register Recipe") +@Description({ + "Create a custom recipe for any of the following types:", + "Shaped, Shapeless, Cooking, Blasting, Furnace, Campfire, Smoking, Smithing Transform, Smithing Trim or Stonecutting", + "NOTES:", + "All recipes except Smithing Trim require a 'result item'", + "Shaped and Shapeless Ingredients allows custom items only on Paper", + "Shaped and Shapeless have a maximum of 9 and minimum requirement of 2 ingredients", + "Blasting, Furnace, Campfire and Smoking all fall under Cooking", + "Groups only apply to Shaped, Shapeless and Cooking Recipes", + "Category only applies to Shaped, Shapeless and Cooking Recipes" +}) +@Examples({ + "register a new shaped recipe with the name \"my_recipe\":", + "\tset the recipe ingredients to diamond, air, diamond, air, emerald, air, diamond and diamond #OR", + "\tset recipe ingredients of 1st row to diamond, air and diamond", + "\tset recipe ingredients of second row to air, emerald and air", + "\tset recipe ingredients of 3rd row to diamond, air and diamond", + "\tset recipe group to \"my group\"", + "\tset recipe category to crafting.misc", + "\tset recipe result to diamond sword named \"Heavenly Sword\"", + "", + "register a shapeless recipe with namespace \"my_recipe\":", + "\tset recipe ingredients to 3 diamonds, 3 emeralds and 3 iron ingots", + "\tset the recipe group to \"custom group\"", + "\tset the recipe category to crafting category misc", + "\tset the recipe result item to diamond helmet named \"Heavenly Helm\"", + "", + "#Blasting, Furnace, Campfire and Smoking follow same format as Cooking", + "create new cooking recipe with the namespacekey \"my_recipe\":", + "\tset the recipe experience to 5", + "\tset the recipe cooking time to 10 seconds", + "\tset the recipe group to \"custom group\"", + "\tset the recipe category to cooking.misc", + "\tset the recipe input item to coal named \"Ash\"", + "\tset the recipe resulting item to gunpowder named \"Dust\"", + "", + "#Smithing Trim follows the same format, except for 'result item'", + "create smithing transform recipe with name \"my_recipe\":", + "\tset the recipe base item to diamond", + "\tset the recipe template item to emerald", + "\tset the recipe additional item to netherite ingot", + "\tset the recipe result to ...", + "", + "create a new stonecutting recipe with namespacekey \"my_recipe\":", + "\tset the recipe source item to cobblestone named \"Cracked Stone\"", + "\tset the recipe result to stone named \"Refurnished Stone\"" +}) +@Since("INSERT VERSION") public class SecRegisterRecipe extends Section { /* TODO: - set category effect - CondDiscoveredRecipe - EffDiscoverRecipe Tests - Maybe CraftingBookCategory and CookingBookCategory lang + ExprAllRecipes (Including of recipe type) + ExprRecipeName (Get recipe via name) + ExprRecipeFor (Get all recipes for item) + Rewrite Sec to provide a valid recipe as event value (Including RegisterRecipeEvent.java) */ - private static final boolean SUPPORT_SHAPED_ITEMSTACK = Skript.methodExists(ShapedRecipe.class, "setIngredient", Character.class, ItemStack.class); - private static final boolean SUPPORT_SHAPELESS_ITEMSTACK = Skript.methodExists(ShapelessRecipe.class, "addIngredient", ItemStack.class); - private static final RecipeTypes[] recipeTypes = RecipeTypes.values(); static { @@ -46,6 +98,12 @@ public class SecRegisterRecipe extends Section { patterns[type.ordinal()] = "(register|create) [a] [new] " + type.getPattern() + " recipe with [the] name[space[key]] %string%"; } Skript.registerSection(SecRegisterRecipe.class, patterns); + EventValues.registerEventValue(RegisterRecipeEvent.class, Recipe.class, new Getter() { + @Override + public @Nullable Recipe get(RegisterRecipeEvent recipe) { + return null; + } + }, EventValues.TIME_NOW); } private RecipeTypes recipeType; @@ -96,7 +154,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye switch (recipeType) { case SHAPED, SHAPELESS -> { if (recipeEvent instanceof CraftingRecipeEvent craftingRecipe) { - ItemStack[] ingredients = craftingRecipe.getIngredients(); + RecipeChoice[] ingredients = craftingRecipe.getIngredients(); if (ingredients.length < 2 || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < 2) { customError("You must have at least 2 ingredients when registering a '" + recipeType.getToString() + "' recipe."); return super.walk(event, false); @@ -111,12 +169,12 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye } case COOKING, BLASTING, FURNACE, CAMPFIRE, SMOKING -> { if (recipeEvent instanceof CookingRecipeEvent cookingRecipe) { - Material inputItem = cookingRecipe.getInputItem(); + RecipeChoice input = cookingRecipe.getInput(); String group = cookingRecipe.getGroup(); CookingBookCategory category = cookingRecipe.getCategory(); int cookingTime = cookingRecipe.getCookingTime(); float experience = cookingRecipe.getExperience(); - createCookingRecipe(recipeType, key, result, inputItem, group, category, cookingTime, experience); + createCookingRecipe(recipeType, key, result, input, group, category, cookingTime, experience); } } case SMITHINGTRANSFORM, SMITHINGTRIM -> { @@ -144,7 +202,7 @@ private void completeRecipe(NamespacedKey key, Recipe recipe) { Bukkit.addRecipe(recipe); } - private void createShapedRecipe(NamespacedKey key, ItemStack result, ItemStack[] ingredients, String group, CraftingBookCategory category) { + private void createShapedRecipe(NamespacedKey key, ItemStack result, RecipeChoice[] ingredients, String group, CraftingBookCategory category) { ShapedRecipe shapedRecipe = new ShapedRecipe(key, result); if (category != null) shapedRecipe.setCategory(category); @@ -153,43 +211,33 @@ private void createShapedRecipe(NamespacedKey key, ItemStack result, ItemStack[] Character[] characters = new Character[]{'a','b','c','d','e','f','g','h','i'}; shapedRecipe.shape("abc","def","ghi"); for (int i = 0; i < ingredients.length; i++) { - ItemStack thisItem = ingredients[i]; - if (thisItem != null) { - if (SUPPORT_SHAPED_ITEMSTACK) { - shapedRecipe.setIngredient(characters[i], thisItem); - } else { - shapedRecipe.setIngredient(characters[i], thisItem.getType()); - } - } + RecipeChoice thisChoice = ingredients[i]; + if (thisChoice != null) + shapedRecipe.setIngredient(characters[i], thisChoice); } completeRecipe(key, shapedRecipe); } - private void createShapelessRecipe(NamespacedKey key, ItemStack result, ItemStack[] ingredients, String group, CraftingBookCategory category) { + private void createShapelessRecipe(NamespacedKey key, ItemStack result, RecipeChoice[] ingredients, String group, CraftingBookCategory category) { ShapelessRecipe shapelessRecipe = new ShapelessRecipe(key, result); if (category != null) shapelessRecipe.setCategory(category); if (group != null && !group.isEmpty()) shapelessRecipe.setGroup(group); for (int i = 0; i < ingredients.length; i++) { - ItemStack thisItem = ingredients[i]; - if (thisItem != null) { - if (SUPPORT_SHAPELESS_ITEMSTACK) { - shapelessRecipe.addIngredient(thisItem); - } else { - shapelessRecipe.addIngredient(thisItem.getAmount(), thisItem.getType()); - } - } + RecipeChoice thisChoice = ingredients[i]; + if (thisChoice != null) + shapelessRecipe.addIngredient(thisChoice); } completeRecipe(key, shapelessRecipe); } - private void createCookingRecipe(RecipeTypes recipeType, NamespacedKey key, ItemStack result, Material inputItem, String group, CookingBookCategory category, int cookingTime, float experience) { + private void createCookingRecipe(RecipeTypes recipeType, NamespacedKey key, ItemStack result, RecipeChoice input, String group, CookingBookCategory category, int cookingTime, float experience) { var recipe = switch (recipeType) { - case BLASTING -> new BlastingRecipe(key, result, inputItem, experience, cookingTime); - case CAMPFIRE -> new CampfireRecipe(key, result, inputItem, experience, cookingTime); - case FURNACE -> new FurnaceRecipe(key, result, inputItem, experience, cookingTime); - case SMOKING -> new SmokingRecipe(key, result, inputItem, experience, cookingTime); + case BLASTING -> new BlastingRecipe(key, result, input, experience, cookingTime); + case CAMPFIRE -> new CampfireRecipe(key, result, input, experience, cookingTime); + case FURNACE -> new FurnaceRecipe(key, result, input, experience, cookingTime); + case SMOKING -> new SmokingRecipe(key, result, input, experience, cookingTime); default -> null; }; if (recipe == null) @@ -203,7 +251,7 @@ private void createCookingRecipe(RecipeTypes recipeType, NamespacedKey key, Item private void createSmithingRecipe(RecipeTypes recipeType, NamespacedKey key, ItemStack result, RecipeChoice base, RecipeChoice template, RecipeChoice addition) { if (base == null || template == null || addition == null) { - customError("Unable to create " + recipeType.getToString() + " recipe, missing data."); + customError("Unable to create '" + recipeType.getToString() + "' recipe, missing data."); return; } var recipe = switch (recipeType) { @@ -218,7 +266,7 @@ private void createSmithingRecipe(RecipeTypes recipeType, NamespacedKey key, Ite private void createStonecuttingRecipe(NamespacedKey key, ItemStack result, RecipeChoice input) { if (input == null) { - customError("Unable to create a stonecutting recipe, missing data."); + customError("Unable to create a 'stonecutting' recipe, missing data."); return; } StonecuttingRecipe recipe = new StonecuttingRecipe(key, result, input); diff --git a/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java b/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java index 947524ba333..cd7bd4698f4 100644 --- a/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java +++ b/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java @@ -3,8 +3,7 @@ import org.bukkit.Material; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.RecipeChoice; +import org.bukkit.inventory.*; import org.bukkit.inventory.recipe.CookingBookCategory; import org.bukkit.inventory.recipe.CraftingBookCategory; import org.jetbrains.annotations.NotNull; @@ -12,34 +11,27 @@ public class RegisterRecipeEvent extends Event { public enum RecipeTypes { - SHAPED("shaped [crafting]", 9, 3, "shaped", CraftingRecipeEvent.ShapedRecipeEvent.class), - SHAPELESS("shapeless [crafting]", 9, 0, "shapeless", CraftingRecipeEvent.ShapelessRecipeEvent.class), - BLASTING("blast[ing]", "blasting", CookingRecipeEvent.BlastingRecipeEvent.class), - CAMPFIRE("campfire", "campfire", CookingRecipeEvent.CampfireRecipeEvent.class), - FURNACE("furnace", "furnace", CookingRecipeEvent.FurnaceRecipeEvent.class), - SMOKING("smoking", "smoking", CookingRecipeEvent.SmokingRecipeEvent.class), - COOKING("cooking", "cooking", CookingRecipeEvent.class), - SMITHINGTRANSFORM("smith[ing] transform", "smithing transform", SmithingRecipeEvent.SmithingTransformRecipeEvent.class), - SMITHINGTRIM("smith[ing] trim", "smithing trim", SmithingRecipeEvent.SmithingTrimRecipeEvent.class), - STONECUTTING("stone cutting", "stone cutting", StonecuttingRecipeEvent.class); + SHAPED("shaped [crafting]", "shaped", CraftingRecipeEvent.ShapedRecipeEvent.class, ShapedRecipe.class), + SHAPELESS("shapeless [crafting]", "shapeless", CraftingRecipeEvent.ShapelessRecipeEvent.class, ShapelessRecipe.class), + BLASTING("blast[ing]", "blasting", CookingRecipeEvent.BlastingRecipeEvent.class, BlastingRecipe.class), + CAMPFIRE("campfire", "campfire", CookingRecipeEvent.CampfireRecipeEvent.class, CampfireRecipe.class), + FURNACE("furnace", "furnace", CookingRecipeEvent.FurnaceRecipeEvent.class, FurnaceRecipe.class), + SMOKING("smoking", "smoking", CookingRecipeEvent.SmokingRecipeEvent.class, SmokingRecipe.class), + COOKING("cooking", "cooking", CookingRecipeEvent.class, CookingRecipe.class), + SMITHINGTRANSFORM("smith[ing] transform", "smithing transform", SmithingRecipeEvent.SmithingTransformRecipeEvent.class, SmithingTransformRecipe.class), + SMITHINGTRIM("smith[ing] trim", "smithing trim", SmithingRecipeEvent.SmithingTrimRecipeEvent.class, SmithingTrimRecipe.class), + STONECUTTING("stone cutting", "stone cutting", StonecuttingRecipeEvent.class, StonecuttingRecipe.class); private String pattern, toString; - private int maxIngredients, maxRowIngredients; private Class eventClass; + private Class recipeClass; - RecipeTypes(String pattern, int maxIngredients, int maxRowIngredients, String toString, Class eventClass) { - this.pattern = pattern; - this.maxIngredients = maxIngredients; - this.maxRowIngredients = maxRowIngredients; - this.toString = toString; - this.eventClass = eventClass; - } - - RecipeTypes(String pattern, String toString, Class eventClass) { + RecipeTypes(String pattern, String toString, Class eventClass, Class recipeClass) { this.pattern = pattern; this.toString = toString; this.eventClass = eventClass; + this.recipeClass = recipeClass; } public String getPattern() { @@ -54,14 +46,6 @@ public String getToString() { return toString; } - public int getMaxIngredients() { - return maxIngredients; - } - - public int getMaxRowIngredients() { - return maxRowIngredients; - } - } private ItemStack resultItem; @@ -93,11 +77,15 @@ public RecipeTypes getRecipeType() { } public String getRecipeName() { - return recipeType.getToString(); + return recipeType.toString; + } + + public Class getRecipeClass() { + return recipeType.recipeClass; } public static class CraftingRecipeEvent extends RegisterRecipeEvent { - private ItemStack[] ingredients = new ItemStack[9]; + private RecipeChoice[] ingredients = new RecipeChoice[9]; private CraftingBookCategory category = CraftingBookCategory.MISC; private String group; @@ -105,7 +93,7 @@ public CraftingRecipeEvent(RecipeTypes recipeType) { super(recipeType); }; - public void setIngredients(int placement, ItemStack item) { + public void setIngredients(int placement, RecipeChoice item) { ingredients[placement] = item; } @@ -117,18 +105,10 @@ public void setGroup(String group) { this.group = group; } - public ItemStack[] getIngredients() { + public RecipeChoice[] getIngredients() { return ingredients; } - public int getMaxIngredients() { - return getRecipeType().getMaxIngredients(); - } - - public int getMaxRowIngredients() { - return getRecipeType().getMaxRowIngredients(); - } - public CraftingBookCategory getCategory() { return category; } @@ -151,7 +131,7 @@ public ShapelessRecipeEvent(RecipeTypes recipeType) { } public static class CookingRecipeEvent extends RegisterRecipeEvent { - private Material inputItem; + private RecipeChoice input; private CookingBookCategory category = CookingBookCategory.MISC; private String group; private int cookingTime = 10; @@ -161,8 +141,8 @@ public CookingRecipeEvent(RecipeTypes recipeType) { super(recipeType); }; - public void setInputItem(Material item) { - inputItem = item; + public void setInput(RecipeChoice input) { + this.input = input; } public void setCategory(CookingBookCategory category) { @@ -189,8 +169,8 @@ public String getGroup() { return group; } - public Material getInputItem() { - return inputItem; + public RecipeChoice getInput() { + return input; } public int getCookingTime() { diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index d95bf8b9907..b7f8b5722b9 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2303,6 +2303,19 @@ transform reasons: unknown: unknown infection: infection, villager infection +# -- Crafting Book Categories -- +crafting book categories: + building: crafting.building, crafting building, craftingcategory.building, craftingcategory building, crafting category.building, crafting category building + equipment: crafting.equipment, crafting equipment, craftingcategory.equipment, craftingcategory equipment, crafting category.equipment, crafting category equipment + misc: crafting.misc, crafting misc, craftingcategory.misc, craftingcategory misc, crafting category.misc, crafting category misc + redstone: crafting.redstone, crafting redstone, craftingcategory.redstone, craftingcategory redstone, crafting category.redstone, crafting category redstone + +# -- Cooking Book Categories -- +cooking book categories: + blocks: cooking.blocks, cooking blocks, cookingcategory.blocks, cookingcategory blocks, cooking category.blocks, cooking category blocks + food: cooking.food, cooking food, cookingcategory.food, cookingcategory food, cooking category.food, cooking category food + misc: cooking.misc, cooking misc, cookingcategory.misc, cookingcategory misc, cooking category.misc, cooking category misc + # -- Boolean -- boolean: true: @@ -2383,6 +2396,9 @@ types: quitreason: quit reason¦s @a inventoryclosereason: inventory close reason¦s @an transformreason: transform reason¦s @a + recipe: recipe¦s @a + craftingbookcategory: crafting book categor¦y¦ies @a + cookingbookcategory: cooking book categor¦y¦ies @a # Skript weathertype: weather type¦s @a From d73bad27dde1373e49c0a92bf2a2c4abdb1f1436 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:01:06 -0400 Subject: [PATCH 07/20] Further Additions --- .../skript/classes/data/BukkitClasses.java | 12 +- .../conditions/CondDiscoveredRecipes.java | 4 +- .../skript/conditions/CondRecipeExists.java | 48 +++ .../njol/skript/effects/EffRemoveRecipe.java | 4 +- .../skript/expressions/ExprAllRecipes.java | 128 ++++++++ .../skript/expressions/ExprGetRecipe.java | 71 +++++ .../expressions/ExprRecipeCategory.java | 4 +- .../expressions/ExprRecipeCookingTime.java | 4 +- .../expressions/ExprRecipeExperience.java | 4 +- .../skript/expressions/ExprRecipeGroup.java | 4 +- .../expressions/ExprRecipeIngredients.java | 10 +- .../skript/expressions/ExprRecipeName.java | 65 ++++ .../skript/expressions/ExprRecipeResult.java | 2 +- .../skript/expressions/ExprRecipeType.java | 63 ++++ .../skript/sections/SecRegisterRecipe.java | 67 ++-- .../java/ch/njol/skript/util/RecipeUtils.java | 297 ++++++++++++++++++ .../njol/skript/util/RegisterRecipeEvent.java | 275 ---------------- src/main/resources/lang/default.lang | 14 + 18 files changed, 745 insertions(+), 331 deletions(-) create mode 100644 src/main/java/ch/njol/skript/conditions/CondRecipeExists.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprRecipeName.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprRecipeType.java create mode 100644 src/main/java/ch/njol/skript/util/RecipeUtils.java delete mode 100644 src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index 54a5a3ab899..ee054a06c80 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -30,6 +30,7 @@ import java.util.stream.Collectors; import ch.njol.skript.bukkitutil.BukkitUtils; +import ch.njol.skript.util.*; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Difficulty; @@ -72,6 +73,7 @@ import org.bukkit.event.player.PlayerResourcePackStatusEvent.Status; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.inventory.*; +import org.bukkit.inventory.BlockInventoryHolder; import org.bukkit.inventory.recipe.CookingBookCategory; import org.bukkit.inventory.recipe.CraftingBookCategory; import org.bukkit.metadata.Metadatable; @@ -99,9 +101,6 @@ import ch.njol.skript.lang.util.SimpleLiteral; import ch.njol.skript.localization.Language; import ch.njol.skript.registrations.Classes; -import ch.njol.skript.util.BlockUtils; -import ch.njol.skript.util.PotionEffectUtils; -import ch.njol.skript.util.StringMode; import ch.njol.util.StringUtils; import ch.njol.yggdrasil.Fields; import io.papermc.paper.world.MoonPhase; @@ -1541,6 +1540,13 @@ public String toVariableNameString(EnchantmentOffer eo) { .since("INSERT VERSION") .defaultExpression(new EventValueExpression<>(Recipe.class))); + Classes.registerClass(new EnumClassInfo<>(RecipeUtils.RecipeType.class, "recipetype", "recipe types") + .user("recipe type") + .name("Recipe Type") + .description("Represents recipe types") + .since("INSERT VERSION") + ); + Classes.registerClass(new EnumClassInfo<>(CraftingBookCategory.class, "craftingbookcategory", "crafting book categories") .user("crafting book category") .name("Crafting Book Category") diff --git a/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java b/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java index 82a829ec71d..216c9312fd6 100644 --- a/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java +++ b/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java @@ -29,8 +29,8 @@ public class CondDiscoveredRecipes extends Condition { static { Skript.registerCondition(CondDiscoveredRecipes.class, - "%players% (has|have) (discovered|unlocked| recipe[s] %strings%", - "%players% (hasn't|has not|haven't|have not) (discovered|unlocked| recipe[s] %strings%"); + "%players% (has|have) (discovered|unlocked) recipe[s] %strings%", + "%players% (hasn't|has not|haven't|have not) (discovered|unlocked) recipe[s] %strings%"); } private Expression players; diff --git a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java new file mode 100644 index 00000000000..3df418c28d1 --- /dev/null +++ b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java @@ -0,0 +1,48 @@ +package ch.njol.skript.conditions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Condition; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +@Name("Recipe Exists") +@Description("Checks to see if a recipe exists using the name") +@Examples({ + "if the recipe \"my_recipe\" exists:", + "\tremove the recipe \"my_recipe\" from the server" +}) +@Since("INSERT VERSION") +public class CondRecipeExists extends Condition { + + static { + Skript.registerCondition(CondRecipeExists.class, "[the] recipe[s] %strings% exist[s]"); + } + + private Expression recipes; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + recipes = (Expression) exprs[0]; + return true; + } + + @Override + public boolean check(Event event) { + return recipes.check(event, recipe -> Bukkit.getRecipe(NamespacedKey.fromString(recipe, Skript.getInstance())) != null); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "recipes " + recipes.toString(event, debug) + "exists"; + } +} diff --git a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java index f17bedf0476..b5897800833 100644 --- a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java +++ b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java @@ -19,13 +19,13 @@ "Remove a recipe or multiple recipes from the server", "Removing a recipe from a server will cause all players who have discovered the recipe to be undiscovered." }) -@Examples("remove recipe \"my_recipe\" from the server") +@Examples("remove the recipe \"my_recipe\" from the server") @Since("INSERT VERSION") public class EffRemoveRecipe extends Effect { static { Skript.registerEffect(EffRemoveRecipe.class, - "(remove|delete|clear) recipe[s] %strings% [from the server]"); + "(remove|delete|clear) [the] recipe[s] %strings% [from the server]"); } private Expression recipes; diff --git a/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java b/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java new file mode 100644 index 00000000000..bdd49a4deae --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java @@ -0,0 +1,128 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.skript.util.RecipeUtils; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.Keyed; +import org.bukkit.NamespacedKey; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +@Name("All Recipes") +@Description({ + "Retrieve all recipes registered in the server", + "You can retrieve all recipes of a recipe type", + "You can retrieve all recipes of an item, including custom items", + "You can retrieve all minecraft recipes", + "You can retrieve all custom recipes made by any and all plugins" +}) +@Examples({ + "set {_list::*} to all of the recipe of type shaped recipe for netherite ingot", + "set {_list::*} to all mc recipes of type cooking recipe for raw beef", + "set {_list::*} to all of the custom recipes of type blasting for raw iron named \"Impure Iron\"" +}) +@Since("INSERT VERSION") +public class ExprAllRecipes extends SimpleExpression { + + static { + Skript.registerExpression(ExprAllRecipes.class, Recipe.class, ExpressionType.SIMPLE, + "all [of the] recipes [types:of type %recipetypes%] [items:for %itemstacks/itemtypes%]", + "all [of the] (mc|minecraft|vanilla) recipes [types:of type %recipetypes%] [items:for %itemstacks/itemtypes%]", + "all [of the] custom recipes [types:of type %recipetypes%] [items:for %itemstacks/itemtypes%]"); + } + + private Expression recipeTypeExpr; + private Expression itemExpr; + private boolean getMinecraft, getCustom; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + recipeTypeExpr = parseResult.hasTag("types") ? (Expression) exprs[0] : null; + itemExpr = parseResult.hasTag("items") ? exprs[1] : null; + getMinecraft = matchedPattern == 1; + getCustom = matchedPattern == 2; + return true; + } + + @Override + protected Recipe @Nullable [] get(Event event) { + + List recipeList = new ArrayList<>(); + Iterator iterator = null; + if (itemExpr != null) { + List itemRecipes = new ArrayList<>(); + for (Object object : itemExpr.getArray(event)) { + ItemStack stack = null; + if (object instanceof ItemStack itemStack) { + stack = itemStack; + } else if (object instanceof ItemType itemType) { + stack = new ItemStack(itemType.getMaterial()); + stack.setItemMeta(itemType.getItemMeta()); + } + if (stack != null) + itemRecipes.addAll(Bukkit.getRecipesFor(stack)); + } + if (itemRecipes.isEmpty()) + return null; + iterator = itemRecipes.iterator(); + } else { + iterator = Bukkit.recipeIterator(); + } + + + iterator.forEachRemaining(recipe -> { + if (recipe instanceof Keyed keyed) { + NamespacedKey key = keyed.getKey(); + if (getMinecraft && !key.getNamespace().equalsIgnoreCase("minecraft")) + return; + else if (getCustom && key.getNamespace().equalsIgnoreCase("minecraft")) + return; + + if (recipeTypeExpr != null) { + for (RecipeUtils.RecipeType type : recipeTypeExpr.getArray(event)) { + if (recipe.getClass().equals(type.getRecipeClass())) + recipeList.add(recipe); + } + } else { + recipeList.add(recipe); + } + } + }); + + return recipeList.toArray(new Recipe[0]); + } + + @Override + public boolean isSingle() { + return false; + } + + @Override + public Class getReturnType() { + return Recipe.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "all of the " + (getMinecraft ? "minecraft " : getCustom ? "custom " : "") + "recipes" + + (recipeTypeExpr != null ? " of type " + recipeTypeExpr.toString(event, debug) : "") + + (itemExpr != null ? " for " + itemExpr.toString(event, debug) : ""); + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java new file mode 100644 index 00000000000..d345da92a3d --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java @@ -0,0 +1,71 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.NamespacedKey; +import org.bukkit.event.Event; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +@Name("Get Recipe") +@Description("Get a recipe matching the corresponding name") +@Examples({ + "set {_recipe} to recipe with the name \"my_recipe\"", + "set {_recipes::*} to recipes with the names \"my_recipe\" and \"custom_recipe\"" +}) +@Since("INSERT VERSION") +public class ExprGetRecipe extends SimpleExpression { + + static { + Skript.registerExpression(ExprGetRecipe.class, Recipe.class, ExpressionType.SIMPLE, + "recipe[s] with [the] name[s] %strings%"); + } + + private Expression recipeNames; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + recipeNames = (Expression) exprs[0]; + return true; + } + + @Override + protected Recipe @Nullable [] get(Event event) { + List recipeList = new ArrayList<>(); + for (String name : recipeNames.getArray(event)) { + NamespacedKey key = NamespacedKey.fromString(name, Skript.getInstance()); + Recipe check = Bukkit.getRecipe(key); + if (check != null) + recipeList.add(check); + } + return recipeList.toArray(new Recipe[0]); + } + + @Override + public boolean isSingle() { + return recipeNames.isSingle(); + } + + @Override + public Class getReturnType() { + return Recipe.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "recipes with the names " + recipeNames.toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java index 9f40ae208cf..ed5ef4ad75f 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java @@ -7,8 +7,8 @@ import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.*; import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; import org.bukkit.event.Event; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java index 1605f720cfa..1321db93066 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java @@ -11,8 +11,8 @@ import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.CookingRecipeEvent; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.CookingRecipeEvent; import ch.njol.skript.util.Timespan; import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java index dcd43426374..f098ded53c2 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java @@ -11,8 +11,8 @@ import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.CookingRecipeEvent; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.CookingRecipeEvent; import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; import org.bukkit.event.Event; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java index 8a9ead51007..dae335e7cfe 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java @@ -11,8 +11,8 @@ import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.*; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.*; import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; import org.bukkit.event.Event; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java index 5c48207547f..4ffcbf07bf2 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java @@ -16,9 +16,9 @@ import ch.njol.util.coll.CollectionUtils; import org.bukkit.Material; import org.bukkit.event.Event; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.*; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.CraftingRecipeEvent.*; import org.bukkit.inventory.*; import org.jetbrains.annotations.Nullable; @@ -249,7 +249,7 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { return; if (items.size() > 9) { - customError("You can only provide up to 9 items when setting the ingredients for a '" + recipeEvent.getRecipeName() + "' recipe."); + customError("You can only provide up to 9 items when setting the ingredients for a '" + recipeEvent.getRecipeType() + "' recipe."); recipeEvent.setErrorInEffect(); return; } @@ -272,7 +272,7 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { if (!(event instanceof ShapedRecipeEvent shapedEvent)) return; if (items.size() > 3) { - customError("You can only provide up to 3 items when setting the ingredients of a row for a '" + recipeEvent.getRecipeName() + "' recipe."); + customError("You can only provide up to 3 items when setting the ingredients of a row for a '" + recipeEvent.getRecipeType() + "' recipe."); recipeEvent.setErrorInEffect(); return; } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeName.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeName.java new file mode 100644 index 00000000000..c6a5cf10cbd --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeName.java @@ -0,0 +1,65 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.util.Kleenean; +import org.bukkit.Keyed; +import org.bukkit.event.Event; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +@Name("Recipe Name") +@Description("Get the namespacekey of a recipe") +@Examples({ + "loop all recipes:", + "\tbroadcast the recipe name of loop-recipe", + "\tadd loop-recipe's namespacekey to {_list::*}" +}) +@Since("INSERT VERSION") +public class ExprRecipeName extends PropertyExpression { + + static { + Skript.registerExpression(ExprRecipeName.class, String.class, ExpressionType.PROPERTY, + "[the] recipe name[space[key]][s] of %recipes%", + "[the] %recipes%'[s] name[space[key][s]"); + } + + private Expression recipes; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + recipes = (Expression) exprs[0]; + return true; + } + + @Override + protected String @Nullable [] get(Event event, Recipe[] source) { + List names = new ArrayList<>(); + for (Recipe recipe : recipes.getArray(event)) { + if (recipe instanceof Keyed key) + names.add(key.getKey().toString()); + } + return names.toArray(new String[0]); + } + + @Override + public Class getReturnType() { + return String.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the recipe namespacekeys of " + recipes.toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java index b8a05c5c888..25725f47afa 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java @@ -11,7 +11,7 @@ import ch.njol.skript.classes.Changer.ChangeMode; import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.RegisterRecipeEvent; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; import org.bukkit.event.Event; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java new file mode 100644 index 00000000000..5aa615b1d4a --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java @@ -0,0 +1,63 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.PropertyExpression; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.RecipeUtils; +import ch.njol.util.Kleenean; +import org.bukkit.event.Event; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +@Name("Recipe Type") +@Description("Get the recipe type of a recipe") +@Examples({ + "loop all recipes:", + "\tbroadcast the recipe type of loop-recipe" +}) +@Since("INSERT VERSION") +public class ExprRecipeType extends PropertyExpression { + + static { + Skript.registerExpression(ExprRecipeType.class, RecipeUtils.RecipeType.class, ExpressionType.PROPERTY, + "[the] recipe type of %recipes%", + "[the] %recipes%'[s] recipe type"); + } + + private Expression recipes; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + recipes = (Expression) exprs[0]; + return true; + } + + @Override + protected RecipeUtils.RecipeType @Nullable [] get(Event event, Recipe[] source) { + List types = new ArrayList<>(); + for (Recipe recipe : recipes.getArray(event)) { + types.add(RecipeUtils.getRecipeTypeFromRecipe(recipe)); + } + return types.toArray(new RecipeUtils.RecipeType[0]); + } + + @Override + public Class getReturnType() { + return RecipeUtils.RecipeType.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the recipe type of " + recipes.toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 438fafaac4c..84cb2886b18 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -7,17 +7,17 @@ import ch.njol.skript.doc.Examples; import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.Section; +import ch.njol.skript.lang.*; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.Trigger; -import ch.njol.skript.lang.TriggerItem; import ch.njol.skript.registrations.EventValues; import ch.njol.skript.util.Getter; -import ch.njol.skript.util.RegisterRecipeEvent; -import ch.njol.skript.util.RegisterRecipeEvent.RecipeTypes; -import ch.njol.skript.util.RegisterRecipeEvent.*; -import ch.njol.skript.util.RegisterRecipeEvent.CraftingRecipeEvent.*; +import ch.njol.skript.util.LiteralUtils; +import ch.njol.skript.util.RecipeUtils; +import ch.njol.skript.util.RecipeUtils.*; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; +import ch.njol.skript.util.RecipeUtils.RecipeType; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.*; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.CraftingRecipeEvent.*; import ch.njol.skript.variables.Variables; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; @@ -51,13 +51,13 @@ "\tset recipe ingredients of second row to air, emerald and air", "\tset recipe ingredients of 3rd row to diamond, air and diamond", "\tset recipe group to \"my group\"", - "\tset recipe category to crafting.misc", + "\tset recipe crafting category to crafting.misc", "\tset recipe result to diamond sword named \"Heavenly Sword\"", "", "register a shapeless recipe with namespace \"my_recipe\":", "\tset recipe ingredients to 3 diamonds, 3 emeralds and 3 iron ingots", "\tset the recipe group to \"custom group\"", - "\tset the recipe category to crafting category misc", + "\tset the recipe crafting category to crafting category misc", "\tset the recipe result item to diamond helmet named \"Heavenly Helm\"", "", "#Blasting, Furnace, Campfire and Smoking follow same format as Cooking", @@ -65,7 +65,7 @@ "\tset the recipe experience to 5", "\tset the recipe cooking time to 10 seconds", "\tset the recipe group to \"custom group\"", - "\tset the recipe category to cooking.misc", + "\tset the recipe cooking category to cooking.misc", "\tset the recipe input item to coal named \"Ash\"", "\tset the recipe resulting item to gunpowder named \"Dust\"", "", @@ -85,19 +85,14 @@ public class SecRegisterRecipe extends Section { /* TODO: Tests - ExprAllRecipes (Including of recipe type) - ExprRecipeName (Get recipe via name) - ExprRecipeFor (Get all recipes for item) - Rewrite Sec to provide a valid recipe as event value (Including RegisterRecipeEvent.java) + Rewrite Sec to provide a valid recipe as event value (Including rewrite of RecipeUtils.java) + Omit "Recipe" as optional in some of the expressions (Make sure to change examples) + Change category langs + Add "'" to smithing ingredients pattern */ - private static final RecipeTypes[] recipeTypes = RecipeTypes.values(); static { - String[] patterns = new String[recipeTypes.length]; - for (RecipeTypes type : recipeTypes) { - patterns[type.ordinal()] = "(register|create) [a] [new] " + type.getPattern() + " recipe with [the] name[space[key]] %string%"; - } - Skript.registerSection(SecRegisterRecipe.class, patterns); + Skript.registerSection(SecRegisterRecipe.class, "(register|create) [a] [new] %-recipetype% with [the] name[space[key]] %string%"); EventValues.registerEventValue(RegisterRecipeEvent.class, Recipe.class, new Getter() { @Override public @Nullable Recipe get(RegisterRecipeEvent recipe) { @@ -106,8 +101,8 @@ Rewrite Sec to provide a valid recipe as event value (Including RegisterRecipeEv }, EventValues.TIME_NOW); } - private RecipeTypes recipeType; private Expression providedName; + private Expression providedType; private Trigger trigger; private Node thisNode; private String thisScript; @@ -115,11 +110,12 @@ Rewrite Sec to provide a valid recipe as event value (Including RegisterRecipeEv @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult, SectionNode sectionNode, List triggerItems) { - recipeType = recipeTypes[matchedPattern]; - providedName = (Expression) exprs[0]; + providedType = (Expression) exprs[0]; + providedName = (Expression) exprs[1]; + Class eventClass = ((Literal) exprs[0]).getSingle().getEventClass(); AtomicBoolean delayed = new AtomicBoolean(false); Runnable afterLoading = () -> delayed.set(!getParser().getHasDelayBefore().isFalse()); - trigger = loadCode(sectionNode, "register recipe", afterLoading, recipeType.getEventClass()); + trigger = loadCode(sectionNode, "register recipe", afterLoading, eventClass); if (delayed.get()) { Skript.error("Delays cannot be used within a 'register recipe' section."); return false; @@ -133,11 +129,12 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye protected @Nullable TriggerItem walk(Event event) { String name = providedName.getSingle(event); NamespacedKey key = NamespacedKey.fromString(name, Skript.getInstance()); + RecipeType recipeType = providedType.getSingle(event); RegisterRecipeEvent recipeEvent = switch (recipeType) { case SHAPED -> new ShapedRecipeEvent(recipeType); case SHAPELESS -> new ShapelessRecipeEvent(recipeType); case COOKING, BLASTING, FURNACE, CAMPFIRE, SMOKING -> new CookingRecipeEvent(recipeType); - case SMITHINGTRANSFORM, SMITHINGTRIM -> new SmithingRecipeEvent(recipeType); + case SMITHING_TRANSFORM, SMITHING_TRIM -> new SmithingRecipeEvent(recipeType); case STONECUTTING -> new StonecuttingRecipeEvent(recipeType); }; Variables.setLocalVariables(recipeEvent, Variables.copyLocalVariables(event)); @@ -147,7 +144,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye if (recipeEvent.getErrorInEffect()) return super.walk(event, false); ItemStack result = recipeEvent.getResultItem(); - if (result == null && (recipeType != RecipeTypes.SMITHINGTRIM)) { + if (result == null && (recipeType != RecipeType.SMITHING_TRIM)) { customError("You must provide a result item when registering a recipe."); return super.walk(event, false); } @@ -156,7 +153,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye if (recipeEvent instanceof CraftingRecipeEvent craftingRecipe) { RecipeChoice[] ingredients = craftingRecipe.getIngredients(); if (ingredients.length < 2 || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < 2) { - customError("You must have at least 2 ingredients when registering a '" + recipeType.getToString() + "' recipe."); + customError("You must have at least 2 ingredients when registering a '" + recipeType + "' recipe."); return super.walk(event, false); } String group = craftingRecipe.getGroup(); @@ -177,7 +174,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye createCookingRecipe(recipeType, key, result, input, group, category, cookingTime, experience); } } - case SMITHINGTRANSFORM, SMITHINGTRIM -> { + case SMITHING_TRANSFORM, SMITHING_TRIM -> { if (recipeEvent instanceof SmithingRecipeEvent smithingRecipe) { RecipeChoice base = smithingRecipe.getBase(); RecipeChoice template = smithingRecipe.getTemplate(); @@ -232,7 +229,7 @@ private void createShapelessRecipe(NamespacedKey key, ItemStack result, RecipeCh completeRecipe(key, shapelessRecipe); } - private void createCookingRecipe(RecipeTypes recipeType, NamespacedKey key, ItemStack result, RecipeChoice input, String group, CookingBookCategory category, int cookingTime, float experience) { + private void createCookingRecipe(RecipeType recipeType, NamespacedKey key, ItemStack result, RecipeChoice input, String group, CookingBookCategory category, int cookingTime, float experience) { var recipe = switch (recipeType) { case BLASTING -> new BlastingRecipe(key, result, input, experience, cookingTime); case CAMPFIRE -> new CampfireRecipe(key, result, input, experience, cookingTime); @@ -249,14 +246,14 @@ private void createCookingRecipe(RecipeTypes recipeType, NamespacedKey key, Item completeRecipe(key, recipe); } - private void createSmithingRecipe(RecipeTypes recipeType, NamespacedKey key, ItemStack result, RecipeChoice base, RecipeChoice template, RecipeChoice addition) { + private void createSmithingRecipe(RecipeType recipeType, NamespacedKey key, ItemStack result, RecipeChoice base, RecipeChoice template, RecipeChoice addition) { if (base == null || template == null || addition == null) { - customError("Unable to create '" + recipeType.getToString() + "' recipe, missing data."); + customError("Unable to create '" + recipeType + "' recipe, missing data."); return; } var recipe = switch (recipeType) { - case SMITHINGTRANSFORM -> new SmithingTransformRecipe(key, result, template, base, addition); - case SMITHINGTRIM -> new SmithingTrimRecipe(key, template, base, addition); + case SMITHING_TRANSFORM -> new SmithingTransformRecipe(key, result, template, base, addition); + case SMITHING_TRIM -> new SmithingTrimRecipe(key, template, base, addition); default -> null; }; if (recipe == null) @@ -279,7 +276,7 @@ private void customError(String message) { @Override public String toString(@Nullable Event event, boolean debug) { - return "register a new " + recipeType.getToString() + " recipe with the namespacekey " + providedName.toString(event, debug); + return "register a new " + providedType.toString(event, debug) + " recipe with the namespacekey " + providedName.toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/util/RecipeUtils.java b/src/main/java/ch/njol/skript/util/RecipeUtils.java new file mode 100644 index 00000000000..c496f6f28bd --- /dev/null +++ b/src/main/java/ch/njol/skript/util/RecipeUtils.java @@ -0,0 +1,297 @@ +package ch.njol.skript.util; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.*; +import org.bukkit.inventory.recipe.CookingBookCategory; +import org.bukkit.inventory.recipe.CraftingBookCategory; +import org.jetbrains.annotations.NotNull; + +public class RecipeUtils { + + // Custom enum for registering a 'recipetype' class + // TODO: If and when Bukkit creates a RecipeType enum, remove this and change lang + public enum RecipeType { + SHAPED(ShapedRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class), + SHAPELESS(ShapelessRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapelessRecipeEvent.class), + COOKING(CookingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.class), + BLASTING(BlastingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.BlastingRecipeEvent.class), + FURNACE(FurnaceRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.FurnaceRecipeEvent.class), + CAMPFIRE(CampfireRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.CampfireRecipeEvent.class), + SMOKING(SmokingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.SmokingRecipeEvent.class), + SMITHING_TRANSFORM(SmithingTransformRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.SmithingTransformRecipeEvent.class), + SMITHING_TRIM(SmithingTrimRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.SmithingTrimRecipeEvent.class), + STONECUTTING(StonecuttingRecipe.class, RegisterRecipeEvent.StonecuttingRecipeEvent.class); + + private final Class recipeClass; + private final Class eventClass; + + RecipeType(Class recipeClass, Class eventClass) { + this.recipeClass = recipeClass; + this.eventClass = eventClass; + } + + public Class getRecipeClass() { + return recipeClass; + } + + public Class getEventClass() { + return eventClass; + } + } + + private static final RecipeType[] recipeTypes = RecipeType.values(); + + public static RecipeType getRecipeTypeFromRecipeClass(Class providedClass) { + for (RecipeType type : recipeTypes) { + if (type.recipeClass.equals(providedClass)) + return type; + } + return null; + } + + public static RecipeType getRecipeTypeFromRecipe(Recipe providedRecipe) { + return getRecipeTypeFromRecipeClass(providedRecipe.getClass()); + } + + // Custom Events used for SecRegisterRecipe + + public static class RegisterRecipeEvent extends Event { + private ItemStack resultItem; + private boolean errorInEffect = false; + private RecipeType recipeType; + + public RegisterRecipeEvent(RecipeType recipeType) { + this.recipeType = recipeType; + } + + public void setResultItem(ItemStack resultItem) { + this.resultItem = resultItem; + } + + public void setErrorInEffect() { + this.errorInEffect = true; + } + + public ItemStack getResultItem() { + return resultItem; + } + + public boolean getErrorInEffect() { + return errorInEffect; + } + + public RecipeType getRecipeType() { + return recipeType; + } + + public static class CraftingRecipeEvent extends RegisterRecipeEvent { + private RecipeChoice[] ingredients = new RecipeChoice[9]; + private CraftingBookCategory category = CraftingBookCategory.MISC; + private String group; + + public CraftingRecipeEvent(RecipeType recipeType) { + super(recipeType); + }; + + public void setIngredients(int placement, RecipeChoice item) { + ingredients[placement] = item; + } + + public void setCategory(CraftingBookCategory category) { + this.category = category; + } + + public void setGroup(String group) { + this.group = group; + } + + public RecipeChoice[] getIngredients() { + return ingredients; + } + + public CraftingBookCategory getCategory() { + return category; + } + + public String getGroup() { + return group; + } + + public static class ShapedRecipeEvent extends CraftingRecipeEvent { + public ShapedRecipeEvent(RecipeType recipeType) { + super(recipeType); + }; + } + + public static class ShapelessRecipeEvent extends CraftingRecipeEvent { + public ShapelessRecipeEvent(RecipeType recipeType) { + super(recipeType); + }; + } + } + + public static class CookingRecipeEvent extends RegisterRecipeEvent { + private RecipeChoice input; + private CookingBookCategory category = CookingBookCategory.MISC; + private String group; + private int cookingTime = 10; + private float experience = 0; + + public CookingRecipeEvent(RecipeType recipeType) { + super(recipeType); + }; + + public void setInput(RecipeChoice input) { + this.input = input; + } + + public void setCategory(CookingBookCategory category) { + this.category = category; + } + + public void setGroup(String group) { + this.group = group; + } + + public void setCookingTime(int cookingTime) { + this.cookingTime = cookingTime; + } + + public void setExperience(float experience) { + this.experience = experience; + } + + public CookingBookCategory getCategory() { + return category; + } + + public String getGroup() { + return group; + } + + public RecipeChoice getInput() { + return input; + } + + public int getCookingTime() { + return cookingTime; + } + + public float getExperience() { + return experience; + } + + public static class BlastingRecipeEvent extends CookingRecipeEvent { + public BlastingRecipeEvent(RecipeType recipeType) { + super(recipeType); + } + } + + public static class CampfireRecipeEvent extends CookingRecipeEvent { + public CampfireRecipeEvent(RecipeType recipeType) { + super(recipeType); + } + } + + public static class FurnaceRecipeEvent extends CookingRecipeEvent { + public FurnaceRecipeEvent(RecipeType recipeType) { + super(recipeType); + } + } + + public static class SmokingRecipeEvent extends CookingRecipeEvent { + public SmokingRecipeEvent(RecipeType recipeType) { + super(recipeType); + } + } + } + + public static class SmithingRecipeEvent extends RegisterRecipeEvent { + + private RecipeChoice base, addition, template; + + public SmithingRecipeEvent(RecipeType recipeType) { + super(recipeType); + } + + public void setBase(RecipeChoice base) { + this.base = base; + } + + public void setAddition(RecipeChoice addition) { + this.addition = addition; + } + + public void setTemplate(RecipeChoice template) { + this.template = template; + } + + public RecipeChoice getBase() { + return base; + } + + public RecipeChoice getAddition() { + return base; + } + + public RecipeChoice getTemplate() { + return base; + } + + public static class SmithingTransformRecipeEvent extends SmithingRecipeEvent { + public SmithingTransformRecipeEvent(RecipeType recipeType) { + super(recipeType); + } + } + + public static class SmithingTrimRecipeEvent extends SmithingRecipeEvent { + public SmithingTrimRecipeEvent(RecipeType recipeType) { + super(recipeType); + } + } + } + + public static class StonecuttingRecipeEvent extends RegisterRecipeEvent { + + private RecipeChoice input; + + public StonecuttingRecipeEvent(RecipeType recipeType) { + super(recipeType); + } + + public void setInput(RecipeChoice input) { + this.input = input; + } + + public RecipeChoice getInput() { + return input; + } + } + + @Override + public @NotNull HandlerList getHandlers() { + throw new IllegalStateException(); + } + } + + public Class getRecipeEventFromRecipeType(RecipeType recipeType) { + return switch (recipeType) { + case SHAPED -> RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class; + case SHAPELESS -> RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class; + case COOKING -> RegisterRecipeEvent.CookingRecipeEvent.class; + case BLASTING -> RegisterRecipeEvent.CookingRecipeEvent.BlastingRecipeEvent.class; + case CAMPFIRE -> RegisterRecipeEvent.CookingRecipeEvent.CampfireRecipeEvent.class; + case FURNACE -> RegisterRecipeEvent.CookingRecipeEvent.FurnaceRecipeEvent.class; + case SMOKING -> RegisterRecipeEvent.CookingRecipeEvent.SmokingRecipeEvent.class; + case SMITHING_TRANSFORM -> RegisterRecipeEvent.SmithingRecipeEvent.SmithingTransformRecipeEvent.class; + case SMITHING_TRIM -> RegisterRecipeEvent.SmithingRecipeEvent.SmithingTrimRecipeEvent.class; + case STONECUTTING -> RegisterRecipeEvent.StonecuttingRecipeEvent.class; + }; + } + + public Class getRecipeEventFromRecipeClass(Class recipeClass) { + return getRecipeEventFromRecipeType(getRecipeTypeFromRecipeClass(recipeClass)); + } + +} diff --git a/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java b/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java deleted file mode 100644 index cd7bd4698f4..00000000000 --- a/src/main/java/ch/njol/skript/util/RegisterRecipeEvent.java +++ /dev/null @@ -1,275 +0,0 @@ -package ch.njol.skript.util; - -import org.bukkit.Material; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; -import org.bukkit.inventory.*; -import org.bukkit.inventory.recipe.CookingBookCategory; -import org.bukkit.inventory.recipe.CraftingBookCategory; -import org.jetbrains.annotations.NotNull; - -public class RegisterRecipeEvent extends Event { - - public enum RecipeTypes { - SHAPED("shaped [crafting]", "shaped", CraftingRecipeEvent.ShapedRecipeEvent.class, ShapedRecipe.class), - SHAPELESS("shapeless [crafting]", "shapeless", CraftingRecipeEvent.ShapelessRecipeEvent.class, ShapelessRecipe.class), - BLASTING("blast[ing]", "blasting", CookingRecipeEvent.BlastingRecipeEvent.class, BlastingRecipe.class), - CAMPFIRE("campfire", "campfire", CookingRecipeEvent.CampfireRecipeEvent.class, CampfireRecipe.class), - FURNACE("furnace", "furnace", CookingRecipeEvent.FurnaceRecipeEvent.class, FurnaceRecipe.class), - SMOKING("smoking", "smoking", CookingRecipeEvent.SmokingRecipeEvent.class, SmokingRecipe.class), - COOKING("cooking", "cooking", CookingRecipeEvent.class, CookingRecipe.class), - SMITHINGTRANSFORM("smith[ing] transform", "smithing transform", SmithingRecipeEvent.SmithingTransformRecipeEvent.class, SmithingTransformRecipe.class), - SMITHINGTRIM("smith[ing] trim", "smithing trim", SmithingRecipeEvent.SmithingTrimRecipeEvent.class, SmithingTrimRecipe.class), - STONECUTTING("stone cutting", "stone cutting", StonecuttingRecipeEvent.class, StonecuttingRecipe.class); - - - private String pattern, toString; - private Class eventClass; - private Class recipeClass; - - RecipeTypes(String pattern, String toString, Class eventClass, Class recipeClass) { - this.pattern = pattern; - this.toString = toString; - this.eventClass = eventClass; - this.recipeClass = recipeClass; - } - - public String getPattern() { - return pattern; - } - - public Class getEventClass() { - return eventClass; - } - - public String getToString() { - return toString; - } - - } - - private ItemStack resultItem; - private boolean errorInEffect = false; - private RecipeTypes recipeType; - - public RegisterRecipeEvent(RecipeTypes recipeType) { - this.recipeType = recipeType; - } - - public void setResultItem(ItemStack resultItem) { - this.resultItem = resultItem; - } - - public void setErrorInEffect() { - this.errorInEffect = true; - } - - public ItemStack getResultItem() { - return resultItem; - } - - public boolean getErrorInEffect() { - return errorInEffect; - } - - public RecipeTypes getRecipeType() { - return recipeType; - } - - public String getRecipeName() { - return recipeType.toString; - } - - public Class getRecipeClass() { - return recipeType.recipeClass; - } - - public static class CraftingRecipeEvent extends RegisterRecipeEvent { - private RecipeChoice[] ingredients = new RecipeChoice[9]; - private CraftingBookCategory category = CraftingBookCategory.MISC; - private String group; - - public CraftingRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - }; - - public void setIngredients(int placement, RecipeChoice item) { - ingredients[placement] = item; - } - - public void setCategory(CraftingBookCategory category) { - this.category = category; - } - - public void setGroup(String group) { - this.group = group; - } - - public RecipeChoice[] getIngredients() { - return ingredients; - } - - public CraftingBookCategory getCategory() { - return category; - } - - public String getGroup() { - return group; - } - - public static class ShapedRecipeEvent extends CraftingRecipeEvent { - public ShapedRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - }; - } - - public static class ShapelessRecipeEvent extends CraftingRecipeEvent { - public ShapelessRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - }; - } - } - - public static class CookingRecipeEvent extends RegisterRecipeEvent { - private RecipeChoice input; - private CookingBookCategory category = CookingBookCategory.MISC; - private String group; - private int cookingTime = 10; - private float experience = 0; - - public CookingRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - }; - - public void setInput(RecipeChoice input) { - this.input = input; - } - - public void setCategory(CookingBookCategory category) { - this.category = category; - } - - public void setGroup(String group) { - this.group = group; - } - - public void setCookingTime(int cookingTime) { - this.cookingTime = cookingTime; - } - - public void setExperience(float experience) { - this.experience = experience; - } - - public CookingBookCategory getCategory() { - return category; - } - - public String getGroup() { - return group; - } - - public RecipeChoice getInput() { - return input; - } - - public int getCookingTime() { - return cookingTime; - } - - public float getExperience() { - return experience; - } - - public static class BlastingRecipeEvent extends CookingRecipeEvent { - public BlastingRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - } - } - - public static class CampfireRecipeEvent extends CookingRecipeEvent { - public CampfireRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - } - } - - public static class FurnaceRecipeEvent extends CookingRecipeEvent { - public FurnaceRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - } - } - - public static class SmokingRecipeEvent extends CookingRecipeEvent { - public SmokingRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - } - } - } - - public static class SmithingRecipeEvent extends RegisterRecipeEvent { - - private RecipeChoice base, addition, template; - - public SmithingRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - } - - public void setBase(RecipeChoice base) { - this.base = base; - } - - public void setAddition(RecipeChoice addition) { - this.addition = addition; - } - - public void setTemplate(RecipeChoice template) { - this.template = template; - } - - public RecipeChoice getBase() { - return base; - } - - public RecipeChoice getAddition() { - return base; - } - - public RecipeChoice getTemplate() { - return base; - } - - public static class SmithingTransformRecipeEvent extends SmithingRecipeEvent { - public SmithingTransformRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - } - } - - public static class SmithingTrimRecipeEvent extends SmithingRecipeEvent { - public SmithingTrimRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - } - } - } - - public static class StonecuttingRecipeEvent extends RegisterRecipeEvent { - - private RecipeChoice input; - - public StonecuttingRecipeEvent(RecipeTypes recipeType) { - super(recipeType); - } - - public void setInput(RecipeChoice input) { - this.input = input; - } - - public RecipeChoice getInput() { - return input; - } - } - - @Override - public @NotNull HandlerList getHandlers() { - throw new IllegalStateException(); - } -} diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index b7f8b5722b9..30442d483ff 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2316,6 +2316,19 @@ cooking book categories: food: cooking.food, cooking food, cookingcategory.food, cookingcategory food, cooking category.food, cooking category food misc: cooking.misc, cooking misc, cookingcategory.misc, cookingcategory misc, cooking category.misc, cooking category misc +# -- Recipe Types -- +recipe types: + shaped: shaped recipe, shaped crafting recipe + shapeless: shapeless recipe, shapeless crafting recipe + cooking: cooking recipe + blasting: blasting recipe + furnace: furnace recipe + campfire: campfire recipe + smoking: smoking recipe + smithing_transform: smithing transform recipe + smithing_trim: smithing trim recipe + stonecutting: stonecutting recipe + # -- Boolean -- boolean: true: @@ -2418,6 +2431,7 @@ types: experience.pattern: (e?xp|experience( points?)?) classinfo: type¦s @a visualeffect: visual effect¦s @a + recipetype: recipe type¦s @a # Hooks money: money From 23d4dc0aa5e466e36d5a0d333880fa98279d3d4a Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Fri, 11 Oct 2024 23:28:06 -0400 Subject: [PATCH 08/20] Fuse Changes --- .../skript/expressions/ExprAllRecipes.java | 15 ++++---- .../skript/expressions/ExprGetRecipe.java | 10 +++--- .../expressions/ExprRecipeCategory.java | 28 +++++++++++++-- .../expressions/ExprRecipeCookingTime.java | 5 +-- .../expressions/ExprRecipeExperience.java | 5 +-- .../skript/expressions/ExprRecipeGroup.java | 2 +- .../expressions/ExprRecipeIngredients.java | 25 +++++--------- ...ExprRecipeName.java => ExprRecipeKey.java} | 14 ++++---- .../skript/expressions/ExprRecipeResult.java | 5 +-- .../skript/sections/SecRegisterRecipe.java | 20 +++++------ src/main/resources/lang/default.lang | 34 +++++++++---------- 11 files changed, 88 insertions(+), 75 deletions(-) rename src/main/java/ch/njol/skript/expressions/{ExprRecipeName.java => ExprRecipeKey.java} (77%) diff --git a/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java b/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java index bdd49a4deae..5102ddc33d6 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java +++ b/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java @@ -42,9 +42,9 @@ public class ExprAllRecipes extends SimpleExpression { static { Skript.registerExpression(ExprAllRecipes.class, Recipe.class, ExpressionType.SIMPLE, - "all [of the] recipes [types:of type %recipetypes%] [items:for %itemstacks/itemtypes%]", - "all [of the] (mc|minecraft|vanilla) recipes [types:of type %recipetypes%] [items:for %itemstacks/itemtypes%]", - "all [of the] custom recipes [types:of type %recipetypes%] [items:for %itemstacks/itemtypes%]"); + "all [of the] (%recipetype%|recipes) [items:for %itemstacks/itemtypes%]", + "all [of the] (mc|minecraft|vanilla) (%recipetype%|recipes) [items:for %itemstacks/itemtypes%]", + "all [of the] custom (%recipetype%|recipes) [items:for %itemstacks/itemtypes%]"); } private Expression recipeTypeExpr; @@ -54,7 +54,7 @@ public class ExprAllRecipes extends SimpleExpression { @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - recipeTypeExpr = parseResult.hasTag("types") ? (Expression) exprs[0] : null; + recipeTypeExpr = exprs[0] != null ? (Expression) exprs[0] : null; itemExpr = parseResult.hasTag("items") ? exprs[1] : null; getMinecraft = matchedPattern == 1; getCustom = matchedPattern == 2; @@ -96,10 +96,9 @@ else if (getCustom && key.getNamespace().equalsIgnoreCase("minecraft")) return; if (recipeTypeExpr != null) { - for (RecipeUtils.RecipeType type : recipeTypeExpr.getArray(event)) { - if (recipe.getClass().equals(type.getRecipeClass())) - recipeList.add(recipe); - } + RecipeUtils.RecipeType type = recipeTypeExpr.getSingle(event); + if (recipe.getClass().equals(type.getRecipeClass()) || type.getRecipeClass().isInstance(recipe)) + recipeList.add(recipe); } else { recipeList.add(recipe); } diff --git a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java index d345da92a3d..93cad9eac5e 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java +++ b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java @@ -20,17 +20,17 @@ import java.util.List; @Name("Get Recipe") -@Description("Get a recipe matching the corresponding name") +@Description("Get a recipe registered under the provided key") @Examples({ - "set {_recipe} to recipe with the name \"my_recipe\"", - "set {_recipes::*} to recipes with the names \"my_recipe\" and \"custom_recipe\"" + "set {_recipe} to recipe with the key \"my_recipe\"", + "set {_recipes::*} to recipes with the ids \"my_recipe\" and \"custom_recipe\"" }) @Since("INSERT VERSION") public class ExprGetRecipe extends SimpleExpression { static { Skript.registerExpression(ExprGetRecipe.class, Recipe.class, ExpressionType.SIMPLE, - "recipe[s] with [the] name[s] %strings%"); + "recipe[s] with [the] (key|id)[s] %strings%"); } private Expression recipeNames; @@ -66,6 +66,6 @@ public Class getReturnType() { @Override public String toString(@Nullable Event event, boolean debug) { - return "recipes with the names " + recipeNames.toString(event, debug); + return "recipes with the keys " + recipeNames.toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java index ed5ef4ad75f..0767248d37e 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java @@ -2,6 +2,9 @@ import ch.njol.skript.Skript; import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; import ch.njol.skript.expressions.base.EventValueExpression; import ch.njol.skript.expressions.base.PropertyExpression; import ch.njol.skript.lang.Expression; @@ -19,12 +22,31 @@ import org.bukkit.inventory.recipe.CraftingBookCategory; import org.jetbrains.annotations.Nullable; +@Name("Recipe Category") +@Description("The recipe category of a Shaped, Shapeless, Cooking, Blasting, Furnace, Campfire and Smoking Recipe.") +@Examples({ + "register a new shaped recipe with the key \"my_recipe\":", + "\tset the recipe ingredients to diamond, air, diamond, air, emerald, air, diamond, air and diamond", + "\tset the recipe crafting category to crafting misc", + "\tset the recipe result item to nether star", + "", + "register a new blasting recipe with the id \"my_recipe\":", + "\tset the recipe input item to coal", + "\tset the recipe cooking category to cooking misc", + "\tset the recipe result item to gunpowder", + "", + "loop all recipes:", + "\tif recipe type of loop-recipe is shaped recipe:", + "\t\tbroadcast recipe crafting category of loop-recipe", + "\telse if recipe type of loop-recipe is cooking recipe:", + "\t\tbroadcast recipe cooking category of loop-recipe" +}) public class ExprRecipeCategory extends PropertyExpression { static { Skript.registerExpression(ExprRecipeCategory.class, String.class, ExpressionType.PROPERTY, - "[the] recipe crafting category [of %recipes%]", - "[the] recipe cooking category [of %recipes%]"); + "[the] [recipe] crafting category [of %recipes%]", + "[the] [recipe] cooking category [of %recipes%]"); } private boolean isCrafting = false; @@ -100,6 +122,6 @@ public Class getReturnType() { @Override public String toString(@Nullable Event event, boolean debug) { - return null; + return "the recipe " + (isCrafting ? "crafting" : "cooking") + " category of " + getExpr().toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java index 1321db93066..1bb0c99d6b9 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java @@ -24,7 +24,7 @@ @Name("Recipe Cooking Time") @Description("The cooking time of a Cooking, Blasting, Furnace, Campfire and Smoking Recipe.") @Examples({ - "register a new cooking recipe with the name \"my_recipe\":", + "register a new cooking recipe with the key \"my_recipe\":", "\tset the recipe input item to raw gold named \"Impure Gold\"", "\tset the recipe cooking time to 10 seconds", "\tset the recipe result to gold ingot named \"Pure Gold\"" @@ -33,7 +33,8 @@ public class ExprRecipeCookingTime extends PropertyExpression { static { - Skript.registerExpression(ExprRecipeCookingTime.class, Timespan.class, ExpressionType.PROPERTY, "[the] recipe cook[ing] time [of %recipes%]"); + Skript.registerExpression(ExprRecipeCookingTime.class, Timespan.class, ExpressionType.PROPERTY, + "[the] recipe cook[ing] time [of %recipes%]"); } private boolean isEvent = false; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java index f098ded53c2..aa3a1f1b81a 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java @@ -23,7 +23,7 @@ @Name("Recipe Experience") @Description("The experience of a Cooking, Blasting, Furnace, Campfire, and Smoking Recipe.") @Examples({ - "register a new blasting recipe with the name \"my_recipe\":", + "register a new blasting recipe with the key \"my_recipe\":", "\tset the recipe input item to a raw copper named \"Impure Copper\"", "\tset the recipe experience to 20", "\tset the recipe result to copper ingot named \"Pure Copper\"" @@ -32,7 +32,8 @@ public class ExprRecipeExperience extends PropertyExpression { static { - Skript.registerExpression(ExprRecipeExperience.class, Float.class, ExpressionType.PROPERTY, "[the] recipe [e]xp[erience] [of %recipes%]"); + Skript.registerExpression(ExprRecipeExperience.class, Float.class, ExpressionType.PROPERTY, + "[the] recipe [e]xp[erience] [of %recipes%]"); } private boolean isEvent = false; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java index dae335e7cfe..c8bc2ca568f 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java @@ -24,7 +24,7 @@ @Name("Recipe Group") @Description("The recipe group of a Shaped, Shapeless, Cooking, Blasting, Furnace, Campfire and Smoking Recipe.") @Examples({ - "register a new shapeless recipe with the name \"my_recipe\":", + "register a new shapeless recipe with the key \"my_recipe\":", "\tset the recipe ingredients to 3 diamonds, 3 emeralds and 3 netherite ingots", "\tset the recipe group to \"my group\"", "\tset the recipe result to nether star" diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java index 4ffcbf07bf2..90af450423f 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java @@ -32,7 +32,7 @@ "The base, template, addition items of a Smithing Transform and Smithing Trim recipe" }) @Examples({ - "register a new shaped recipe with the name \"my_recipe\":", + "register a new shaped recipe with the key \"my_recipe\":", "\tset the recipe ingredients to diamond, air, diamond, air, emerald, air, diamond, air and diamond", "\t#OR", "\tset the recipe ingredients of the 1st row to diamond, air and diamond", @@ -40,15 +40,15 @@ "\tset the recipe ingredients of the third row to diamond, air and diamond", "\tset the recipe result to beacon", "", - "create a shapeless recipe with namespace \"my_recipe\":", + "create a shapeless recipe with id \"my_recipe\":", "\tset recipe ingredients to iron ingot, gold ingot, iron ingot, nether star, 5 obsidian, nether star, iron ingot, gold ingot and iron ingot", "\tset recipe resulting item to beacon named \"OP Beacon\"", "", - "register new cooking recipe with the namespacekey \"my_recipe\":", + "register new cooking recipe with the id \"my_recipe\":", "\tset the recipe input item to netherite ingot named \"Impure Netherite\"", "\tset the recipe result item to netherite ingot named \"Pure Netherite\"", "", - "create a new smithing transform recipe with name \"my_recipe\":", + "create a new smithing transform recipe with key \"my_recipe\":", "\tset the recipe base item to diamond helmet", "\tset the recipe template item to paper named \"Blueprint\"", "\tset the recipe addition item to netherite ingot named \"Pure Netherite\"", @@ -66,11 +66,11 @@ enum RecipePattern { "This can only be used when registering a Shaped Recipe."), INPUT("recipe (input|source) [item]", "recipe input item", new Class[]{CookingRecipeEvent.class, StonecuttingRecipeEvent.class}, "This can only be used when registering a Cooking, Blasting, Furnace, Campfire, Smoking or Stonecutting Recipe."), - BASE("recipe base item[s]", "recipe base items", SmithingRecipeEvent.class, + BASE("[recipe] base item['s]", "recipe base item's", SmithingRecipeEvent.class, "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), - TEMPLATE("recipe template item[s]", "recipe template items", SmithingRecipeEvent.class, + TEMPLATE("[recipe] template item['s]", "recipe template item's", SmithingRecipeEvent.class, "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), - ADDITION("recipe addition[al] item[s]", "recipe additional items", SmithingRecipeEvent.class, + ADDITION("[recipe] addition[al] item['s]", "recipe additional item's", SmithingRecipeEvent.class, "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."); @@ -332,15 +332,6 @@ private void customError(String message) { @Override public String toString(@Nullable Event event, boolean debug) { - return "the recipe " + switch (selectedChoice) { - case INGREDIENTS -> "ingredients"; - case FIRSTROW -> "ingredients of first row"; - case SECONDROW -> "ingredients of second row"; - case THIRDROW -> "ingredients of third row"; - case BASE -> "base item"; - case TEMPLATE -> "template item"; - case ADDITION -> "addition item"; - case INPUT -> "input item"; - } + " of " + getExpr().toString(event, debug); + return "the " + selectedChoice.toString + " of " + getExpr().toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeName.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java similarity index 77% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeName.java rename to src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java index c6a5cf10cbd..d835da7ea6b 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeName.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java @@ -22,16 +22,16 @@ @Description("Get the namespacekey of a recipe") @Examples({ "loop all recipes:", - "\tbroadcast the recipe name of loop-recipe", - "\tadd loop-recipe's namespacekey to {_list::*}" + "\tbroadcast the recipe key of loop-recipe", + "\tadd loop-recipe's id to {_list::*}" }) @Since("INSERT VERSION") -public class ExprRecipeName extends PropertyExpression { +public class ExprRecipeKey extends PropertyExpression { static { - Skript.registerExpression(ExprRecipeName.class, String.class, ExpressionType.PROPERTY, - "[the] recipe name[space[key]][s] of %recipes%", - "[the] %recipes%'[s] name[space[key][s]"); + Skript.registerExpression(ExprRecipeKey.class, String.class, ExpressionType.PROPERTY, + "[the] recipe (key|id)[s] of %recipes%", + "[the] %recipes%'[s] (key|id)[s]"); } private Expression recipes; @@ -60,6 +60,6 @@ public Class getReturnType() { @Override public String toString(@Nullable Event event, boolean debug) { - return "the recipe namespacekeys of " + recipes.toString(event, debug); + return "the recipe keys of " + recipes.toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java index 25725f47afa..d0910937dbe 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java @@ -22,7 +22,7 @@ @Name("Recipe Result") @Description("The result item for a recipe") @Examples({ - "register a new shaped recipe with the name \"my_recipe\":", + "register a new shaped recipe with the key \"my_recipe\":", "\tset the recipe ingredients of 1st row to diamond, air and diamond", "\tset the recipe result to diamond sword named \"Chosen One\"" }) @@ -30,7 +30,8 @@ public class ExprRecipeResult extends PropertyExpression { static { - Skript.registerExpression(ExprRecipeResult.class, ItemStack.class, ExpressionType.PROPERTY, "[the] recipe result[ing] [item] [of %recipes%]"); + Skript.registerExpression(ExprRecipeResult.class, ItemStack.class, ExpressionType.PROPERTY, + "[the] recipe result[ing] [item] [of %recipes%]"); } private boolean isEvent = false; diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 84cb2886b18..380970f6489 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -51,7 +51,7 @@ "\tset recipe ingredients of second row to air, emerald and air", "\tset recipe ingredients of 3rd row to diamond, air and diamond", "\tset recipe group to \"my group\"", - "\tset recipe crafting category to crafting.misc", + "\tset recipe crafting category to crafting misc", "\tset recipe result to diamond sword named \"Heavenly Sword\"", "", "register a shapeless recipe with namespace \"my_recipe\":", @@ -65,16 +65,16 @@ "\tset the recipe experience to 5", "\tset the recipe cooking time to 10 seconds", "\tset the recipe group to \"custom group\"", - "\tset the recipe cooking category to cooking.misc", + "\tset the recipe cooking category to cooking misc", "\tset the recipe input item to coal named \"Ash\"", "\tset the recipe resulting item to gunpowder named \"Dust\"", "", "#Smithing Trim follows the same format, except for 'result item'", - "create smithing transform recipe with name \"my_recipe\":", - "\tset the recipe base item to diamond", - "\tset the recipe template item to emerald", - "\tset the recipe additional item to netherite ingot", - "\tset the recipe result to ...", + "create smithing transform recipe with key \"my_recipe\":", + "\tset the recipe base item to diamond helmet", + "\tset the recipe template item to paper named \"Blueprint\"", + "\tset the recipe addition item to netherite ingot named \"Pure Netherite\"", + "\tset the recipe result to netherite helmet named \"Pure Helmet\"", "", "create a new stonecutting recipe with namespacekey \"my_recipe\":", "\tset the recipe source item to cobblestone named \"Cracked Stone\"", @@ -86,13 +86,11 @@ public class SecRegisterRecipe extends Section { TODO: Tests Rewrite Sec to provide a valid recipe as event value (Including rewrite of RecipeUtils.java) - Omit "Recipe" as optional in some of the expressions (Make sure to change examples) - Change category langs - Add "'" to smithing ingredients pattern + Add Smithing Recipe (Enum, Ingredients, blah) */ static { - Skript.registerSection(SecRegisterRecipe.class, "(register|create) [a] [new] %-recipetype% with [the] name[space[key]] %string%"); + Skript.registerSection(SecRegisterRecipe.class, "(register|create) [a] [new] %*recipetype% with [the] (key|id) %string%"); EventValues.registerEventValue(RegisterRecipeEvent.class, Recipe.class, new Getter() { @Override public @Nullable Recipe get(RegisterRecipeEvent recipe) { diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index 30442d483ff..0b1a1ac934d 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2305,29 +2305,29 @@ transform reasons: # -- Crafting Book Categories -- crafting book categories: - building: crafting.building, crafting building, craftingcategory.building, craftingcategory building, crafting category.building, crafting category building - equipment: crafting.equipment, crafting equipment, craftingcategory.equipment, craftingcategory equipment, crafting category.equipment, crafting category equipment - misc: crafting.misc, crafting misc, craftingcategory.misc, craftingcategory misc, crafting category.misc, crafting category misc - redstone: crafting.redstone, crafting redstone, craftingcategory.redstone, craftingcategory redstone, crafting category.redstone, crafting category redstone + building: crafting building, craftingcategory building, crafting category building + equipment: crafting equipment, craftingcategory equipment, crafting category equipment + misc: crafting misc, craftingcategory misc, crafting category misc + redstone: crafting redstone, craftingcategory redstone, crafting category redstone # -- Cooking Book Categories -- cooking book categories: - blocks: cooking.blocks, cooking blocks, cookingcategory.blocks, cookingcategory blocks, cooking category.blocks, cooking category blocks - food: cooking.food, cooking food, cookingcategory.food, cookingcategory food, cooking category.food, cooking category food - misc: cooking.misc, cooking misc, cookingcategory.misc, cookingcategory misc, cooking category.misc, cooking category misc + blocks: cooking blocks, cookingcategory blocks, cooking category blocks + food: cooking food, cookingcategory food, cooking category food + misc: cooking misc, cookingcategory misc, cooking category misc # -- Recipe Types -- recipe types: - shaped: shaped recipe, shaped crafting recipe - shapeless: shapeless recipe, shapeless crafting recipe - cooking: cooking recipe - blasting: blasting recipe - furnace: furnace recipe - campfire: campfire recipe - smoking: smoking recipe - smithing_transform: smithing transform recipe - smithing_trim: smithing trim recipe - stonecutting: stonecutting recipe + shaped: shaped recipe, shaped crafting recipe, shaped recipes, shaped crafting recipes + shapeless: shapeless recipe, shapeless crafting recipe, shapeless recipes, shapeless crafting recipes + cooking: cooking recipe, cooking recipes + blasting: blasting recipe, blasting recipes + furnace: furnace recipe, furnace recipes + campfire: campfire recipe, campfire recipes + smoking: smoking recipe, smoking recipes + smithing_transform: smithing transform recipe, smithing transform recipes + smithing_trim: smithing trim recipe, smithing trim recipes + stonecutting: stonecutting recipe, stonecutting recipes # -- Boolean -- boolean: From fbefde4b44dd73cb824c25a340d22802cc9ffd93 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Sat, 12 Oct 2024 17:59:48 -0400 Subject: [PATCH 09/20] Tests (Stopping Point) --- .../skript/conditions/CondRecipeExists.java | 7 +- .../skript/expressions/ExprLastRecipe.java | 57 ++++++++++ .../expressions/ExprRecipeCategory.java | 6 +- .../expressions/ExprRecipeCookingTime.java | 4 +- .../expressions/ExprRecipeExperience.java | 4 +- .../skript/expressions/ExprRecipeGroup.java | 4 +- .../expressions/ExprRecipeIngredients.java | 27 +++-- .../skript/expressions/ExprRecipeResult.java | 4 +- .../skript/sections/SecRegisterRecipe.java | 51 ++++----- .../java/ch/njol/skript/util/RecipeUtils.java | 4 +- src/main/resources/lang/default.lang | 1 + .../syntaxes/expressions/ExprAllRecipes.sk | 16 +++ .../syntaxes/expressions/ExprGetRecipe.sk | 8 ++ .../expressions/ExprRecipeCategory.sk | 19 ++++ .../expressions/ExprRecipeCookingTime.sk | 9 ++ .../expressions/ExprRecipeExperience.sk | 9 ++ .../syntaxes/expressions/ExprRecipeGroup.sk | 9 ++ .../syntaxes/expressions/ExprRecipeKey.sk | 8 ++ .../syntaxes/expressions/ExprRecipeResult.sk | 9 ++ .../syntaxes/expressions/ExprRecipeType.sk | 103 ++++++++++++++++++ .../syntaxes/sections/SecRegisterRecipe.sk | 78 +++++++++++++ 21 files changed, 387 insertions(+), 50 deletions(-) create mode 100644 src/main/java/ch/njol/skript/expressions/ExprLastRecipe.java create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprAllRecipes.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk create mode 100644 src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk diff --git a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java index 3df418c28d1..2d1597d8ff9 100644 --- a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java +++ b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java @@ -24,7 +24,9 @@ public class CondRecipeExists extends Condition { static { - Skript.registerCondition(CondRecipeExists.class, "[the] recipe[s] %strings% exist[s]"); + Skript.registerCondition(CondRecipeExists.class, + "[the] recipe[s] %strings% exist[s]", + "[the] recipe[s] %strings% (doesn't|does not) exist[s]"); } private Expression recipes; @@ -33,6 +35,7 @@ public class CondRecipeExists extends Condition { @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { recipes = (Expression) exprs[0]; + setNegated(matchedPattern == 1); return true; } @@ -43,6 +46,6 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - return "recipes " + recipes.toString(event, debug) + "exists"; + return "recipes " + recipes.toString(event, debug) + (isNegated() ? "does not" : "") + "exists"; } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprLastRecipe.java b/src/main/java/ch/njol/skript/expressions/ExprLastRecipe.java new file mode 100644 index 00000000000..5b2f9ee4362 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprLastRecipe.java @@ -0,0 +1,57 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.skript.sections.SecRegisterRecipe; +import ch.njol.util.Kleenean; +import org.bukkit.event.Event; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +@Name("Last Registered Recipe") +@Description("Gets the recipe that was last registered through the Register Recipe Section.") +@Examples({ + "register a new shapeless recipe with the key \"my_recipe\":", + "\tset ingredients to diamond, emerald and iron ingot", + "\tset recipe result to diamond sword", + "set {_last} to last registered recipe" +}) +@Since("INSERT VERSION") +public class ExprLastRecipe extends SimpleExpression { + + static { + Skript.registerExpression(ExprLastRecipe.class, Recipe.class, ExpressionType.SIMPLE, "[the] last (created|registered) recipe"); + } + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + return true; + } + + @Override + protected Recipe @Nullable [] get(Event event) { + return new Recipe[]{SecRegisterRecipe.lastRegistered}; + } + + @Override + public boolean isSingle() { + return true; + } + + @Override + public Class getReturnType() { + return Recipe.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the last registered recipe"; + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java index 0767248d37e..307052f529e 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java @@ -45,8 +45,8 @@ public class ExprRecipeCategory extends PropertyExpression { static { Skript.registerExpression(ExprRecipeCategory.class, String.class, ExpressionType.PROPERTY, - "[the] [recipe] crafting category [of %recipes%]", - "[the] [recipe] cooking category [of %recipes%]"); + "[the] [recipe] crafting category [of %-recipes%]", + "[the] [recipe] cooking category [of %-recipes%]"); } private boolean isCrafting = false; @@ -56,7 +56,7 @@ public class ExprRecipeCategory extends PropertyExpression { @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { isCrafting = matchedPattern == 0; - if (!exprs[0].isDefault()) { + if (exprs[0] != null) { setExpr((Expression) exprs[0]); } else { if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java index 1bb0c99d6b9..733b617ca43 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java @@ -34,7 +34,7 @@ public class ExprRecipeCookingTime extends PropertyExpression static { Skript.registerExpression(ExprRecipeCookingTime.class, Timespan.class, ExpressionType.PROPERTY, - "[the] recipe cook[ing] time [of %recipes%]"); + "[the] recipe cook[ing] time [of %-recipes%]"); } private boolean isEvent = false; @@ -42,7 +42,7 @@ public class ExprRecipeCookingTime extends PropertyExpression @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - if (!exprs[0].isDefault()) { + if (exprs[0] != null) { setExpr((Expression) exprs[0]); } else { if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java index aa3a1f1b81a..c2ba33c961d 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java @@ -33,7 +33,7 @@ public class ExprRecipeExperience extends PropertyExpression { static { Skript.registerExpression(ExprRecipeExperience.class, Float.class, ExpressionType.PROPERTY, - "[the] recipe [e]xp[erience] [of %recipes%]"); + "[the] recipe [e]xp[erience] [of %-recipes%]"); } private boolean isEvent = false; @@ -41,7 +41,7 @@ public class ExprRecipeExperience extends PropertyExpression { @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - if (!exprs[0].isDefault()) { + if (exprs[0] != null) { setExpr((Expression) exprs[0]); } else { if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java index c8bc2ca568f..f030358386a 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java @@ -33,7 +33,7 @@ public class ExprRecipeGroup extends PropertyExpression { static { - Skript.registerExpression(ExprRecipeGroup.class, String.class, ExpressionType.PROPERTY, "[the] recipe group [of %recipes%]"); + Skript.registerExpression(ExprRecipeGroup.class, String.class, ExpressionType.PROPERTY, "[the] recipe group [of %-recipes%]"); } private boolean isEvent = false; @@ -41,7 +41,7 @@ public class ExprRecipeGroup extends PropertyExpression { @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - if (!exprs[0].isDefault()) { + if (exprs[0] != null) { setExpr((Expression) exprs[0]); } else { if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java index 90af450423f..69eca465673 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java @@ -19,6 +19,7 @@ import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.*; import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.CraftingRecipeEvent.*; +import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.SmithingRecipeEvent.*; import org.bukkit.inventory.*; import org.jetbrains.annotations.Nullable; @@ -67,11 +68,11 @@ enum RecipePattern { INPUT("recipe (input|source) [item]", "recipe input item", new Class[]{CookingRecipeEvent.class, StonecuttingRecipeEvent.class}, "This can only be used when registering a Cooking, Blasting, Furnace, Campfire, Smoking or Stonecutting Recipe."), BASE("[recipe] base item['s]", "recipe base item's", SmithingRecipeEvent.class, - "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), - TEMPLATE("[recipe] template item['s]", "recipe template item's", SmithingRecipeEvent.class, + "This can only be used when registering a Smithing, Smithing Transform, or Smithing Trim Recipe."), + TEMPLATE("[recipe] template item['s]", "recipe template item's", new Class[]{SmithingTransformRecipeEvent.class, SmithingTrimRecipeEvent.class}, "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."), ADDITION("[recipe] addition[al] item['s]", "recipe additional item's", SmithingRecipeEvent.class, - "This can only be used when registering a Smithing Transform or Smithing Trim Recipe."); + "This can only be used when registering a Smithing, Smithing Transform or Smithing Trim Recipe."); private String pattern, toString, error; @@ -79,14 +80,14 @@ enum RecipePattern { private Class[] eventClasses; RecipePattern(String pattern, String toString, Class eventClass, String error) { - this.pattern = "[the] " + pattern + " [of %recipes%]"; + this.pattern = "[the] " + pattern + " [of %-recipes%]"; this.toString = toString; this.eventClass = eventClass; this.error = error; } RecipePattern(String pattern, String toString, Class[] eventClasses, String error) { - this.pattern = "[the] " + pattern + " [of %recipes%]"; + this.pattern = "[the] " + pattern + " [of %-recipes%]"; this.toString = toString; this.eventClasses = eventClasses; this.error = error; @@ -112,7 +113,7 @@ enum RecipePattern { @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { selectedChoice = recipePatterns[matchedPattern]; - if (!exprs[0].isDefault()) { + if (exprs[0] != null) { setExpr((Expression) exprs[0]); } else { if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { @@ -163,6 +164,8 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye }).toList()); } else if (recipe instanceof ShapelessRecipe shapelessRecipe) { ingredients.addAll(shapelessRecipe.getIngredientList()); + } else { + customError("You can only get the ingredients of a Shaped or Shapeless Recipe."); } } case FIRSTROW, SECONDROW, THIRDROW -> { @@ -175,6 +178,8 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye if (stack == null) stack = new ItemStack(Material.AIR); ingredients.add(stack); } + } else { + customError("You can only get the ingredients of a row for a Shaped Recipe."); } } case BASE, TEMPLATE, ADDITION -> { @@ -182,8 +187,10 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye RecipeChoice choice = switch (selectedChoice) { case BASE -> smithingRecipe.getBase(); case TEMPLATE -> { - if (recipe instanceof SmithingTransformRecipe transformRecipe) yield transformRecipe.getTemplate(); - else if (recipe instanceof SmithingTrimRecipe trimRecipe) yield trimRecipe.getTemplate(); + if (recipe instanceof SmithingTransformRecipe transformRecipe) + yield transformRecipe.getTemplate(); + else if (recipe instanceof SmithingTrimRecipe trimRecipe) + yield trimRecipe.getTemplate(); yield null; } case ADDITION -> smithingRecipe.getAddition(); @@ -196,6 +203,8 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye materialChoice.getChoices().stream().map(ItemStack::new).toList() ); } + } else { + customError("You can only get the base, template, and addition items of a Smithing, Ssmithing Transform and Smithing Trim Recipe."); } } case INPUT -> { @@ -204,6 +213,8 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye choice = cookingRecipe.getInputChoice(); } else if (recipe instanceof StonecuttingRecipe stonecuttingRecipe) { choice = stonecuttingRecipe.getInputChoice(); + } else { + customError("You can only get the input item of a Cooking, Blasting, Furnace, Campfire, Smoking and Stonecutting Recipe."); } if (choice instanceof RecipeChoice.ExactChoice exactChoice) { ingredients.addAll(exactChoice.getChoices()); diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java index d0910937dbe..0ae0d3d9644 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java @@ -31,7 +31,7 @@ public class ExprRecipeResult extends PropertyExpression { static { Skript.registerExpression(ExprRecipeResult.class, ItemStack.class, ExpressionType.PROPERTY, - "[the] recipe result[ing] [item] [of %recipes%]"); + "[the] recipe result[ing] [item] [of %-recipes%]"); } private boolean isEvent = false; @@ -39,7 +39,7 @@ public class ExprRecipeResult extends PropertyExpression { @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - if (!exprs[0].isDefault()) { + if (exprs[0] != null) { setExpr((Expression) exprs[0]); } else { if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 380970f6489..15800dfb176 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -84,19 +84,11 @@ public class SecRegisterRecipe extends Section { /* TODO: - Tests - Rewrite Sec to provide a valid recipe as event value (Including rewrite of RecipeUtils.java) - Add Smithing Recipe (Enum, Ingredients, blah) + Fix Tests and expressions */ static { Skript.registerSection(SecRegisterRecipe.class, "(register|create) [a] [new] %*recipetype% with [the] (key|id) %string%"); - EventValues.registerEventValue(RegisterRecipeEvent.class, Recipe.class, new Getter() { - @Override - public @Nullable Recipe get(RegisterRecipeEvent recipe) { - return null; - } - }, EventValues.TIME_NOW); } private Expression providedName; @@ -104,6 +96,7 @@ Add Smithing Recipe (Enum, Ingredients, blah) private Trigger trigger; private Node thisNode; private String thisScript; + public static Recipe lastRegistered; @Override @SuppressWarnings("unchecked") @@ -132,8 +125,9 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye case SHAPED -> new ShapedRecipeEvent(recipeType); case SHAPELESS -> new ShapelessRecipeEvent(recipeType); case COOKING, BLASTING, FURNACE, CAMPFIRE, SMOKING -> new CookingRecipeEvent(recipeType); - case SMITHING_TRANSFORM, SMITHING_TRIM -> new SmithingRecipeEvent(recipeType); + case SMITHING, SMITHING_TRANSFORM, SMITHING_TRIM -> new SmithingRecipeEvent(recipeType); case STONECUTTING -> new StonecuttingRecipeEvent(recipeType); + default -> throw new IllegalStateException("Unexpected vale: " + recipeType); }; Variables.setLocalVariables(recipeEvent, Variables.copyLocalVariables(event)); TriggerItem.walk(trigger, recipeEvent); @@ -148,14 +142,14 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye } switch (recipeType) { case SHAPED, SHAPELESS -> { - if (recipeEvent instanceof CraftingRecipeEvent craftingRecipe) { - RecipeChoice[] ingredients = craftingRecipe.getIngredients(); + if (recipeEvent instanceof CraftingRecipeEvent craftingEvent) { + RecipeChoice[] ingredients = craftingEvent.getIngredients(); if (ingredients.length < 2 || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < 2) { customError("You must have at least 2 ingredients when registering a '" + recipeType + "' recipe."); return super.walk(event, false); } - String group = craftingRecipe.getGroup(); - CraftingBookCategory category = craftingRecipe.getCategory(); + String group = craftingEvent.getGroup(); + CraftingBookCategory category = craftingEvent.getCategory(); switch (recipeType) { case SHAPED -> createShapedRecipe(key, result, ingredients, group, category); case SHAPELESS -> createShapelessRecipe(key, result, ingredients, group, category); @@ -163,26 +157,26 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye } } case COOKING, BLASTING, FURNACE, CAMPFIRE, SMOKING -> { - if (recipeEvent instanceof CookingRecipeEvent cookingRecipe) { - RecipeChoice input = cookingRecipe.getInput(); - String group = cookingRecipe.getGroup(); - CookingBookCategory category = cookingRecipe.getCategory(); - int cookingTime = cookingRecipe.getCookingTime(); - float experience = cookingRecipe.getExperience(); + if (recipeEvent instanceof CookingRecipeEvent cookingEvent) { + RecipeChoice input = cookingEvent.getInput(); + String group = cookingEvent.getGroup(); + CookingBookCategory category = cookingEvent.getCategory(); + int cookingTime = cookingEvent.getCookingTime(); + float experience = cookingEvent.getExperience(); createCookingRecipe(recipeType, key, result, input, group, category, cookingTime, experience); } } - case SMITHING_TRANSFORM, SMITHING_TRIM -> { - if (recipeEvent instanceof SmithingRecipeEvent smithingRecipe) { - RecipeChoice base = smithingRecipe.getBase(); - RecipeChoice template = smithingRecipe.getTemplate(); - RecipeChoice addition = smithingRecipe.getAddition(); + case SMITHING, SMITHING_TRANSFORM, SMITHING_TRIM -> { + if (recipeEvent instanceof SmithingRecipeEvent smithingEvent) { + RecipeChoice base = smithingEvent.getBase(); + RecipeChoice template = smithingEvent.getTemplate(); + RecipeChoice addition = smithingEvent.getAddition(); createSmithingRecipe(recipeType, key, result, base, template, addition); } } case STONECUTTING -> { - if (recipeEvent instanceof StonecuttingRecipeEvent stonecuttingRecipe) { - RecipeChoice input = stonecuttingRecipe.getInput(); + if (recipeEvent instanceof StonecuttingRecipeEvent stonecuttingEvent) { + RecipeChoice input = stonecuttingEvent.getInput(); createStonecuttingRecipe(key, result, input); } } @@ -195,6 +189,7 @@ private void completeRecipe(NamespacedKey key, Recipe recipe) { if (Bukkit.getRecipe(key) != null) Bukkit.removeRecipe(key); Bukkit.addRecipe(recipe); + lastRegistered = recipe; } private void createShapedRecipe(NamespacedKey key, ItemStack result, RecipeChoice[] ingredients, String group, CraftingBookCategory category) { @@ -277,4 +272,4 @@ public String toString(@Nullable Event event, boolean debug) { return "register a new " + providedType.toString(event, debug) + " recipe with the namespacekey " + providedName.toString(event, debug); } -} +} \ No newline at end of file diff --git a/src/main/java/ch/njol/skript/util/RecipeUtils.java b/src/main/java/ch/njol/skript/util/RecipeUtils.java index c496f6f28bd..08e293522cf 100644 --- a/src/main/java/ch/njol/skript/util/RecipeUtils.java +++ b/src/main/java/ch/njol/skript/util/RecipeUtils.java @@ -19,6 +19,7 @@ public enum RecipeType { FURNACE(FurnaceRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.FurnaceRecipeEvent.class), CAMPFIRE(CampfireRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.CampfireRecipeEvent.class), SMOKING(SmokingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.SmokingRecipeEvent.class), + SMITHING(SmithingRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.class), SMITHING_TRANSFORM(SmithingTransformRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.SmithingTransformRecipeEvent.class), SMITHING_TRIM(SmithingTrimRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.SmithingTrimRecipeEvent.class), STONECUTTING(StonecuttingRecipe.class, RegisterRecipeEvent.StonecuttingRecipeEvent.class); @@ -284,6 +285,7 @@ public Class getRecipeEventFromRecipeType(RecipeType recipeType case CAMPFIRE -> RegisterRecipeEvent.CookingRecipeEvent.CampfireRecipeEvent.class; case FURNACE -> RegisterRecipeEvent.CookingRecipeEvent.FurnaceRecipeEvent.class; case SMOKING -> RegisterRecipeEvent.CookingRecipeEvent.SmokingRecipeEvent.class; + case SMITHING -> RegisterRecipeEvent.SmithingRecipeEvent.class; case SMITHING_TRANSFORM -> RegisterRecipeEvent.SmithingRecipeEvent.SmithingTransformRecipeEvent.class; case SMITHING_TRIM -> RegisterRecipeEvent.SmithingRecipeEvent.SmithingTrimRecipeEvent.class; case STONECUTTING -> RegisterRecipeEvent.StonecuttingRecipeEvent.class; @@ -294,4 +296,4 @@ public Class getRecipeEventFromRecipeClass(Class 0 with "All recipes did not return sufficient data" + set {_all_shaped} to size of all shaped recipes + assert {_all_shaped} > 0 with "All shaped recipes did not return sufficient data" + set {_custom} to size of all custom recipes + set {_custom_shaped} to size of all custom shaped recipes + + register a new shaped recipe with the key "test_all_recipes": + set the recipe ingredients to coal, charcoal and copper + set the recipe result to lightning rod + + assert (size of all recipes) = ({_all} + 1) with "Mismatching size of all comparison" + assert (size of all shaped recipes) = ({_all_shaped} + 1) with "Mismatching size of all shaped comparison" + assert (size of all custom recipes) = ({_custom} + 1) with "Mismatching size of all custom comparison" + assert (size of all custom shaped recipes) = ({_custom_shaped} + 1) with "Mismacthing size of all custom shaped comparison" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk b/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk new file mode 100644 index 00000000000..4bc54efaec2 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk @@ -0,0 +1,8 @@ +test "get recipe": + register a new shaped recipe with the key "test_get_recipe": + set the recipe ingredients to diamond, air, diamond, air, emerald, air, diamond, air and diamond + set the recipe result to netherite sword named "test_get_recipe" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_get_recipe" + assert {_get} != null with "Could not retrieve recipe" + assert {_get} = {_last} with "Retrieved recipe does not match from last registered" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk new file mode 100644 index 00000000000..b00cd171ad2 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk @@ -0,0 +1,19 @@ +test "recipe crafting category": + register a new shaped recipe with the key "test_recipe_crafting_category": + set the recipe ingredients to oak log, oak plank and oak wood + set the recipe crafting category to crafting misc + set the recipe result to oak sapling + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_crafting_category" + assert the recipe crafting category of {_last} = crafting misc with "Crafting category mismatch of last registered recipe" + assert the recipe crafting category of {_get} = crafting misc with "Crafting category mismatch of get recipe" + +test "recipe cooking category": + register a new cooking recipe with the key "test_recipe_cooking_category": + set the input item to raw copper named "test_recipe_cooking_category" + set the recipe cooking category to cooking misc + set the result to copper ingot named "test_recipe_cooking_category" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_cooking_category" + assert the recipe crafting category of {_last} = cooking misc with "Cooking category mismatch of last registered recipe" + assert the recipe crafting category of {_get} = cooking misc with "Cooking category mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk new file mode 100644 index 00000000000..b86f0b445f8 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk @@ -0,0 +1,9 @@ +test "recipe cooking time": + register a new cooking recipe with the key "test_recipe_cooking_time": + set the input item to raw copper named "test_recipe_cooking_time" + set the recipe cooking time to 20 seconds + set the result to copper ingot named "test_recipe_cooking_time" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_cooking_time" + assert the recipe cooking time of {_last} = 20 seconds with "Cooking time mismatch of last registered recipe" + assert the recipe cooking time of {_get} = 20 seconds with "Cooking time mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk new file mode 100644 index 00000000000..d12c7e9b4b4 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk @@ -0,0 +1,9 @@ +test "recipe experience": + register a new cooking recipe with the key "test_recipe_experience": + set the input item to raw copper named "test_recipe_experience" + set the recipe experience to 100 + set the result to copper ingot named "test_recipe_experience" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_experience" + assert the recipe experience of {_last} = 100 with "Experience mismatch of last registered recipe" + assert the recipe experience of {_get} = 100 with "Experience mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk new file mode 100644 index 00000000000..b52ff220bd6 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk @@ -0,0 +1,9 @@ +test "recipe group": + register a new cooking recipe with the key "test_recipe_group": + set the input item to raw copper named "test_recipe_group" + set the recipe group to "test_group" + set the result to copper ingot named "test_recipe_group" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_group" + assert the recipe group of {_last} = "test_group" with "Group mismatch of last registered recipe" + assert the recipe group of {_get} = "test_group" with "Group mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk new file mode 100644 index 00000000000..e35b1002e52 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk @@ -0,0 +1,8 @@ +test "recipe key": + register a new cooking recipe with the key "test_recipe_key": + set the input item to raw copper named "test_recipe_key" + set the result to copper ingot named "test_recipe_key" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_key" + assert the recipe key of {_last} = "test_recipe_key" with "Key mismatch of last registered recipe" + assert the recipe key of {_get} = "test_recipe_key" with "Key mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk new file mode 100644 index 00000000000..3046ec412db --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk @@ -0,0 +1,9 @@ +test "recipe result": + set {_result} to copper ingot named "test_recipe_result" + register a new cooking recipe with the key "test_recipe_result": + set the input item to raw copper named "test_recipe_result" + set the result to {_result} + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_result" + assert the recipe result of {_last} = {_result} with "Result mismatch of last registered recipe" + assert the recipe experience of {_get} = {_result} with "Result mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk new file mode 100644 index 00000000000..4c6a762c807 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk @@ -0,0 +1,103 @@ +test "shaped recipe type": + register a new shaped recipe with the key "test_shaped_recipe_type": + set the recipe ingredients to emerald and stick + set the recipe result to netherite sword named "test_shaped_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_shaped_recipe_type" + assert the recipe type of {_last} = shaped recipe with "Shaped recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = shaped recipe with "Shaped recipe type mismatch of get recipe" + +test "shapeless recipe type": + register a new shapeless recipe with the key "test_shapeless_recipe_type": + set the recipe ingredients to coal and oak log + set the recipe result to netherite sword named "test_shapeless_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_shapeless_recipe_type" + assert the recipe type of {_last} = shapeless recipe with "Shapeless recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = shapeless recipe with "Shapeless recipe type mismatch of get recipe" + +test "cooking recipe type": + register a new cooking recipe with the key "test_cooking_recipe_type": + set the recipe input item to raw copper named "test_cooking_recipe_type" + set the recipe result to copper ingot named "test_cooking_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_cooking_recipe_type" + assert the recipe type of {_last} = cooking recipe with "Cooking recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = cooking recipe with "Cooking recipe type mismatch of get recipe" + +test "blasting recipe type": + register a new blasting recipe with the key "test_blasting_recipe_type": + set the recipe input item to raw iron named "test_blasting_recipe_type" + set the recipe result to iron ingot named "test_blasting_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_blasting_recipe_type" + assert the recipe type of {_last} = blasting recipe with "Blasting recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = blasting recipe with "Blasting recipe type mismatch of get recipe" + +test "furnace recipe type": + register a new furnace recipe with the key "test_furnace_recipe_type": + set the recipe input item to raw gold named "test_furnace_recipe_type" + set the recipe result to gold ingot named "test_furnace_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_furnace_recipe_type" + assert the recipe type of {_last} = furnace recipe with "Furnace recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = furnace recipe with "Furnace recipe type mismatch of get recipe" + +test "campfire recipe type": + register a new campfire recipe with the key "test_campfire_recipe_type": + set the recipe input item to raw copper named "test_campfire_recipe_type" + set the recipe result to copper ingot named "test_campfire_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_campfire_recipe_type" + assert the recipe type of {_last} = campfire recipe with "Campfire recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = campfire recipe with "Campfire recipe type mismatch of get recipe" + +test "smoking recipe type": + register a new smoking recipe with the key "test_smoking_recipe_type": + set the recipe input item to raw iron named "test_smoking_recipe_type" + set the recipe result to iron ingot named "test_smoking_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_smoking_recipe_type" + assert the recipe type of {_last} = smoking recipe with "Smoking recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = smoking recipe with "Smoking recipe type mismatch of get recipe" + +test "smithing recipe type": + register a new smithing recipe with the key "test_smithing_recipe_type": + set the recipe base item to iron ingot named "test_smithing_recipe_type" + set the recipe additional item to gold ingot named "test_smithing_recipe_type" + set the recipe result to netherite ingot named "test_smithing_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_smithing_recipe_type" + assert the recipe type of {_last} = smithing recipe with "Smithing recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = smithing recipe with "Smithing recipe type mismatch of get recipe" + +test "smithing transform recipe type": + register a new smithing transform recipe with the key "test_smithing_transform_recipe_type": + set the recipe base item to iron ingot named "test_smithing_transform_recipe_type" + set the recipe additional item to gold ingot named "test_smithing_transform_recipe_type" + set the recipe template item to diamond named "test_smithing_transform_recipe_type" + set the recipe result to netherite ingot named "test_smithing_transform_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_smithing_transform_recipe_type" + assert the recipe type of {_last} = smithing transform recipe with "Smithing Transform recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = smithing transform recipe with "Smithing Transform recipe type mismatch of get recipe" + +test "smithing trim recipe type": + register a new smithing trim recipe with the key "test_smithing_trim_recipe_type": + set the recipe base item to iron ingot named "test_smithing_trim_recipe_type" + set the recipe additional item to gold ingot named "test_smithing_trim_recipe_type" + set the recipe template item to diamond named "test_smithing_trim_recipe_type" + set the recipe result to netherite ingot named "test_smithing_trim_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_smithing_trim_recipe_type" + assert the recipe type of {_last} = smithing trim recipe with "Smithing Trim recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = smithing trim recipe with "Smithing Trim recipe type mismatch of get recipe" + +test "stonecutting recipe type": + register a new stonecutting recipe with the key "test_stonecutting_recipe_type": + set the recipe input item to stone named "test_stonecutting_recipe_type" + set the recipe result item to smooth stone named "test_stonecutting_recipe_type" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_stonecutting_recipe_type" + assert the recipe type of {_last} = stonecutting recipe with "Stonecutting recipe type mismatch of last registered recipe" + assert the recipe type of {_get} = stonecutting recipe with "Stonecutting recipe type mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk b/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk new file mode 100644 index 00000000000..db9841566b0 --- /dev/null +++ b/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk @@ -0,0 +1,78 @@ +test "register shaped recipe": + register a new shaped recipe with the key "test_register_shaped_recipe": + set the recipe ingredients to diamond, air, diamond, air, emerald, air, diamond, air and diamond + set the recipe result to netherite sword named "test_register_shaped_recipe" + assert the recipe "test_register_shaped_recipe" exists with "Shaped recipe does not exist" + +test "register shapeless recipe": + register a new shapeless recipe with the key "test_register_shapeless_recipe": + set the recipe ingredients to diamond, iron ingot and netherite ingot + set the recipe result to netherite sword named "test_register_shapeless_recipe" + assert the recipe "test_register_shapeless_recipe" exists + +test "register shapeless recipe fail": + parse: + register a new shapeless recipe with the key "test_register_shapeless_recipe_fail": + set the recipe ingredients of the 1st row to iron ingot, diamond and gold ingot #Fail + set the recipe result to netherite sword named "test_register_shapeless_recipe_fail" + assert last parse logs contains "This can only be used when registering a Shaped Recipe." with "Ingredients of a row did not fail for Shapeless recipe" + assert the recipe "test_register_shapeless_recipe_fail" does not exist with "Shapeless recipe should not have registered after failing" + +test "register cooking recipe": + register a new cooking recipe with the key "test_register_cooking_recipe": + set the recipe input item to raw copper named "test_register_cooking_recipe" + set the recipe result to copper ingot named "test_register_cooking_recipe" + assert the recipe "test_register_cooking_recipe" exists with "Cooking recipe does not exist" + +test "register blasting recipe": + register a new blasting recipe with the key "test_register_blasting_recipe": + set the recipe input item to raw iron named "test_register_blasting_recipe" + set the recipe result to iron ingot named "test_register_blasting_recipe" + assert the recipe "test_register_blasting_recipe" exists with "Blasting recipe does not exist" + +test "register furnace recipe": + register a new furnace recipe with the key "test_register_furnace_recipe": + set the recipe input item to raw gold named "test_register_furnace_recipe" + set the recipe result to gold ingot named "test_register_furnace_recipe" + assert the recipe "test_register_furnace_recipe" exists with "Furnace recipe does not exist" + +test "register campfire recipe": + register a new campfire recipe with the key "test_register_campfire_recipe": + set the recipe input item to raw copper named "test_register_campfire_recipe" + set the recipe result to copper ingot named "test_register_campfire_recipe" + assert the recipe "test_register_campfire_recipe" exists with "Campfire recipe does not exist" + +test "register smoking recipe": + register a new smoking recipe with the key "test_register_smoking_recipe": + set the recipe input item to raw iron named "test_register_smoking_recipe" + set the recipe result to iron ingot named "test_register_smoking_recipe" + assert the recipe "test_register_smoking_recipe" exists with "Smoking recipe does not exist" + +test "register smithing recipe": + register a new smithing recipe with the key "test_register_smithing_recipe": + set the recipe base item to iron ingot named "test_register_smithing_recipe" + set the recipe additional item to gold ingot named "test_register_smithing_recipe" + set the recipe result to netherite ingot named "test_register_smithing_recipe" + assert the recipe "test_register_smithing_recipe" exists with "Smithing recipe does not exist" + +test "register smithing transform recipe": + register a new smithing transform recipe with the key "test_register_smithing_transform_recipe": + set the recipe base item to iron ingot named "test_register_smithing_transform_recipe" + set the recipe additional item to gold ingot named "test_register_smithing_transform_recipe" + set the recipe template item to diamond named "test_register_smithing_transform_recipe" + set the recipe result to netherite ingot named "test_register_smithing_transform_recipe" + assert the recipe "test_register_smithing_transform_recipe" exists with "Smithing Transform recipe does not exist" + +test "register smithing trim recipe": + register a new smithing trim recipe with the key "test_register_smithing_trim_recipe": + set the recipe base item to iron ingot named "test_register_smithing_trim_recipe" + set the recipe additional item to gold ingot named "test_register_smithing_trim_recipe" + set the recipe template item to diamond named "test_register_smithing_trim_recipe" + set the recipe result to netherite ingot named "test_register_smithing_trim_recipe" + assert the recipe "test_register_smithing_trim_recipe" exists with "Smithing Trim recipe does not exist" + +test "register stonecutting recipe": + register a new stonecutting recipe with the key "test_register_stonecutting_recipe": + set the recipe input item to stone named "test_register_stonecutting_recipe" + set the recipe result item to smooth stone named "test_register_stonecutting_recipe" + assert the recipe "test_register_stonecutting_recipe" exists with "Stonecutting recipe does not exist" From a687e0fccc7d3abfa0b89574db07d0cb51a28e47 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Sun, 13 Oct 2024 17:34:25 -0400 Subject: [PATCH 10/20] Some Fixes --- .../conditions/CondDiscoveredRecipes.java | 3 +- .../skript/conditions/CondRecipeExists.java | 3 +- .../skript/effects/EffDiscoverRecipe.java | 3 +- .../njol/skript/effects/EffRemoveRecipe.java | 3 +- .../skript/expressions/ExprAllRecipes.java | 15 ++- .../skript/expressions/ExprGetRecipe.java | 3 +- .../expressions/ExprRecipeCategory.java | 14 +-- .../skript/expressions/ExprRecipeKey.java | 1 + .../skript/expressions/ExprRecipeKeyFrom.java | 63 ++++++++++ .../skript/expressions/ExprRecipeType.java | 1 + .../skript/sections/SecRegisterRecipe.java | 8 +- .../ch/njol/skript/util/NamespacedUtils.java | 115 ++++++++++++++++++ .../java/ch/njol/skript/util/RecipeUtils.java | 6 +- .../syntaxes/expressions/ExprAllRecipes.sk | 2 +- .../syntaxes/expressions/ExprGetRecipe.sk | 2 +- .../expressions/ExprRecipeCategory.sk | 8 +- .../expressions/ExprRecipeCookingTime.sk | 4 +- .../expressions/ExprRecipeExperience.sk | 4 +- .../syntaxes/expressions/ExprRecipeGroup.sk | 4 +- .../syntaxes/expressions/ExprRecipeKey.sk | 8 +- .../syntaxes/expressions/ExprRecipeResult.sk | 4 +- .../syntaxes/sections/SecRegisterRecipe.sk | 2 +- 22 files changed, 234 insertions(+), 42 deletions(-) create mode 100644 src/main/java/ch/njol/skript/expressions/ExprRecipeKeyFrom.java create mode 100644 src/main/java/ch/njol/skript/util/NamespacedUtils.java diff --git a/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java b/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java index 216c9312fd6..c671d4addd8 100644 --- a/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java +++ b/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java @@ -8,6 +8,7 @@ import ch.njol.skript.lang.Condition; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; @@ -50,7 +51,7 @@ public boolean check(Event event) { return players.check(event, player -> recipes.check(event, recipe -> { - NamespacedKey key = NamespacedKey.fromString(recipe, Skript.getInstance()); + NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe); if (Bukkit.getRecipe(key) != null) return player.hasDiscoveredRecipe(key); return false; diff --git a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java index 2d1597d8ff9..cddbc47335f 100644 --- a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java +++ b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java @@ -8,6 +8,7 @@ import ch.njol.skript.lang.Condition; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; @@ -41,7 +42,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override public boolean check(Event event) { - return recipes.check(event, recipe -> Bukkit.getRecipe(NamespacedKey.fromString(recipe, Skript.getInstance())) != null); + return recipes.check(event, recipe -> Bukkit.getRecipe(NamespacedUtils.getNamespacedKey(recipe)) != null); } @Override diff --git a/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java b/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java index cb036e87ac4..78946388bc1 100644 --- a/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java +++ b/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java @@ -8,6 +8,7 @@ import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; @@ -51,7 +52,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye protected void execute(Event event) { for (Player player : players.getArray(event)) { for (String recipe : recipes.getArray(event)) { - NamespacedKey key = NamespacedKey.fromString(recipe, Skript.getInstance()); + NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe); if (Bukkit.getRecipe(key) != null) { if (isDiscover) player.discoverRecipe(key); diff --git a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java index b5897800833..bfb16a55a1d 100644 --- a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java +++ b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java @@ -8,6 +8,7 @@ import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; @@ -40,7 +41,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected void execute(Event event) { for (String recipe : recipes.getArray(event)) { - NamespacedKey key = NamespacedKey.fromString(recipe, Skript.getInstance()); + NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe); if (Bukkit.getRecipe(key) != null) Bukkit.removeRecipe(key); } diff --git a/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java b/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java index 5102ddc33d6..10179d4f538 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java +++ b/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java @@ -42,9 +42,12 @@ public class ExprAllRecipes extends SimpleExpression { static { Skript.registerExpression(ExprAllRecipes.class, Recipe.class, ExpressionType.SIMPLE, - "all [of the] (%recipetype%|recipes) [items:for %itemstacks/itemtypes%]", - "all [of the] (mc|minecraft|vanilla) (%recipetype%|recipes) [items:for %itemstacks/itemtypes%]", - "all [of the] custom (%recipetype%|recipes) [items:for %itemstacks/itemtypes%]"); + "all [of the] recipes [items:for %-itemstacks/itemtypes%]", + "all [of the] (mc|minecraft|vanilla) recipes [items:for %-itemstacks/itemtypes%]", + "all [of the] custom recipes [items:for %-itemstacks/itemtypes%]", + "all [of the] %recipetype% [items:for %-itemstacks/itemtypes%]", + "all [of the] (mc|minecraft|vanilla) %recipetype% [items:for %-itemstacks/itemtypes%]", + "all [of the] custom %recipetype% [items:for %-itemstacks/itemtypes%]"); } private Expression recipeTypeExpr; @@ -54,10 +57,10 @@ public class ExprAllRecipes extends SimpleExpression { @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - recipeTypeExpr = exprs[0] != null ? (Expression) exprs[0] : null; + recipeTypeExpr = matchedPattern >= 3 ? (Expression) exprs[0] : null; itemExpr = parseResult.hasTag("items") ? exprs[1] : null; - getMinecraft = matchedPattern == 1; - getCustom = matchedPattern == 2; + getMinecraft = matchedPattern == 1 || matchedPattern == 4; + getCustom = matchedPattern == 2 || matchedPattern == 5; return true; } diff --git a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java index 93cad9eac5e..c87e1c38dd2 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java +++ b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java @@ -9,6 +9,7 @@ import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.skript.util.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; @@ -46,7 +47,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye protected Recipe @Nullable [] get(Event event) { List recipeList = new ArrayList<>(); for (String name : recipeNames.getArray(event)) { - NamespacedKey key = NamespacedKey.fromString(name, Skript.getInstance()); + NamespacedKey key = NamespacedUtils.getNamespacedKey(name); Recipe check = Bukkit.getRecipe(key); if (check != null) recipeList.add(check); diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java index 307052f529e..dea7f2eaa7c 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java @@ -41,10 +41,10 @@ "\telse if recipe type of loop-recipe is cooking recipe:", "\t\tbroadcast recipe cooking category of loop-recipe" }) -public class ExprRecipeCategory extends PropertyExpression { +public class ExprRecipeCategory extends PropertyExpression { static { - Skript.registerExpression(ExprRecipeCategory.class, String.class, ExpressionType.PROPERTY, + Skript.registerExpression(ExprRecipeCategory.class, Object.class, ExpressionType.PROPERTY, "[the] [recipe] crafting category [of %-recipes%]", "[the] [recipe] cooking category [of %-recipes%]"); } @@ -77,15 +77,15 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye } @Override - protected String @Nullable [] get(Event event, Recipe[] source) { + protected Object @Nullable [] get(Event event, Recipe[] source) { if (isEvent) return null; return get(source, recipe -> { if (isCrafting && recipe instanceof CraftingRecipe craftingRecipe) { - return craftingRecipe.getCategory().name(); + return craftingRecipe.getCategory(); } else if (!isCrafting && recipe instanceof CookingRecipe cookingRecipe) { - return cookingRecipe.getCategory().name(); + return cookingRecipe.getCategory(); } return null; }); @@ -116,8 +116,8 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { } @Override - public Class getReturnType() { - return String.class; + public Class getReturnType() { + return isCrafting ? CraftingBookCategory.class : CookingBookCategory.class; } @Override diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java index d835da7ea6b..1646a0e684c 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java @@ -40,6 +40,7 @@ public class ExprRecipeKey extends PropertyExpression { @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { recipes = (Expression) exprs[0]; + setExpr(recipes); return true; } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeKeyFrom.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeKeyFrom.java new file mode 100644 index 00000000000..792f1224ad5 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeKeyFrom.java @@ -0,0 +1,63 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.skript.util.NamespacedUtils; +import ch.njol.util.Kleenean; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +@Name("Recipe Key From String") +@Description({ + "Gets the end product key from a string", + "To produce a valid key, the provided string has to be altered to meet the requirements." +}) +@Examples({ + "send the recipe key from \"my_recipe\"", + "loop all custom recipes:", + "\tif recipe key of loop-recipe = recipe key from \"my_recipe\":", + "\t\tbroadcast loop-recipe" +}) +public class ExprRecipeKeyFrom extends SimpleExpression { + + static { + Skript.registerExpression(ExprRecipeKeyFrom.class, String.class, ExpressionType.SIMPLE, "[the] recipe key[s] from %strings%"); + } + + private Expression names; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + names = (Expression) exprs[0]; + return true; + } + + @Override + protected String @Nullable [] get(Event event) { + return Arrays.stream(names.getArray(event)).map(name -> NamespacedUtils.getNamespacedKey(name).toString()).toArray(String[]::new); + } + + @Override + public boolean isSingle() { + return names.isSingle(); + } + + @Override + public Class getReturnType() { + return String.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "recipe keys from " + names.toString(event, debug); + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java index 5aa615b1d4a..954ab98d926 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java @@ -39,6 +39,7 @@ public class ExprRecipeType extends PropertyExpression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { recipes = (Expression) exprs[0]; + setExpr(recipes); return true; } diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 15800dfb176..0a2b98f91a2 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -12,6 +12,7 @@ import ch.njol.skript.registrations.EventValues; import ch.njol.skript.util.Getter; import ch.njol.skript.util.LiteralUtils; +import ch.njol.skript.util.NamespacedUtils; import ch.njol.skript.util.RecipeUtils; import ch.njol.skript.util.RecipeUtils.*; import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; @@ -119,7 +120,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected @Nullable TriggerItem walk(Event event) { String name = providedName.getSingle(event); - NamespacedKey key = NamespacedKey.fromString(name, Skript.getInstance()); + NamespacedKey key = NamespacedUtils.getNamespacedKey(name); RecipeType recipeType = providedType.getSingle(event); RegisterRecipeEvent recipeEvent = switch (recipeType) { case SHAPED -> new ShapedRecipeEvent(recipeType); @@ -206,6 +207,7 @@ private void createShapedRecipe(NamespacedKey key, ItemStack result, RecipeChoic shapedRecipe.setIngredient(characters[i], thisChoice); } completeRecipe(key, shapedRecipe); + return; } private void createShapelessRecipe(NamespacedKey key, ItemStack result, RecipeChoice[] ingredients, String group, CraftingBookCategory category) { @@ -228,6 +230,7 @@ private void createCookingRecipe(RecipeType recipeType, NamespacedKey key, ItemS case CAMPFIRE -> new CampfireRecipe(key, result, input, experience, cookingTime); case FURNACE -> new FurnaceRecipe(key, result, input, experience, cookingTime); case SMOKING -> new SmokingRecipe(key, result, input, experience, cookingTime); + case COOKING -> new CookingRecipe<>(key, result, input, experience, cookingTime) {}; default -> null; }; if (recipe == null) @@ -240,13 +243,14 @@ private void createCookingRecipe(RecipeType recipeType, NamespacedKey key, ItemS } private void createSmithingRecipe(RecipeType recipeType, NamespacedKey key, ItemStack result, RecipeChoice base, RecipeChoice template, RecipeChoice addition) { - if (base == null || template == null || addition == null) { + if (base == null || (template == null && recipeType != RecipeType.SMITHING) || addition == null) { customError("Unable to create '" + recipeType + "' recipe, missing data."); return; } var recipe = switch (recipeType) { case SMITHING_TRANSFORM -> new SmithingTransformRecipe(key, result, template, base, addition); case SMITHING_TRIM -> new SmithingTrimRecipe(key, template, base, addition); + case SMITHING -> new SmithingRecipe(key, result, base, addition); default -> null; }; if (recipe == null) diff --git a/src/main/java/ch/njol/skript/util/NamespacedUtils.java b/src/main/java/ch/njol/skript/util/NamespacedUtils.java new file mode 100644 index 00000000000..c303828c497 --- /dev/null +++ b/src/main/java/ch/njol/skript/util/NamespacedUtils.java @@ -0,0 +1,115 @@ +package ch.njol.skript.util; + +import ch.njol.skript.Skript; +import ch.njol.util.Pair; +import com.google.common.collect.Sets; +import org.apache.commons.lang.ArrayUtils; +import org.bukkit.NamespacedKey; + +import java.util.Set; + +public class NamespacedUtils { + + private static final Set LEGAL_NAMESPACE_CHARS = Sets.newHashSet(ArrayUtils.toObject("abcdefghijklmnopqrstuvwxyz0123456789._-/".toCharArray())); + + /** + * Gets a namespaced key. This method will try to get existing keys first, but if that fails + * it will create the key in Skript's namespace. + * @param key the unparsed key + * @return the resulting NamespacedKey + */ + public static NamespacedKey getNamespacedKey(String key) { + NamespacedKey namespacedKey = NamespacedKey.fromString(key, Skript.getInstance()); + if (namespacedKey != null) + return namespacedKey; + NamespacedKey convertedKey = createNamespacedKey(key); + Skript.info("The key provided '" + key + "' has been converted to '" + convertedKey + "' due to invalid characters." + + "\n\tValid characters are a-z, 0-9, -, _ and ."); + return convertedKey; + } + + /** + * Creates a namespaced key in Skript's namespace encoded to avoid the character limitations of a normal key. + * This key will be created in Skript's namespace. + * + * @param key The key to use + * @return a NamespacedKey with the encoded key in Skript's namespace + */ + public static NamespacedKey createNamespacedKey(String key) { + // TODO: add tests for this + StringBuilder encodedKeyBuilder = new StringBuilder(); + // keys must be all lowercase + key = key.toLowerCase(); + key = key.replace(' ', '_'); + int keyLength = key.length(); + for (int i = 0; i < keyLength; i++) { + char currentChar = key.charAt(i); + // if this character is legal to use in a namespace key + if (LEGAL_NAMESPACE_CHARS.contains(currentChar)) { + // if the original string had a ".x" in it, we need to escape it + // so decoding doesn't think it's a hex sequence + if (currentChar == '.' && key.charAt(i + 1) == 'x') { + i += 1; // skip the "x" + encodedKeyBuilder.append(".x"); + encodedKeyBuilder.append(Integer.toHexString('.')); + encodedKeyBuilder.append(".x"); + encodedKeyBuilder.append(Integer.toHexString('x')); + // if we're not at the end and the next char is a legal char, add the trailing dot + // to represent the end of the hex sequence + if (i != (keyLength - 1) && LEGAL_NAMESPACE_CHARS.contains(key.charAt(i + 1))) + encodedKeyBuilder.append('.'); + } else { + // we are dealing with a legal character, so we can just append it + encodedKeyBuilder.append(currentChar); + } + } else { + // add ".x(hex code)" to the encoded key + encodedKeyBuilder.append(".x"); + encodedKeyBuilder.append(Integer.toHexString(currentChar)); + // only add the trailing dot if the next character is a legal character + if (i != (keyLength - 1) && LEGAL_NAMESPACE_CHARS.contains(key.charAt(i + 1))) + encodedKeyBuilder.append('.'); + } + } + return new NamespacedKey(Skript.getInstance(), encodedKeyBuilder.toString()); + } + + /** + * Decodes a NamespacedKey encoded by #getNamespacedKey + * + * @param namespacedKey the namespaced key to decode + * @return a Pair with the first element as the namespace and the second as the decoded key + */ + public static Pair decodeNamespacedKey(NamespacedKey namespacedKey) { + // TODO: add tests for this + String encodedKey = namespacedKey.getKey(); + StringBuilder decodedKeyBuilder = new StringBuilder(); + int encodedKeyLength = encodedKey.length(); + int lastCharIndex = encodedKeyLength - 1; + for (int i = 0; i < encodedKeyLength; i++) { + char currentChar = encodedKey.charAt(i); + // if we are encountering a ".x" hex sequence + if (i != lastCharIndex && currentChar == '.' && encodedKey.charAt(i + 1) == 'x') { + i += 2; // skip the ".x" so it isn't part of our hex string + StringBuilder hexString = new StringBuilder(); + // The hex sequence continues until a . is encountered or we reach the end of the string + while (i <= lastCharIndex && encodedKey.charAt(i) != '.') { + hexString.append(encodedKey.charAt(i)); + i++; + } + // if the . was the start of another ".x" hex sequence, back up by 1 character + if (i <= lastCharIndex && encodedKey.charAt(i + 1) == 'x') + i--; + // parse the hex sequence to a char + char decodedChar = (char) Long.parseLong(hexString.toString(), 16); + decodedKeyBuilder.append(decodedChar); + } else { + // this is just a normal character, not a hex sequence + // so we can just append it + decodedKeyBuilder.append(currentChar); + } + } + return new Pair<>(namespacedKey.getNamespace(), decodedKeyBuilder.toString()); + } + +} diff --git a/src/main/java/ch/njol/skript/util/RecipeUtils.java b/src/main/java/ch/njol/skript/util/RecipeUtils.java index 08e293522cf..7a22cb1e140 100644 --- a/src/main/java/ch/njol/skript/util/RecipeUtils.java +++ b/src/main/java/ch/njol/skript/util/RecipeUtils.java @@ -14,14 +14,14 @@ public class RecipeUtils { public enum RecipeType { SHAPED(ShapedRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class), SHAPELESS(ShapelessRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapelessRecipeEvent.class), - COOKING(CookingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.class), BLASTING(BlastingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.BlastingRecipeEvent.class), FURNACE(FurnaceRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.FurnaceRecipeEvent.class), CAMPFIRE(CampfireRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.CampfireRecipeEvent.class), SMOKING(SmokingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.SmokingRecipeEvent.class), - SMITHING(SmithingRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.class), + COOKING(CookingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.class), // Having 'COOKING' under the subclasses allows for proper ExprRecipeType SMITHING_TRANSFORM(SmithingTransformRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.SmithingTransformRecipeEvent.class), SMITHING_TRIM(SmithingTrimRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.SmithingTrimRecipeEvent.class), + SMITHING(SmithingRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.class), // Having 'SMITHING' under the subclasses allows for proper ExprRecipeType STONECUTTING(StonecuttingRecipe.class, RegisterRecipeEvent.StonecuttingRecipeEvent.class); private final Class recipeClass; @@ -45,7 +45,7 @@ public Class getEventClass() { public static RecipeType getRecipeTypeFromRecipeClass(Class providedClass) { for (RecipeType type : recipeTypes) { - if (type.recipeClass.equals(providedClass)) + if (type.recipeClass.equals(providedClass) || type.recipeClass.isAssignableFrom(providedClass)) return type; } return null; diff --git a/src/test/skript/tests/syntaxes/expressions/ExprAllRecipes.sk b/src/test/skript/tests/syntaxes/expressions/ExprAllRecipes.sk index d7d4406eaf4..fb020df7a47 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprAllRecipes.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprAllRecipes.sk @@ -7,7 +7,7 @@ test "all recipes": set {_custom_shaped} to size of all custom shaped recipes register a new shaped recipe with the key "test_all_recipes": - set the recipe ingredients to coal, charcoal and copper + set the recipe ingredients to raw iron, raw gold and raw copper set the recipe result to lightning rod assert (size of all recipes) = ({_all} + 1) with "Mismatching size of all comparison" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk b/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk index 4bc54efaec2..efcceb8b757 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk @@ -4,5 +4,5 @@ test "get recipe": set the recipe result to netherite sword named "test_get_recipe" set {_last} to last registered recipe set {_get} to recipe with the key "test_get_recipe" - assert {_get} != null with "Could not retrieve recipe" + assert {_get} is set with "Could not retrieve recipe" assert {_get} = {_last} with "Retrieved recipe does not match from last registered" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk index b00cd171ad2..b08019807b1 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk @@ -10,10 +10,10 @@ test "recipe crafting category": test "recipe cooking category": register a new cooking recipe with the key "test_recipe_cooking_category": - set the input item to raw copper named "test_recipe_cooking_category" + set the recipe input item to raw copper named "test_recipe_cooking_category" set the recipe cooking category to cooking misc - set the result to copper ingot named "test_recipe_cooking_category" + set the recipe result to copper ingot named "test_recipe_cooking_category" set {_last} to last registered recipe set {_get} to recipe with the key "test_recipe_cooking_category" - assert the recipe crafting category of {_last} = cooking misc with "Cooking category mismatch of last registered recipe" - assert the recipe crafting category of {_get} = cooking misc with "Cooking category mismatch of get recipe" + assert the recipe cooking category of {_last} = cooking misc with "Cooking category mismatch of last registered recipe" + assert the recipe cooking category of {_get} = cooking misc with "Cooking category mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk index b86f0b445f8..bd4dd5f65ca 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk @@ -1,8 +1,8 @@ test "recipe cooking time": register a new cooking recipe with the key "test_recipe_cooking_time": - set the input item to raw copper named "test_recipe_cooking_time" + set the recipe input item to raw copper named "test_recipe_cooking_time" set the recipe cooking time to 20 seconds - set the result to copper ingot named "test_recipe_cooking_time" + set the recipe result to copper ingot named "test_recipe_cooking_time" set {_last} to last registered recipe set {_get} to recipe with the key "test_recipe_cooking_time" assert the recipe cooking time of {_last} = 20 seconds with "Cooking time mismatch of last registered recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk index d12c7e9b4b4..61b6f5a22b7 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk @@ -1,8 +1,8 @@ test "recipe experience": register a new cooking recipe with the key "test_recipe_experience": - set the input item to raw copper named "test_recipe_experience" + set the recipe input item to raw copper named "test_recipe_experience" set the recipe experience to 100 - set the result to copper ingot named "test_recipe_experience" + set the recipe result to copper ingot named "test_recipe_experience" set {_last} to last registered recipe set {_get} to recipe with the key "test_recipe_experience" assert the recipe experience of {_last} = 100 with "Experience mismatch of last registered recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk index b52ff220bd6..165ebf5fb81 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk @@ -1,8 +1,8 @@ test "recipe group": register a new cooking recipe with the key "test_recipe_group": - set the input item to raw copper named "test_recipe_group" + set the recipe input item to raw copper named "test_recipe_group" set the recipe group to "test_group" - set the result to copper ingot named "test_recipe_group" + set the recipe result to copper ingot named "test_recipe_group" set {_last} to last registered recipe set {_get} to recipe with the key "test_recipe_group" assert the recipe group of {_last} = "test_group" with "Group mismatch of last registered recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk index e35b1002e52..056e0e33fae 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk @@ -1,8 +1,8 @@ test "recipe key": register a new cooking recipe with the key "test_recipe_key": - set the input item to raw copper named "test_recipe_key" - set the result to copper ingot named "test_recipe_key" + set the recipe input item to raw copper named "test_recipe_key" + set the recipe result to copper ingot named "test_recipe_key" set {_last} to last registered recipe set {_get} to recipe with the key "test_recipe_key" - assert the recipe key of {_last} = "test_recipe_key" with "Key mismatch of last registered recipe" - assert the recipe key of {_get} = "test_recipe_key" with "Key mismatch of get recipe" + assert the recipe key of {_last} = recipe key from "test_recipe_key" with "Key mismatch of last registered recipe" + assert the recipe key of {_get} = recipe key from "test_recipe_key" with "Key mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk index 3046ec412db..9d2350c5ba2 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk @@ -1,8 +1,8 @@ test "recipe result": set {_result} to copper ingot named "test_recipe_result" register a new cooking recipe with the key "test_recipe_result": - set the input item to raw copper named "test_recipe_result" - set the result to {_result} + set the recipe input item to raw copper named "test_recipe_result" + set the recipe result to {_result} set {_last} to last registered recipe set {_get} to recipe with the key "test_recipe_result" assert the recipe result of {_last} = {_result} with "Result mismatch of last registered recipe" diff --git a/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk b/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk index db9841566b0..f914b552d53 100644 --- a/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk +++ b/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk @@ -8,7 +8,7 @@ test "register shapeless recipe": register a new shapeless recipe with the key "test_register_shapeless_recipe": set the recipe ingredients to diamond, iron ingot and netherite ingot set the recipe result to netherite sword named "test_register_shapeless_recipe" - assert the recipe "test_register_shapeless_recipe" exists + assert the recipe "test_register_shapeless_recipe" exists with "Shapeless recipe does not exist" test "register shapeless recipe fail": parse: From 1f79ed6184d5d8f79c0b8191fe0d8f4c73cd3956 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:57:24 -0400 Subject: [PATCH 11/20] Additional Changes + Fixes --- .../classes/data/DefaultComparators.java | 30 +++++++---- .../skript/conditions/CondRecipeExists.java | 4 +- .../skript/expressions/ExprGetRecipe.java | 2 +- .../expressions/ExprRecipeCategory.java | 18 +++++-- .../skript/expressions/ExprRecipeGroup.java | 17 +++--- .../skript/expressions/ExprRecipeKey.java | 9 ++-- .../skript/expressions/ExprRecipeResult.java | 4 ++ .../skript/expressions/ExprRecipeType.java | 14 ++--- .../skript/sections/SecRegisterRecipe.java | 53 +++++++++++-------- .../java/ch/njol/skript/util/RecipeUtils.java | 5 +- .../expressions/ExprRecipeCategory.sk | 2 +- .../expressions/ExprRecipeCookingTime.sk | 2 +- .../expressions/ExprRecipeExperience.sk | 2 +- .../syntaxes/expressions/ExprRecipeGroup.sk | 2 +- .../syntaxes/expressions/ExprRecipeKey.sk | 2 +- .../syntaxes/expressions/ExprRecipeResult.sk | 4 +- .../syntaxes/expressions/ExprRecipeType.sk | 21 ++++---- .../syntaxes/sections/SecRegisterRecipe.sk | 8 +-- 18 files changed, 109 insertions(+), 90 deletions(-) diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java index e5e42bf1423..09cc6166bd3 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -28,16 +28,7 @@ import ch.njol.skript.entity.BoatData; import ch.njol.skript.entity.EntityData; import ch.njol.skript.entity.RabbitData; -import ch.njol.skript.util.BlockUtils; -import ch.njol.skript.util.Date; -import ch.njol.skript.util.EnchantmentType; -import ch.njol.skript.util.Experience; -import ch.njol.skript.util.GameruleValue; -import ch.njol.skript.util.StructureType; -import ch.njol.skript.util.Time; -import ch.njol.skript.util.Timeperiod; -import ch.njol.skript.util.Timespan; -import ch.njol.skript.util.WeatherType; +import ch.njol.skript.util.*; import ch.njol.skript.util.slot.EquipmentSlot; import ch.njol.skript.util.slot.Slot; import ch.njol.skript.util.slot.SlotWithIndex; @@ -60,6 +51,7 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; import org.bukkit.potion.PotionEffectType; import org.skriptlang.skript.lang.comparator.Comparator; import org.skriptlang.skript.lang.comparator.Comparators; @@ -656,6 +648,24 @@ public boolean supportsOrdering() { // Potion Effect Type Comparators.registerComparator(PotionEffectType.class, PotionEffectType.class, (one, two) -> Relation.get(one.equals(two))); + + Comparators.registerComparator(Recipe.class, Recipe.class, new Comparator() { + @Override + public Relation compare(Recipe o1, Recipe o2) { + Recipe first = null; + Recipe second = null; + if (o1.getClass().getSuperclass().equals(o2.getClass())) { + first = (Recipe) o1; + second = o2; + } else if (o2.getClass().getSuperclass().equals(o1.getClass())) { + first = o1.getClass().cast(o2); + second = o1; + } + Skript.adminBroadcast("Compare 1: " + first); + Skript.adminBroadcast("Compare 2: " + second); + return Relation.NOT_EQUAL; + } + }); } } diff --git a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java index cddbc47335f..39e6863c09d 100644 --- a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java +++ b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java @@ -26,7 +26,7 @@ public class CondRecipeExists extends Condition { static { Skript.registerCondition(CondRecipeExists.class, - "[the] recipe[s] %strings% exist[s]", + "[the] recipe[s] %strings% [does] exist[s]", "[the] recipe[s] %strings% (doesn't|does not) exist[s]"); } @@ -42,7 +42,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override public boolean check(Event event) { - return recipes.check(event, recipe -> Bukkit.getRecipe(NamespacedUtils.getNamespacedKey(recipe)) != null); + return recipes.check(event, recipe -> Bukkit.getRecipe(NamespacedUtils.getNamespacedKey(recipe)) != null, isNegated()); } @Override diff --git a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java index c87e1c38dd2..701f756d51c 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java +++ b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java @@ -31,7 +31,7 @@ public class ExprGetRecipe extends SimpleExpression { static { Skript.registerExpression(ExprGetRecipe.class, Recipe.class, ExpressionType.SIMPLE, - "recipe[s] with [the] (key|id)[s] %strings%"); + "[the] recipe[s] with [the] (key|id)[s] %strings%"); } private Expression recipeNames; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java index dea7f2eaa7c..0b84620fa08 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java @@ -15,9 +15,7 @@ import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; import org.bukkit.event.Event; -import org.bukkit.inventory.CookingRecipe; -import org.bukkit.inventory.CraftingRecipe; -import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.*; import org.bukkit.inventory.recipe.CookingBookCategory; import org.bukkit.inventory.recipe.CraftingBookCategory; import org.jetbrains.annotations.Nullable; @@ -43,6 +41,8 @@ }) public class ExprRecipeCategory extends PropertyExpression { + private static final boolean SUPPORT_CRAFTING_TYPE = Skript.classExists("org.bukkit.inventory.CraftingRecipe"); + static { Skript.registerExpression(ExprRecipeCategory.class, Object.class, ExpressionType.PROPERTY, "[the] [recipe] crafting category [of %-recipes%]", @@ -82,8 +82,16 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye return null; return get(source, recipe -> { - if (isCrafting && recipe instanceof CraftingRecipe craftingRecipe) { - return craftingRecipe.getCategory(); + if (isCrafting) { + if (SUPPORT_CRAFTING_TYPE && recipe instanceof CraftingRecipe craftingRecipe) { + return craftingRecipe.getCategory(); + } else if (!SUPPORT_CRAFTING_TYPE) { + if (recipe instanceof ShapedRecipe shapedRecipe) { + return shapedRecipe.getCategory(); + } else if (recipe instanceof ShapelessRecipe shapelessRecipe) { + return shapelessRecipe.getCategory(); + } + } } else if (!isCrafting && recipe instanceof CookingRecipe cookingRecipe) { return cookingRecipe.getCategory(); } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java index f030358386a..cfdfec939a4 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java @@ -16,9 +16,7 @@ import ch.njol.util.Kleenean; import ch.njol.util.coll.CollectionUtils; import org.bukkit.event.Event; -import org.bukkit.inventory.CookingRecipe; -import org.bukkit.inventory.CraftingRecipe; -import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.*; import org.jetbrains.annotations.Nullable; @Name("Recipe Group") @@ -32,6 +30,8 @@ @Since("INSERT VERSION") public class ExprRecipeGroup extends PropertyExpression { + private static final boolean SUPPORT_CRAFTING_TYPE = Skript.classExists("org.bukkit.inventory.CraftingRecipe"); + static { Skript.registerExpression(ExprRecipeGroup.class, String.class, ExpressionType.PROPERTY, "[the] recipe group [of %-recipes%]"); } @@ -64,10 +64,15 @@ protected String[] get(Event event, Recipe[] source) { return null; return get(source, recipe -> { - if (recipe instanceof CraftingRecipe craftingRecipe) { - return craftingRecipe.getGroup(); - } else if (recipe instanceof CookingRecipe cookingRecipe) { + + if (recipe instanceof CookingRecipe cookingRecipe) { return cookingRecipe.getGroup(); + } else if (SUPPORT_CRAFTING_TYPE && recipe instanceof CraftingRecipe craftingRecipe) { + return craftingRecipe.getGroup(); + } else if (recipe instanceof ShapedRecipe shapedRecipe) { + return shapedRecipe.getGroup(); + } else if (recipe instanceof ShapelessRecipe shapelessRecipe) { + return shapelessRecipe.getGroup(); } return null; }); diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java index 1646a0e684c..193b8f61350 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java @@ -34,20 +34,17 @@ public class ExprRecipeKey extends PropertyExpression { "[the] %recipes%'[s] (key|id)[s]"); } - private Expression recipes; - @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - recipes = (Expression) exprs[0]; - setExpr(recipes); + setExpr((Expression) exprs[0]); return true; } @Override protected String @Nullable [] get(Event event, Recipe[] source) { List names = new ArrayList<>(); - for (Recipe recipe : recipes.getArray(event)) { + for (Recipe recipe : getExpr().getArray(event)) { if (recipe instanceof Keyed key) names.add(key.getKey().toString()); } @@ -61,6 +58,6 @@ public Class getReturnType() { @Override public String toString(@Nullable Event event, boolean debug) { - return "the recipe keys of " + recipes.toString(event, debug); + return "the recipe keys of " + getExpr().toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java index 0ae0d3d9644..1187f2a0059 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java @@ -19,6 +19,10 @@ import org.bukkit.inventory.Recipe; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + @Name("Recipe Result") @Description("The result item for a recipe") @Examples({ diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java index 954ab98d926..36c1531bd6a 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java @@ -16,6 +16,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; @Name("Recipe Type") @@ -33,23 +34,16 @@ public class ExprRecipeType extends PropertyExpression recipes; - @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - recipes = (Expression) exprs[0]; - setExpr(recipes); + setExpr((Expression) exprs[0]); return true; } @Override protected RecipeUtils.RecipeType @Nullable [] get(Event event, Recipe[] source) { - List types = new ArrayList<>(); - for (Recipe recipe : recipes.getArray(event)) { - types.add(RecipeUtils.getRecipeTypeFromRecipe(recipe)); - } - return types.toArray(new RecipeUtils.RecipeType[0]); + return Arrays.stream(getExpr().getArray(event)).map(RecipeUtils::getRecipeTypeFromRecipe).toArray(RecipeUtils.RecipeType[]::new); } @Override @@ -59,6 +53,6 @@ public Class getReturnType() { @Override public String toString(@Nullable Event event, boolean debug) { - return "the recipe type of " + recipes.toString(event, debug); + return "the recipe type of " + getExpr().toString(event, debug); } } diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 0a2b98f91a2..9ea3911ac85 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -36,14 +36,15 @@ @Name("Register Recipe") @Description({ "Create a custom recipe for any of the following types:", - "Shaped, Shapeless, Cooking, Blasting, Furnace, Campfire, Smoking, Smithing Transform, Smithing Trim or Stonecutting", + "Shaped, Shapeless, Blasting, Furnace, Campfire, Smoking, Smithing Transform, Smithing Trim or Stonecutting", "NOTES:", "All recipes except Smithing Trim require a 'result item'", "Shaped and Shapeless Ingredients allows custom items only on Paper", "Shaped and Shapeless have a maximum of 9 and minimum requirement of 2 ingredients", - "Blasting, Furnace, Campfire and Smoking all fall under Cooking", + "Blasting, Furnace, Campfire and Smoking all fall under Cooking Recipe Type", "Groups only apply to Shaped, Shapeless and Cooking Recipes", - "Category only applies to Shaped, Shapeless and Cooking Recipes" + "Category only applies to Shaped, Shapeless and Cooking Recipes", + "You can not create a Cooking Recipe type." }) @Examples({ "register a new shaped recipe with the name \"my_recipe\":", @@ -61,8 +62,8 @@ "\tset the recipe crafting category to crafting category misc", "\tset the recipe result item to diamond helmet named \"Heavenly Helm\"", "", - "#Blasting, Furnace, Campfire and Smoking follow same format as Cooking", - "create new cooking recipe with the namespacekey \"my_recipe\":", + "#Furnace, Campfire and Smoking follow same format as Cooking", + "create new blasting recipe with the namespacekey \"my_recipe\":", "\tset the recipe experience to 5", "\tset the recipe cooking time to 10 seconds", "\tset the recipe group to \"custom group\"", @@ -85,15 +86,23 @@ public class SecRegisterRecipe extends Section { /* TODO: - Fix Tests and expressions + Fix comparing recipe to recipe + add comparing recipe type to recipe type (sub -> super) + Comparing key of recipe to a string + Cond tests + Eff tests + Recipe event values + Maybe Complex Recipe? */ + private static final boolean RUNNING_1_20 = Skript.isRunningMinecraft(1, 20, 0); + static { Skript.registerSection(SecRegisterRecipe.class, "(register|create) [a] [new] %*recipetype% with [the] (key|id) %string%"); } private Expression providedName; - private Expression providedType; + private RecipeType providedType; private Trigger trigger; private Node thisNode; private String thisScript; @@ -102,12 +111,18 @@ public class SecRegisterRecipe extends Section { @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult, SectionNode sectionNode, List triggerItems) { - providedType = (Expression) exprs[0]; + providedType = ((Literal) exprs[0]).getSingle(); + if (providedType == RecipeType.COOKING) { + Skript.error("You can not register a 'cooking' recipe type."); + return false; + } else if (providedType == RecipeType.SMITHING && RUNNING_1_20) { + Skript.error("You can not register a 'smithing' recipe type on MC version 1.20+"); + return false; + } providedName = (Expression) exprs[1]; - Class eventClass = ((Literal) exprs[0]).getSingle().getEventClass(); AtomicBoolean delayed = new AtomicBoolean(false); Runnable afterLoading = () -> delayed.set(!getParser().getHasDelayBefore().isFalse()); - trigger = loadCode(sectionNode, "register recipe", afterLoading, eventClass); + trigger = loadCode(sectionNode, "register recipe", afterLoading, providedType.getEventClass()); if (delayed.get()) { Skript.error("Delays cannot be used within a 'register recipe' section."); return false; @@ -121,11 +136,11 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye protected @Nullable TriggerItem walk(Event event) { String name = providedName.getSingle(event); NamespacedKey key = NamespacedUtils.getNamespacedKey(name); - RecipeType recipeType = providedType.getSingle(event); + RecipeType recipeType = providedType; RegisterRecipeEvent recipeEvent = switch (recipeType) { case SHAPED -> new ShapedRecipeEvent(recipeType); case SHAPELESS -> new ShapelessRecipeEvent(recipeType); - case COOKING, BLASTING, FURNACE, CAMPFIRE, SMOKING -> new CookingRecipeEvent(recipeType); + case BLASTING, FURNACE, CAMPFIRE, SMOKING -> new CookingRecipeEvent(recipeType); case SMITHING, SMITHING_TRANSFORM, SMITHING_TRIM -> new SmithingRecipeEvent(recipeType); case STONECUTTING -> new StonecuttingRecipeEvent(recipeType); default -> throw new IllegalStateException("Unexpected vale: " + recipeType); @@ -157,7 +172,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye } } } - case COOKING, BLASTING, FURNACE, CAMPFIRE, SMOKING -> { + case BLASTING, FURNACE, CAMPFIRE, SMOKING -> { if (recipeEvent instanceof CookingRecipeEvent cookingEvent) { RecipeChoice input = cookingEvent.getInput(); String group = cookingEvent.getGroup(); @@ -207,7 +222,6 @@ private void createShapedRecipe(NamespacedKey key, ItemStack result, RecipeChoic shapedRecipe.setIngredient(characters[i], thisChoice); } completeRecipe(key, shapedRecipe); - return; } private void createShapelessRecipe(NamespacedKey key, ItemStack result, RecipeChoice[] ingredients, String group, CraftingBookCategory category) { @@ -230,11 +244,8 @@ private void createCookingRecipe(RecipeType recipeType, NamespacedKey key, ItemS case CAMPFIRE -> new CampfireRecipe(key, result, input, experience, cookingTime); case FURNACE -> new FurnaceRecipe(key, result, input, experience, cookingTime); case SMOKING -> new SmokingRecipe(key, result, input, experience, cookingTime); - case COOKING -> new CookingRecipe<>(key, result, input, experience, cookingTime) {}; - default -> null; + default -> throw new IllegalStateException("Unexpected value: " + recipeType); }; - if (recipe == null) - return; if (category != null) recipe.setCategory(category); if (group != null && !group.isEmpty()) @@ -251,10 +262,8 @@ private void createSmithingRecipe(RecipeType recipeType, NamespacedKey key, Item case SMITHING_TRANSFORM -> new SmithingTransformRecipe(key, result, template, base, addition); case SMITHING_TRIM -> new SmithingTrimRecipe(key, template, base, addition); case SMITHING -> new SmithingRecipe(key, result, base, addition); - default -> null; + default -> throw new IllegalStateException("Unexpected value: " + recipeType); }; - if (recipe == null) - return; completeRecipe(key, recipe); } @@ -273,7 +282,7 @@ private void customError(String message) { @Override public String toString(@Nullable Event event, boolean debug) { - return "register a new " + providedType.toString(event, debug) + " recipe with the namespacekey " + providedName.toString(event, debug); + return "register a new " + providedType + " recipe with the namespacekey " + providedName.toString(event, debug); } } \ No newline at end of file diff --git a/src/main/java/ch/njol/skript/util/RecipeUtils.java b/src/main/java/ch/njol/skript/util/RecipeUtils.java index 7a22cb1e140..43baf2f3785 100644 --- a/src/main/java/ch/njol/skript/util/RecipeUtils.java +++ b/src/main/java/ch/njol/skript/util/RecipeUtils.java @@ -1,5 +1,6 @@ package ch.njol.skript.util; +import ch.njol.skript.Skript; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.bukkit.inventory.*; @@ -10,7 +11,6 @@ public class RecipeUtils { // Custom enum for registering a 'recipetype' class - // TODO: If and when Bukkit creates a RecipeType enum, remove this and change lang public enum RecipeType { SHAPED(ShapedRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class), SHAPELESS(ShapelessRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapelessRecipeEvent.class), @@ -45,8 +45,9 @@ public Class getEventClass() { public static RecipeType getRecipeTypeFromRecipeClass(Class providedClass) { for (RecipeType type : recipeTypes) { - if (type.recipeClass.equals(providedClass) || type.recipeClass.isAssignableFrom(providedClass)) + if (type.recipeClass.isAssignableFrom(providedClass)) { return type; + } } return null; } diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk index b08019807b1..c65183fe1e8 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCategory.sk @@ -9,7 +9,7 @@ test "recipe crafting category": assert the recipe crafting category of {_get} = crafting misc with "Crafting category mismatch of get recipe" test "recipe cooking category": - register a new cooking recipe with the key "test_recipe_cooking_category": + register a new blasting recipe with the key "test_recipe_cooking_category": set the recipe input item to raw copper named "test_recipe_cooking_category" set the recipe cooking category to cooking misc set the recipe result to copper ingot named "test_recipe_cooking_category" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk index bd4dd5f65ca..0d845262016 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeCookingTime.sk @@ -1,5 +1,5 @@ test "recipe cooking time": - register a new cooking recipe with the key "test_recipe_cooking_time": + register a new blasting recipe with the key "test_recipe_cooking_time": set the recipe input item to raw copper named "test_recipe_cooking_time" set the recipe cooking time to 20 seconds set the recipe result to copper ingot named "test_recipe_cooking_time" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk index 61b6f5a22b7..fed399cb444 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeExperience.sk @@ -1,5 +1,5 @@ test "recipe experience": - register a new cooking recipe with the key "test_recipe_experience": + register a new blasting recipe with the key "test_recipe_experience": set the recipe input item to raw copper named "test_recipe_experience" set the recipe experience to 100 set the recipe result to copper ingot named "test_recipe_experience" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk index 165ebf5fb81..a146ca1a223 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeGroup.sk @@ -1,5 +1,5 @@ test "recipe group": - register a new cooking recipe with the key "test_recipe_group": + register a new blasting recipe with the key "test_recipe_group": set the recipe input item to raw copper named "test_recipe_group" set the recipe group to "test_group" set the recipe result to copper ingot named "test_recipe_group" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk index 056e0e33fae..652e402172a 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk @@ -1,5 +1,5 @@ test "recipe key": - register a new cooking recipe with the key "test_recipe_key": + register a new blasting recipe with the key "test_recipe_key": set the recipe input item to raw copper named "test_recipe_key" set the recipe result to copper ingot named "test_recipe_key" set {_last} to last registered recipe diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk index 9d2350c5ba2..9bc816fa430 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeResult.sk @@ -1,9 +1,9 @@ test "recipe result": set {_result} to copper ingot named "test_recipe_result" - register a new cooking recipe with the key "test_recipe_result": + register a new blasting recipe with the key "test_recipe_result": set the recipe input item to raw copper named "test_recipe_result" set the recipe result to {_result} set {_last} to last registered recipe set {_get} to recipe with the key "test_recipe_result" assert the recipe result of {_last} = {_result} with "Result mismatch of last registered recipe" - assert the recipe experience of {_get} = {_result} with "Result mismatch of get recipe" + assert the recipe result of {_get} = {_result} with "Result mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk index 4c6a762c807..f9fa2560378 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk @@ -16,15 +16,6 @@ test "shapeless recipe type": assert the recipe type of {_last} = shapeless recipe with "Shapeless recipe type mismatch of last registered recipe" assert the recipe type of {_get} = shapeless recipe with "Shapeless recipe type mismatch of get recipe" -test "cooking recipe type": - register a new cooking recipe with the key "test_cooking_recipe_type": - set the recipe input item to raw copper named "test_cooking_recipe_type" - set the recipe result to copper ingot named "test_cooking_recipe_type" - set {_last} to last registered recipe - set {_get} to recipe with the key "test_cooking_recipe_type" - assert the recipe type of {_last} = cooking recipe with "Cooking recipe type mismatch of last registered recipe" - assert the recipe type of {_get} = cooking recipe with "Cooking recipe type mismatch of get recipe" - test "blasting recipe type": register a new blasting recipe with the key "test_blasting_recipe_type": set the recipe input item to raw iron named "test_blasting_recipe_type" @@ -61,7 +52,7 @@ test "smoking recipe type": assert the recipe type of {_last} = smoking recipe with "Smoking recipe type mismatch of last registered recipe" assert the recipe type of {_get} = smoking recipe with "Smoking recipe type mismatch of get recipe" -test "smithing recipe type": +test "smithing recipe type" when running below minecraft "1.20": register a new smithing recipe with the key "test_smithing_recipe_type": set the recipe base item to iron ingot named "test_smithing_recipe_type" set the recipe additional item to gold ingot named "test_smithing_recipe_type" @@ -80,7 +71,10 @@ test "smithing transform recipe type": set {_last} to last registered recipe set {_get} to recipe with the key "test_smithing_transform_recipe_type" assert the recipe type of {_last} = smithing transform recipe with "Smithing Transform recipe type mismatch of last registered recipe" - assert the recipe type of {_get} = smithing transform recipe with "Smithing Transform recipe type mismatch of get recipe" + if running below minecraft "1.20": + assert the recipe type of {_get} = smithing recipe with "Smithing Transform recipe type mismatch of get recipe" + else: + assert the recipe type of {_get} = smithing transform recipe with "Smithing Transform recipe type mismatch of get recipe" test "smithing trim recipe type": register a new smithing trim recipe with the key "test_smithing_trim_recipe_type": @@ -91,7 +85,10 @@ test "smithing trim recipe type": set {_last} to last registered recipe set {_get} to recipe with the key "test_smithing_trim_recipe_type" assert the recipe type of {_last} = smithing trim recipe with "Smithing Trim recipe type mismatch of last registered recipe" - assert the recipe type of {_get} = smithing trim recipe with "Smithing Trim recipe type mismatch of get recipe" + if running below minecraft "1.20.0": + assert the recipe type of {_get} = smithing recipe with "Smithing Trim recipe type mismatch of get recipe" + else: + assert the recipe type of {_get} = smithing trim recipe with "Smithing Trim recipe type mismatch of get recipe" test "stonecutting recipe type": register a new stonecutting recipe with the key "test_stonecutting_recipe_type": diff --git a/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk b/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk index f914b552d53..01f8ca0a9ca 100644 --- a/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk +++ b/src/test/skript/tests/syntaxes/sections/SecRegisterRecipe.sk @@ -18,12 +18,6 @@ test "register shapeless recipe fail": assert last parse logs contains "This can only be used when registering a Shaped Recipe." with "Ingredients of a row did not fail for Shapeless recipe" assert the recipe "test_register_shapeless_recipe_fail" does not exist with "Shapeless recipe should not have registered after failing" -test "register cooking recipe": - register a new cooking recipe with the key "test_register_cooking_recipe": - set the recipe input item to raw copper named "test_register_cooking_recipe" - set the recipe result to copper ingot named "test_register_cooking_recipe" - assert the recipe "test_register_cooking_recipe" exists with "Cooking recipe does not exist" - test "register blasting recipe": register a new blasting recipe with the key "test_register_blasting_recipe": set the recipe input item to raw iron named "test_register_blasting_recipe" @@ -48,7 +42,7 @@ test "register smoking recipe": set the recipe result to iron ingot named "test_register_smoking_recipe" assert the recipe "test_register_smoking_recipe" exists with "Smoking recipe does not exist" -test "register smithing recipe": +test "register smithing recipe" when running below minecraft "1.20": register a new smithing recipe with the key "test_register_smithing_recipe": set the recipe base item to iron ingot named "test_register_smithing_recipe" set the recipe additional item to gold ingot named "test_register_smithing_recipe" From 5c3a8c02be61cafb58a7f03cc5d077f00421ab4f Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Tue, 15 Oct 2024 03:16:31 -0400 Subject: [PATCH 12/20] Fuzes Wishlist --- .../classes/data/BukkitEventValues.java | 45 +++++++-------- .../classes/data/DefaultComparators.java | 27 +++------ .../njol/skript/effects/EffRemoveRecipe.java | 2 +- .../njol/skript/effects/EffResetRecipes.java | 2 +- .../njol/skript/events/EvtDiscoverRecipe.java | 57 +++++++++++++++++++ .../expressions/ExprRecipeCookingTime.java | 2 +- .../expressions/ExprRecipeIngredients.java | 2 +- .../skript/expressions/ExprRecipeResult.java | 2 - .../skript/expressions/ExprRecipeType.java | 4 +- .../skript/sections/SecRegisterRecipe.java | 17 ++---- .../ch/njol/skript/util/NamespacedUtils.java | 2 +- .../java/ch/njol/skript/util/RecipeUtils.java | 39 +++++-------- src/main/resources/lang/default.lang | 1 + .../tests/syntaxes/effects/EffRemoveRecipe.sk | 9 +++ .../tests/syntaxes/effects/EffResetRecipes.sk | 13 +++++ .../syntaxes/expressions/ExprGetRecipe.sk | 2 - .../syntaxes/expressions/ExprRecipeType.sk | 23 ++++++++ 17 files changed, 158 insertions(+), 91 deletions(-) create mode 100644 src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java create mode 100644 src/test/skript/tests/syntaxes/effects/EffRemoveRecipe.sk create mode 100644 src/test/skript/tests/syntaxes/effects/EffResetRecipes.sk diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java index c53810d5d69..0b765b76299 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -133,32 +133,9 @@ import org.bukkit.event.inventory.InventoryPickupItemEvent; import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.event.inventory.PrepareItemCraftEvent; -import org.bukkit.event.player.PlayerBedEnterEvent; -import org.bukkit.event.player.PlayerBedLeaveEvent; -import org.bukkit.event.player.PlayerBucketEmptyEvent; -import org.bukkit.event.player.PlayerBucketFillEvent; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerEditBookEvent; -import org.bukkit.event.player.PlayerEggThrowEvent; -import org.bukkit.event.player.PlayerEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerItemBreakEvent; -import org.bukkit.event.player.PlayerItemConsumeEvent; -import org.bukkit.event.player.PlayerItemDamageEvent; -import org.bukkit.event.player.PlayerItemHeldEvent; -import org.bukkit.event.player.PlayerItemMendEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerPickupArrowEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; -import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.*; import org.bukkit.event.player.PlayerQuitEvent.QuitReason; -import org.bukkit.event.player.PlayerRiptideEvent; -import org.bukkit.event.player.PlayerShearEntityEvent; -import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.event.player.PlayerToggleFlightEvent; import org.bukkit.event.server.ServerCommandEvent; import org.bukkit.event.vehicle.VehicleDamageEvent; import org.bukkit.event.vehicle.VehicleDestroyEvent; @@ -1392,6 +1369,12 @@ public Player get(final PrepareItemCraftEvent e) { return null; } }, 0); + EventValues.registerEventValue(PrepareItemCraftEvent.class, Recipe.class, new Getter() { + @Override + public @Nullable Recipe get(PrepareItemCraftEvent event) { + return event.getRecipe(); + } + }, EventValues.TIME_NOW); // CraftEvents - recipe namespaced key strings EventValues.registerEventValue(CraftItemEvent.class, String.class, new Getter() { @Nullable @@ -1421,6 +1404,12 @@ public ItemStack get(CraftItemEvent e) { return e.getRecipe().getResult(); } }, 0); + EventValues.registerEventValue(CraftItemEvent.class, Recipe.class, new Getter() { + @Override + public @Nullable Recipe get(CraftItemEvent event) { + return event.getRecipe(); + } + }, EventValues.TIME_NOW); //InventoryOpenEvent EventValues.registerEventValue(InventoryOpenEvent.class, Player.class, new Getter() { @Override @@ -1964,5 +1953,13 @@ public RegainReason get(EntityRegainHealthEvent event) { return event.getRegainReason(); } }, EventValues.TIME_NOW); + + // PlayerRecipeBookClickEvent + EventValues.registerEventValue(PlayerRecipeDiscoverEvent.class, Recipe.class, new Getter() { + @Override + public @Nullable Recipe get(PlayerRecipeDiscoverEvent event) { + return Bukkit.getRecipe(event.getRecipe()); + } + }, EventValues.TIME_NOW); } } diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java index 09cc6166bd3..e25841cb0f8 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -29,15 +29,14 @@ import ch.njol.skript.entity.EntityData; import ch.njol.skript.entity.RabbitData; import ch.njol.skript.util.*; +import ch.njol.skript.util.StructureType; +import ch.njol.skript.util.WeatherType; import ch.njol.skript.util.slot.EquipmentSlot; import ch.njol.skript.util.slot.Slot; import ch.njol.skript.util.slot.SlotWithIndex; import ch.njol.util.StringUtils; import ch.njol.util.coll.CollectionUtils; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.OfflinePlayer; -import org.bukkit.World; +import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.command.CommandSender; @@ -52,6 +51,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.ShapedRecipe; import org.bukkit.potion.PotionEffectType; import org.skriptlang.skript.lang.comparator.Comparator; import org.skriptlang.skript.lang.comparator.Comparators; @@ -649,20 +649,11 @@ public boolean supportsOrdering() { // Potion Effect Type Comparators.registerComparator(PotionEffectType.class, PotionEffectType.class, (one, two) -> Relation.get(one.equals(two))); - Comparators.registerComparator(Recipe.class, Recipe.class, new Comparator() { - @Override - public Relation compare(Recipe o1, Recipe o2) { - Recipe first = null; - Recipe second = null; - if (o1.getClass().getSuperclass().equals(o2.getClass())) { - first = (Recipe) o1; - second = o2; - } else if (o2.getClass().getSuperclass().equals(o1.getClass())) { - first = o1.getClass().cast(o2); - second = o1; - } - Skript.adminBroadcast("Compare 1: " + first); - Skript.adminBroadcast("Compare 2: " + second); + Comparators.registerComparator(RecipeUtils.RecipeType.class, RecipeUtils.RecipeType.class, new Comparator() { + @Override + public Relation compare(RecipeUtils.RecipeType type1, RecipeUtils.RecipeType type2) { + if (type1.getRecipeClass() != null && type2.getRecipeClass() != null) + return Relation.get(type2.getRecipeClass().isAssignableFrom(type1.getRecipeClass())); return Relation.NOT_EQUAL; } }); diff --git a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java index bfb16a55a1d..e7001107840 100644 --- a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java +++ b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java @@ -26,7 +26,7 @@ public class EffRemoveRecipe extends Effect { static { Skript.registerEffect(EffRemoveRecipe.class, - "(remove|delete|clear) [the] recipe[s] %strings% [from the server]"); + "(remove|delete|clear) [the] recipe[s] [with [the] key] %strings% [from the server]"); } private Expression recipes; diff --git a/src/main/java/ch/njol/skript/effects/EffResetRecipes.java b/src/main/java/ch/njol/skript/effects/EffResetRecipes.java index 1a91b5fad49..5f4567be020 100644 --- a/src/main/java/ch/njol/skript/effects/EffResetRecipes.java +++ b/src/main/java/ch/njol/skript/effects/EffResetRecipes.java @@ -21,7 +21,7 @@ public class EffResetRecipes extends Effect { static { Skript.registerEffect(EffResetRecipes.class, - "reset server recipes"); + "reset [the] server['s] recipes"); } @Override diff --git a/src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java b/src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java new file mode 100644 index 00000000000..4a36c43e37e --- /dev/null +++ b/src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java @@ -0,0 +1,57 @@ +package ch.njol.skript.events; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.util.NamespacedUtils; +import org.bukkit.event.Event; +import org.bukkit.event.player.PlayerRecipeDiscoverEvent; +import org.jetbrains.annotations.Nullable; + +@Name("Player Discover Recipe") +@Description("Called when a player discovers a recipe") +@Examples({ + "on player discovered recipe:", + "\tbroadcast event-recipe", + "", + "on discovered recipe of \"my_recipe\":", + "broadcast event-recipe" +}) +@Since("INSERT VERSION") +public class EvtDiscoverRecipe extends SkriptEvent { + + static { + Skript.registerEvent("Player Discover Recipe", EvtDiscoverRecipe.class, PlayerRecipeDiscoverEvent.class, + "[player] discover[ed] recipe [of %strings%]"); + } + + private Expression recipes; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Literal[] exprs, int matchedPattern, ParseResult parseResult) { + recipes = (Expression) exprs[0]; + return true; + } + + @Override + public boolean check(Event event) { + if (!(event instanceof PlayerRecipeDiscoverEvent discoverEvent)) + return false; + if (recipes == null) + return true; + + return recipes.check(event, recipe -> discoverEvent.getRecipe().equals(NamespacedUtils.getNamespacedKey(recipe))); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "player discovered" + (recipes == null ? "" : " of " + recipes.toString(event, debug)); + } +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java index 733b617ca43..a0499ce1517 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java @@ -24,7 +24,7 @@ @Name("Recipe Cooking Time") @Description("The cooking time of a Cooking, Blasting, Furnace, Campfire and Smoking Recipe.") @Examples({ - "register a new cooking recipe with the key \"my_recipe\":", + "register a new blasting recipe with the key \"my_recipe\":", "\tset the recipe input item to raw gold named \"Impure Gold\"", "\tset the recipe cooking time to 10 seconds", "\tset the recipe result to gold ingot named \"Pure Gold\"" diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java index 69eca465673..fa04bbb12fe 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java @@ -45,7 +45,7 @@ "\tset recipe ingredients to iron ingot, gold ingot, iron ingot, nether star, 5 obsidian, nether star, iron ingot, gold ingot and iron ingot", "\tset recipe resulting item to beacon named \"OP Beacon\"", "", - "register new cooking recipe with the id \"my_recipe\":", + "register new blasting recipe with the id \"my_recipe\":", "\tset the recipe input item to netherite ingot named \"Impure Netherite\"", "\tset the recipe result item to netherite ingot named \"Pure Netherite\"", "", diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java index 1187f2a0059..4187bed39e5 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java @@ -19,9 +19,7 @@ import org.bukkit.inventory.Recipe; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; @Name("Recipe Result") @Description("The result item for a recipe") diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java index 36c1531bd6a..226158a85f4 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java @@ -15,9 +15,7 @@ import org.bukkit.inventory.Recipe; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; @Name("Recipe Type") @Description("Get the recipe type of a recipe") @@ -43,7 +41,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected RecipeUtils.RecipeType @Nullable [] get(Event event, Recipe[] source) { - return Arrays.stream(getExpr().getArray(event)).map(RecipeUtils::getRecipeTypeFromRecipe).toArray(RecipeUtils.RecipeType[]::new); + return get(source, recipe -> RecipeUtils.getRecipeTypeFromRecipe(recipe)); } @Override diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 9ea3911ac85..ec70c839713 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -9,12 +9,7 @@ import ch.njol.skript.doc.Since; import ch.njol.skript.lang.*; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.registrations.EventValues; -import ch.njol.skript.util.Getter; -import ch.njol.skript.util.LiteralUtils; import ch.njol.skript.util.NamespacedUtils; -import ch.njol.skript.util.RecipeUtils; -import ch.njol.skript.util.RecipeUtils.*; import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; import ch.njol.skript.util.RecipeUtils.RecipeType; import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.*; @@ -22,7 +17,6 @@ import ch.njol.skript.variables.Variables; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.event.Event; import org.bukkit.inventory.*; @@ -44,7 +38,7 @@ "Blasting, Furnace, Campfire and Smoking all fall under Cooking Recipe Type", "Groups only apply to Shaped, Shapeless and Cooking Recipes", "Category only applies to Shaped, Shapeless and Cooking Recipes", - "You can not create a Cooking Recipe type." + "You can not create a Cooking and Crafting Recipe type." }) @Examples({ "register a new shaped recipe with the name \"my_recipe\":", @@ -86,13 +80,10 @@ public class SecRegisterRecipe extends Section { /* TODO: - Fix comparing recipe to recipe - add comparing recipe type to recipe type (sub -> super) Comparing key of recipe to a string - Cond tests - Eff tests Recipe event values Maybe Complex Recipe? + ExprRecipeIngredients Test */ private static final boolean RUNNING_1_20 = Skript.isRunningMinecraft(1, 20, 0); @@ -112,8 +103,8 @@ add comparing recipe type to recipe type (sub -> super) @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult, SectionNode sectionNode, List triggerItems) { providedType = ((Literal) exprs[0]).getSingle(); - if (providedType == RecipeType.COOKING) { - Skript.error("You can not register a 'cooking' recipe type."); + if (providedType == RecipeType.COOKING || providedType == RecipeType.CRAFTING) { + Skript.error("You can not register a '" + providedType + "' recipe type."); return false; } else if (providedType == RecipeType.SMITHING && RUNNING_1_20) { Skript.error("You can not register a 'smithing' recipe type on MC version 1.20+"); diff --git a/src/main/java/ch/njol/skript/util/NamespacedUtils.java b/src/main/java/ch/njol/skript/util/NamespacedUtils.java index c303828c497..a0855bdc545 100644 --- a/src/main/java/ch/njol/skript/util/NamespacedUtils.java +++ b/src/main/java/ch/njol/skript/util/NamespacedUtils.java @@ -71,7 +71,7 @@ public static NamespacedKey createNamespacedKey(String key) { encodedKeyBuilder.append('.'); } } - return new NamespacedKey(Skript.getInstance(), encodedKeyBuilder.toString()); + return NamespacedKey.fromString(encodedKeyBuilder.toString(), Skript.getInstance()); } /** diff --git a/src/main/java/ch/njol/skript/util/RecipeUtils.java b/src/main/java/ch/njol/skript/util/RecipeUtils.java index 43baf2f3785..d46f5c6b63b 100644 --- a/src/main/java/ch/njol/skript/util/RecipeUtils.java +++ b/src/main/java/ch/njol/skript/util/RecipeUtils.java @@ -7,13 +7,22 @@ import org.bukkit.inventory.recipe.CookingBookCategory; import org.bukkit.inventory.recipe.CraftingBookCategory; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class RecipeUtils { - // Custom enum for registering a 'recipetype' class + private static Class CRAFTING_CLASS = null; + + // Due to 1.19 not having 'CraftingRecipe.class' + static { + if (Skript.classExists("org.bukkit.inventory.CraftingRecipe")) { + CRAFTING_CLASS = CraftingRecipe.class; + } + } public enum RecipeType { SHAPED(ShapedRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class), SHAPELESS(ShapelessRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapelessRecipeEvent.class), + CRAFTING(CRAFTING_CLASS, RegisterRecipeEvent.CraftingRecipeEvent.class), BLASTING(BlastingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.BlastingRecipeEvent.class), FURNACE(FurnaceRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.FurnaceRecipeEvent.class), CAMPFIRE(CampfireRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.CampfireRecipeEvent.class), @@ -24,10 +33,10 @@ public enum RecipeType { SMITHING(SmithingRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.class), // Having 'SMITHING' under the subclasses allows for proper ExprRecipeType STONECUTTING(StonecuttingRecipe.class, RegisterRecipeEvent.StonecuttingRecipeEvent.class); - private final Class recipeClass; + private final @Nullable Class recipeClass; private final Class eventClass; - RecipeType(Class recipeClass, Class eventClass) { + RecipeType(@Nullable Class recipeClass, Class eventClass) { this.recipeClass = recipeClass; this.eventClass = eventClass; } @@ -41,11 +50,9 @@ public Class getEventClass() { } } - private static final RecipeType[] recipeTypes = RecipeType.values(); - public static RecipeType getRecipeTypeFromRecipeClass(Class providedClass) { - for (RecipeType type : recipeTypes) { - if (type.recipeClass.isAssignableFrom(providedClass)) { + for (RecipeType type : RecipeType.values()) { + if (type.recipeClass != null && type.recipeClass.isAssignableFrom(providedClass)) { return type; } } @@ -278,23 +285,7 @@ public RecipeChoice getInput() { } public Class getRecipeEventFromRecipeType(RecipeType recipeType) { - return switch (recipeType) { - case SHAPED -> RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class; - case SHAPELESS -> RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class; - case COOKING -> RegisterRecipeEvent.CookingRecipeEvent.class; - case BLASTING -> RegisterRecipeEvent.CookingRecipeEvent.BlastingRecipeEvent.class; - case CAMPFIRE -> RegisterRecipeEvent.CookingRecipeEvent.CampfireRecipeEvent.class; - case FURNACE -> RegisterRecipeEvent.CookingRecipeEvent.FurnaceRecipeEvent.class; - case SMOKING -> RegisterRecipeEvent.CookingRecipeEvent.SmokingRecipeEvent.class; - case SMITHING -> RegisterRecipeEvent.SmithingRecipeEvent.class; - case SMITHING_TRANSFORM -> RegisterRecipeEvent.SmithingRecipeEvent.SmithingTransformRecipeEvent.class; - case SMITHING_TRIM -> RegisterRecipeEvent.SmithingRecipeEvent.SmithingTrimRecipeEvent.class; - case STONECUTTING -> RegisterRecipeEvent.StonecuttingRecipeEvent.class; - }; - } - - public Class getRecipeEventFromRecipeClass(Class recipeClass) { - return getRecipeEventFromRecipeType(getRecipeTypeFromRecipeClass(recipeClass)); + return recipeType.getEventClass(); } } \ No newline at end of file diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index b2175c9d102..5716fbf1d69 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2318,6 +2318,7 @@ cooking book categories: # -- Recipe Types -- recipe types: + crafting: crafting recipe shaped: shaped recipe, shaped crafting recipe, shaped recipes, shaped crafting recipes shapeless: shapeless recipe, shapeless crafting recipe, shapeless recipes, shapeless crafting recipes cooking: cooking recipe, cooking recipes diff --git a/src/test/skript/tests/syntaxes/effects/EffRemoveRecipe.sk b/src/test/skript/tests/syntaxes/effects/EffRemoveRecipe.sk new file mode 100644 index 00000000000..93e444dcd57 --- /dev/null +++ b/src/test/skript/tests/syntaxes/effects/EffRemoveRecipe.sk @@ -0,0 +1,9 @@ +test "remove recipe": + register a new blasting recipe with the key "test_remove_recipe": + set the recipe input item to diamond named "test_remove_recipe" + set the recipe result item to nether star named "test_remove_recipe" + set {_get} to recipe with the key "test_remove_recipe" + assert {_get} is set with "Retrieve recipe for removal was not set" + remove recipe with the key "test_remove_recipe" from the server + set {_get} to recipe with the key "test_remove_recipe" + assert {_get} is not set with "Recipe was not removed from the server" diff --git a/src/test/skript/tests/syntaxes/effects/EffResetRecipes.sk b/src/test/skript/tests/syntaxes/effects/EffResetRecipes.sk new file mode 100644 index 00000000000..c56ffac14b3 --- /dev/null +++ b/src/test/skript/tests/syntaxes/effects/EffResetRecipes.sk @@ -0,0 +1,13 @@ +test "reset recipes": + register a new blasting recipe with the key "test_reset_recipes": + set the recipe input item to gold ingot named "test_reset_recipes" + set the recipe result to raw gold named "test_reset_recipes" + set {_all} to size of all recipes + set {_all_blasting} to size of all blasting recipes + set {_custom} to size of all custom recipes + set {_custom_blasting} to size of all custom blasting recipes + reset the server's recipes + assert (size of all recipes) < {_all} with "Size of all recipes did not reduce after resetting" + assert (size of all blasting recipes) < {_all_blasting} with "Size of all blasting recipes did not reduce after resetting" + assert (size of all custom recipes) < {_custom} with "Size of all custom recipes did not reduce after resetting" + assert (size of all custom blasting recipes) < {_custom_blasting} with "Size of all custom blasting recipes did not reduce after resetting" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk b/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk index efcceb8b757..6a1722058b6 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprGetRecipe.sk @@ -2,7 +2,5 @@ test "get recipe": register a new shaped recipe with the key "test_get_recipe": set the recipe ingredients to diamond, air, diamond, air, emerald, air, diamond, air and diamond set the recipe result to netherite sword named "test_get_recipe" - set {_last} to last registered recipe set {_get} to recipe with the key "test_get_recipe" assert {_get} is set with "Could not retrieve recipe" - assert {_get} = {_last} with "Retrieved recipe does not match from last registered" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk index f9fa2560378..4f83caf0cd7 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeType.sk @@ -98,3 +98,26 @@ test "stonecutting recipe type": set {_get} to recipe with the key "test_stonecutting_recipe_type" assert the recipe type of {_last} = stonecutting recipe with "Stonecutting recipe type mismatch of last registered recipe" assert the recipe type of {_get} = stonecutting recipe with "Stonecutting recipe type mismatch of get recipe" + +test "recipe types compared to super types": + if running minecraft "1.20": + assert shaped recipe = crafting recipe with "Shaped recipe should pass as crafting recipe" + assert shapeless recipe = crafting recipe with "Shapeless recipe should pass as crafting recipe" + + assert blasting recipe = cooking recipe with "Blasting recipe should pass as cooking recipe" + assert furnace recipe = cooking recipe with "Furnace recipe should pass as cooking recipe" + assert smoking recipe = cooking recipe with "Smoking recipe should pass as cooking recipe" + assert campfire recipe = cooking recipe with "Campfire recipe should pass as cooking recipe" + + assert smithing transform recipe = smithing recipe with "Smithing Transform recipe should pass as smithing recipe" + assert smithing trim recipe = smithing recipe with "Smithing Trim recipe should pass as smithing recipe" + +test "recipe types compared to neighbor sub types": #FAILS + assert shaped recipe != shapeless recipe with "Shaped recipe should not equal shapeless recipe" + + set {_types::*} to blasting recipe, furnace recipe, smoking recipe and campfire recipe + loop {_types::*}: + loop ({_types::*} where [input != loop-value]): + assert loop-value-1 != loop-value-2 with "%loop-value-1% should not equal %loop-value-2%" + + assert smithing transform recipe != smithing trim recipe with "Smithing Transform recipe should not equal smithing trim recipe" From 78c5411c7e0f7b5073e4c3c1e3a79029b1306884 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Tue, 15 Oct 2024 20:47:55 -0400 Subject: [PATCH 13/20] Almost Done --- .../conditions/CondDiscoveredRecipes.java | 2 +- .../skript/conditions/CondRecipeExists.java | 2 +- .../skript/effects/EffDiscoverRecipe.java | 2 +- .../njol/skript/effects/EffRemoveRecipe.java | 2 +- .../njol/skript/events/EvtDiscoverRecipe.java | 2 +- .../skript/expressions/ExprGetRecipe.java | 2 +- .../expressions/ExprRecipeIngredients.java | 2 +- ...yFrom.java => ExprRecipeKeyConverter.java} | 28 +++++--- .../skript/sections/SecRegisterRecipe.java | 17 ++--- .../ch/njol/skript/util/NamespacedUtils.java | 19 ++++-- .../java/ch/njol/skript/util/RecipeUtils.java | 23 ++++--- src/main/resources/lang/default.lang | 1 + .../expressions/ExprRecipeIngredients.sk | 65 +++++++++++++++++++ .../syntaxes/expressions/ExprRecipeKey.sk | 4 +- .../expressions/ExprRecipeKeyConverter.sk | 10 +++ 15 files changed, 133 insertions(+), 48 deletions(-) rename src/main/java/ch/njol/skript/expressions/{ExprRecipeKeyFrom.java => ExprRecipeKeyConverter.java} (53%) create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprRecipeIngredients.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprRecipeKeyConverter.sk diff --git a/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java b/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java index c671d4addd8..f6fe06caa37 100644 --- a/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java +++ b/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java @@ -51,7 +51,7 @@ public boolean check(Event event) { return players.check(event, player -> recipes.check(event, recipe -> { - NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe); + NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe, false); if (Bukkit.getRecipe(key) != null) return player.hasDiscoveredRecipe(key); return false; diff --git a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java index 39e6863c09d..1ac5de68ea3 100644 --- a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java +++ b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java @@ -42,7 +42,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override public boolean check(Event event) { - return recipes.check(event, recipe -> Bukkit.getRecipe(NamespacedUtils.getNamespacedKey(recipe)) != null, isNegated()); + return recipes.check(event, recipe -> Bukkit.getRecipe(NamespacedUtils.getNamespacedKey(recipe, false)) != null, isNegated()); } @Override diff --git a/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java b/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java index 78946388bc1..5ea0c5d0f4d 100644 --- a/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java +++ b/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java @@ -52,7 +52,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye protected void execute(Event event) { for (Player player : players.getArray(event)) { for (String recipe : recipes.getArray(event)) { - NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe); + NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe, false); if (Bukkit.getRecipe(key) != null) { if (isDiscover) player.discoverRecipe(key); diff --git a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java index e7001107840..c02436908bd 100644 --- a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java +++ b/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java @@ -41,7 +41,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected void execute(Event event) { for (String recipe : recipes.getArray(event)) { - NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe); + NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe, false); if (Bukkit.getRecipe(key) != null) Bukkit.removeRecipe(key); } diff --git a/src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java b/src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java index 4a36c43e37e..f0fe70b3b1d 100644 --- a/src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java +++ b/src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java @@ -47,7 +47,7 @@ public boolean check(Event event) { if (recipes == null) return true; - return recipes.check(event, recipe -> discoverEvent.getRecipe().equals(NamespacedUtils.getNamespacedKey(recipe))); + return recipes.check(event, recipe -> discoverEvent.getRecipe().equals(NamespacedUtils.getNamespacedKey(recipe, false))); } @Override diff --git a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java index 701f756d51c..0e920cbebe8 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java +++ b/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java @@ -47,7 +47,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye protected Recipe @Nullable [] get(Event event) { List recipeList = new ArrayList<>(); for (String name : recipeNames.getArray(event)) { - NamespacedKey key = NamespacedUtils.getNamespacedKey(name); + NamespacedKey key = NamespacedUtils.getNamespacedKey(name, false); Recipe check = Bukkit.getRecipe(key); if (check != null) recipeList.add(check); diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java index fa04bbb12fe..e628d983c2e 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java @@ -204,7 +204,7 @@ else if (recipe instanceof SmithingTrimRecipe trimRecipe) ); } } else { - customError("You can only get the base, template, and addition items of a Smithing, Ssmithing Transform and Smithing Trim Recipe."); + customError("You can only get the base, template, and addition items of a Smithing, Smithing Transform and Smithing Trim Recipe."); } } case INPUT -> { diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeKeyFrom.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeKeyConverter.java similarity index 53% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeKeyFrom.java rename to src/main/java/ch/njol/skript/expressions/ExprRecipeKeyConverter.java index 792f1224ad5..0c9b8791b17 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeKeyFrom.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeKeyConverter.java @@ -4,6 +4,7 @@ import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Examples; import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; @@ -15,35 +16,44 @@ import java.util.Arrays; -@Name("Recipe Key From String") +@Name("Recipe Key Converter") @Description({ - "Gets the end product key from a string", - "To produce a valid key, the provided string has to be altered to meet the requirements." + "Converts a string to a valid key to be used with recipes.", + "'using minecraft namespace' will convert the string to a minecraft namespace key" }) @Examples({ - "send the recipe key from \"my_recipe\"", + "send the converted recipe key from \"my_recipe\"", "loop all custom recipes:", - "\tif recipe key of loop-recipe = recipe key from \"my_recipe\":", - "\t\tbroadcast loop-recipe" + "\tif recipe key of loop-recipe = converted key from \"my_recipe\" using minecraft namespace:", + "\t\tbroadcast loop-recipe", + "", + "register a new shaped recipe with the key (converted key from \"my_recipe\"):", + "set the recipe ingredients to diamond, iron ingot and raw copper", + "set the recipe result to diamond helmet" }) -public class ExprRecipeKeyFrom extends SimpleExpression { +@Since("INSERT VERSION") +public class ExprRecipeKeyConverter extends SimpleExpression { static { - Skript.registerExpression(ExprRecipeKeyFrom.class, String.class, ExpressionType.SIMPLE, "[the] recipe key[s] from %strings%"); + Skript.registerExpression(ExprRecipeKeyConverter.class, String.class, ExpressionType.SIMPLE, + "[the] converted [recipe] key[s] (from|of|for) %strings%", + "[the] converted [recipe] key[s] (from|of|for) %strings% (using|with) (mc|minecraft) namespace"); } private Expression names; + private boolean usingMinecraft; @Override @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { names = (Expression) exprs[0]; + usingMinecraft = matchedPattern == 1; return true; } @Override protected String @Nullable [] get(Event event) { - return Arrays.stream(names.getArray(event)).map(name -> NamespacedUtils.getNamespacedKey(name).toString()).toArray(String[]::new); + return Arrays.stream(names.getArray(event)).map(name -> NamespacedUtils.getNamespacedKey(name, usingMinecraft).toString()).toArray(String[]::new); } @Override diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index ec70c839713..2c749ea88a6 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -38,7 +38,7 @@ "Blasting, Furnace, Campfire and Smoking all fall under Cooking Recipe Type", "Groups only apply to Shaped, Shapeless and Cooking Recipes", "Category only applies to Shaped, Shapeless and Cooking Recipes", - "You can not create a Cooking and Crafting Recipe type." + "You can not create a Cooking, Crafting and Complex Recipe type." }) @Examples({ "register a new shaped recipe with the name \"my_recipe\":", @@ -56,7 +56,7 @@ "\tset the recipe crafting category to crafting category misc", "\tset the recipe result item to diamond helmet named \"Heavenly Helm\"", "", - "#Furnace, Campfire and Smoking follow same format as Cooking", + "#Furnace, Campfire and Smoking follow same format as Blasting example", "create new blasting recipe with the namespacekey \"my_recipe\":", "\tset the recipe experience to 5", "\tset the recipe cooking time to 10 seconds", @@ -78,14 +78,7 @@ }) @Since("INSERT VERSION") public class SecRegisterRecipe extends Section { - /* - TODO: - Comparing key of recipe to a string - Recipe event values - Maybe Complex Recipe? - ExprRecipeIngredients Test - */ - + private static final boolean RUNNING_1_20 = Skript.isRunningMinecraft(1, 20, 0); static { @@ -103,7 +96,7 @@ public class SecRegisterRecipe extends Section { @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult, SectionNode sectionNode, List triggerItems) { providedType = ((Literal) exprs[0]).getSingle(); - if (providedType == RecipeType.COOKING || providedType == RecipeType.CRAFTING) { + if (providedType == RecipeType.COOKING || providedType == RecipeType.CRAFTING || providedType == RecipeType.COMPLEX) { Skript.error("You can not register a '" + providedType + "' recipe type."); return false; } else if (providedType == RecipeType.SMITHING && RUNNING_1_20) { @@ -126,7 +119,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected @Nullable TriggerItem walk(Event event) { String name = providedName.getSingle(event); - NamespacedKey key = NamespacedUtils.getNamespacedKey(name); + NamespacedKey key = NamespacedUtils.getNamespacedKey(name, false); RecipeType recipeType = providedType; RegisterRecipeEvent recipeEvent = switch (recipeType) { case SHAPED -> new ShapedRecipeEvent(recipeType); diff --git a/src/main/java/ch/njol/skript/util/NamespacedUtils.java b/src/main/java/ch/njol/skript/util/NamespacedUtils.java index a0855bdc545..29fbe6bfb5b 100644 --- a/src/main/java/ch/njol/skript/util/NamespacedUtils.java +++ b/src/main/java/ch/njol/skript/util/NamespacedUtils.java @@ -18,13 +18,18 @@ public class NamespacedUtils { * @param key the unparsed key * @return the resulting NamespacedKey */ - public static NamespacedKey getNamespacedKey(String key) { - NamespacedKey namespacedKey = NamespacedKey.fromString(key, Skript.getInstance()); + public static NamespacedKey getNamespacedKey(String key, Boolean usingMinecraft) { + NamespacedKey namespacedKey; + if (usingMinecraft) + namespacedKey = NamespacedKey.fromString(key); + else + namespacedKey = NamespacedKey.fromString(key, Skript.getInstance()); if (namespacedKey != null) return namespacedKey; - NamespacedKey convertedKey = createNamespacedKey(key); - Skript.info("The key provided '" + key + "' has been converted to '" + convertedKey + "' due to invalid characters." + - "\n\tValid characters are a-z, 0-9, -, _ and ."); + NamespacedKey convertedKey = createNamespacedKey(key, usingMinecraft); + if (!Skript.testing()) + Skript.info("The key provided '" + key + "' has been converted to '" + convertedKey.toString() + "' due to invalid characters." + + "\n\tValid characters are a-z, 0-9, -, _ and ."); return convertedKey; } @@ -35,7 +40,7 @@ public static NamespacedKey getNamespacedKey(String key) { * @param key The key to use * @return a NamespacedKey with the encoded key in Skript's namespace */ - public static NamespacedKey createNamespacedKey(String key) { + public static NamespacedKey createNamespacedKey(String key, Boolean usingMinecraft) { // TODO: add tests for this StringBuilder encodedKeyBuilder = new StringBuilder(); // keys must be all lowercase @@ -71,6 +76,8 @@ public static NamespacedKey createNamespacedKey(String key) { encodedKeyBuilder.append('.'); } } + if (usingMinecraft) + return NamespacedKey.fromString(encodedKeyBuilder.toString()); return NamespacedKey.fromString(encodedKeyBuilder.toString(), Skript.getInstance()); } diff --git a/src/main/java/ch/njol/skript/util/RecipeUtils.java b/src/main/java/ch/njol/skript/util/RecipeUtils.java index d46f5c6b63b..8cecb3ead8f 100644 --- a/src/main/java/ch/njol/skript/util/RecipeUtils.java +++ b/src/main/java/ch/njol/skript/util/RecipeUtils.java @@ -31,21 +31,22 @@ public enum RecipeType { SMITHING_TRANSFORM(SmithingTransformRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.SmithingTransformRecipeEvent.class), SMITHING_TRIM(SmithingTrimRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.SmithingTrimRecipeEvent.class), SMITHING(SmithingRecipe.class, RegisterRecipeEvent.SmithingRecipeEvent.class), // Having 'SMITHING' under the subclasses allows for proper ExprRecipeType - STONECUTTING(StonecuttingRecipe.class, RegisterRecipeEvent.StonecuttingRecipeEvent.class); + STONECUTTING(StonecuttingRecipe.class, RegisterRecipeEvent.StonecuttingRecipeEvent.class), + COMPLEX(ComplexRecipe.class, null); private final @Nullable Class recipeClass; - private final Class eventClass; + private final @Nullable Class eventClass; - RecipeType(@Nullable Class recipeClass, Class eventClass) { + RecipeType(@Nullable Class recipeClass, @Nullable Class eventClass) { this.recipeClass = recipeClass; this.eventClass = eventClass; } - public Class getRecipeClass() { + public @Nullable Class getRecipeClass() { return recipeClass; } - public Class getEventClass() { + public @Nullable Class getEventClass() { return eventClass; } } @@ -218,7 +219,9 @@ public SmokingRecipeEvent(RecipeType recipeType) { public static class SmithingRecipeEvent extends RegisterRecipeEvent { - private RecipeChoice base, addition, template; + private RecipeChoice base; + private RecipeChoice template; + private RecipeChoice addition; public SmithingRecipeEvent(RecipeType recipeType) { super(recipeType); @@ -241,11 +244,11 @@ public RecipeChoice getBase() { } public RecipeChoice getAddition() { - return base; + return addition; } public RecipeChoice getTemplate() { - return base; + return template; } public static class SmithingTransformRecipeEvent extends SmithingRecipeEvent { @@ -284,8 +287,4 @@ public RecipeChoice getInput() { } } - public Class getRecipeEventFromRecipeType(RecipeType recipeType) { - return recipeType.getEventClass(); - } - } \ No newline at end of file diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index 5716fbf1d69..0d9f62daef9 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2330,6 +2330,7 @@ recipe types: smithing_transform: smithing transform recipe, smithing transform recipes smithing_trim: smithing trim recipe, smithing trim recipes stonecutting: stonecutting recipe, stonecutting recipes + complex: complex recipe, complex recipes # -- Boolean -- boolean: diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeIngredients.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeIngredients.sk new file mode 100644 index 00000000000..d000f6700d7 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeIngredients.sk @@ -0,0 +1,65 @@ +test "recipe ingredients": + set {_ingredients::*} to raw iron, raw gold, raw copper, iron ingot, gold ingot, copper ingot, diamond, emerald and netherite ingot + register a new shaped recipe with the key "test_recipe_ingredients": + set the recipe ingredients to {_ingredients::*} + set the recipe result to nether star named "test_recipe_ingredients" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_ingredients" + assert the recipe ingredients of {_last} contains {_ingredients::*} with "Mismatch of recipe ingredients from last registered recipe" + assert the recipe ingredients of {_get} contains {_ingredients::*} with "Mismatch of recipe ingredients from get recipe" + +test "recipe ingredients of rows": + set {_first::*} to diamond, emerald and netherite ingot + set {_second::*} to copper ingot, gold ingot and iron ingot + set {_third::*} to raw copper, raw gold and raw iron + register a new shaped recipe with the key "test_recipe_ingredients_rows": + set the recipe ingredients of first row to {_first::*} + set the recipe ingredients of second row to {_second::*} + set the recipe ingredients of third row to {_third::*} + set the recipe result to nether star named "test_recipe_ingredients_rows" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_ingredients_rows" + assert the recipe ingredients of first row of {_last} contains {_first::*} with "Mismatch of recipe ingredients first row from last registered recipe" + assert the recipe ingredients of first row of {_get} contains {_first::*} with "Mismatch of recipe ingredients first row from get recipe" + assert the recipe ingredients of second row of {_last} contains {_second::*} with "Mismatch of recipe ingredients second row from last registered recipe" + assert the recipe ingredients of second row of {_get} contains {_second::*} with "Mismatch of recipe ingredients second row from get recipe" + assert the recipe ingredients of third row of {_last} contains {_third::*} with "Mismatch of recipe ingredients third row from last registered recipe" + assert the recipe ingredients of third row of {_get} contains {_third::*} with "Mismatch of recipe ingredients third row from get recipe" + +test "recipe cooking input": + set {_input} to grass block named "test_recipe_cooking_input" + register a new blasting recipe with the key "test_recipe_cooking_input": + set the recipe input item to {_input} + set the recipe result to nether star named "test_recipe_cooking_input" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_cooking_input" + assert the recipe input item of {_last} = {_input} with "Mismatch of recipe input item from last registered recipe" + assert the recipe input item of {_get} = {_input} with "Mismatch of recipe input item from get recipe" + +test "recipe stonecutting input": + set {_input} to stone named "test_recipe_stonecutting_input" + register a new stonecutting recipe with the key "test_recipe_stonecutting_input": + set the recipe input item to {_input} + set the recipe result to smooth stone named "test_recipe_stonecutting_input" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_stonecutting_input" + assert the recipe input item of {_last} = {_input} with "Mismatch of recipe input item from last registered recipe" + assert the recipe input item of {_get} = {_input} with "Mismatch of recipe input item from get recipe" + +test "recipe base, template and addition item": + set {_base} to diamond named "test_recipe_base_template_addition" + set {_template} to netherite ingot named "test_recipe_base_template_addition" + set {_addition} to emerald named "test_recipe_base_template_addition" + register a new smithing transform recipe with the key "test_recipe_base_template_addition": + set the recipe base item to {_base} + set the recipe template item to {_template} + set the recipe addition item to {_addition} + set the recipe result to netherite sword named "test_recipe_base_template_addition" + set {_last} to last registered recipe + set {_get} to recipe with the key "test_recipe_base_template_addition" + assert the recipe base item of {_last} = {_base} with "Mismatch of recipe base item from last registered recipe" + assert the recipe base item of {_get} = {_base} with "Mismatch of recipe base item from last registered recipe" + assert the recipe template item of {_last} = {_template} with "Mismatch of recipe template item from last registered recipe" + assert the recipe template item of {_get} = {_template} with "Mismatch of recipe template item from last registered recipe" + assert the recipe addition item of {_last} = {_addition} with "Mismatch of recipe addition item from last registered recipe" + assert the recipe addition item of {_get} = {_addition} with "Mismatch of recipe addition item from last registered recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk index 652e402172a..f36f5b68eda 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKey.sk @@ -4,5 +4,5 @@ test "recipe key": set the recipe result to copper ingot named "test_recipe_key" set {_last} to last registered recipe set {_get} to recipe with the key "test_recipe_key" - assert the recipe key of {_last} = recipe key from "test_recipe_key" with "Key mismatch of last registered recipe" - assert the recipe key of {_get} = recipe key from "test_recipe_key" with "Key mismatch of get recipe" + assert the recipe key of {_last} = converted key from "test_recipe_key" with "Key mismatch of last registered recipe" + assert the recipe key of {_get} = converted key from "test_recipe_key" with "Key mismatch of get recipe" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeKeyConverter.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKeyConverter.sk new file mode 100644 index 00000000000..c7bc974a02c --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeKeyConverter.sk @@ -0,0 +1,10 @@ +test "invalid character conversion": + set {_chars::*} to (split ",<>?;'""[]{}\|=+)(*&^%%$#@!" using "") where [input is not ""] + set {_hexes::*} to split "2c,3c,3e,3f,3b,27,22,5b,5d,7b,7d,5c,7c,3d,2b,29,28,2a,26,5e,25,24,23,40,21,60,7e" using "," + loop {_chars::*}: + set {_key} to "test%loop-value%" + set {_skript} to converted key from {_key} + set {_minecraft} to converted key from {_key} using mc namespace + set {_hex} to {_hexes::%loop-iteration%} + assert {_skript} = "skript:test.x%{_hex}%" with "Improper key conversion of %loop-value% for Skript namespace" + assert {_minecraft} = "minecraft:test.x%{_hex}%" with "Improper key conversion of %loop-value% for Minecraft namespace" From ebc9428599ec2eae64a2af84b58798b724239df7 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Tue, 15 Oct 2024 20:59:00 -0400 Subject: [PATCH 14/20] Fix Imports --- .../skript/classes/data/BukkitClasses.java | 12 ++++++--- .../classes/data/BukkitEventValues.java | 26 ++++++++++++++++++- .../classes/data/DefaultComparators.java | 17 +++++++++--- .../skript/conditions/CondRecipeExists.java | 1 - .../skript/expressions/ExprRecipeResult.java | 2 -- .../skript/expressions/ExprRecipeType.java | 2 -- .../skript/sections/SecRegisterRecipe.java | 2 +- .../ch/njol/skript/util/NamespacedUtils.java | 4 ++- 8 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index ee054a06c80..eb8ef11b58a 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -30,7 +30,6 @@ import java.util.stream.Collectors; import ch.njol.skript.bukkitutil.BukkitUtils; -import ch.njol.skript.util.*; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Difficulty; @@ -72,10 +71,13 @@ import org.bukkit.event.player.PlayerQuitEvent.QuitReason; import org.bukkit.event.player.PlayerResourcePackStatusEvent.Status; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.inventory.*; -import org.bukkit.inventory.BlockInventoryHolder; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.recipe.CookingBookCategory; import org.bukkit.inventory.recipe.CraftingBookCategory; +import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.BlockInventoryHolder; import org.bukkit.metadata.Metadatable; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -101,6 +103,10 @@ import ch.njol.skript.lang.util.SimpleLiteral; import ch.njol.skript.localization.Language; import ch.njol.skript.registrations.Classes; +import ch.njol.skript.util.BlockUtils; +import ch.njol.skript.util.PotionEffectUtils; +import ch.njol.skript.util.StringMode; +import ch.njol.skript.util.RecipeUtils; import ch.njol.util.StringUtils; import ch.njol.yggdrasil.Fields; import io.papermc.paper.world.MoonPhase; diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java index 0b765b76299..272b41a9d7c 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -133,9 +133,33 @@ import org.bukkit.event.inventory.InventoryPickupItemEvent; import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.event.inventory.PrepareItemCraftEvent; -import org.bukkit.event.player.*; +import org.bukkit.event.player.PlayerBedEnterEvent; +import org.bukkit.event.player.PlayerBedLeaveEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerBucketFillEvent; +import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerEditBookEvent; +import org.bukkit.event.player.PlayerEggThrowEvent; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemBreakEvent; +import org.bukkit.event.player.PlayerItemConsumeEvent; +import org.bukkit.event.player.PlayerItemDamageEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerItemMendEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerPickupArrowEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent.QuitReason; +import org.bukkit.event.player.PlayerRiptideEvent; +import org.bukkit.event.player.PlayerShearEntityEvent; +import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.event.player.PlayerToggleFlightEvent; +import org.bukkit.event.player.PlayerRecipeDiscoverEvent; import org.bukkit.event.server.ServerCommandEvent; import org.bukkit.event.vehicle.VehicleDamageEvent; import org.bukkit.event.vehicle.VehicleDestroyEvent; diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java index e25841cb0f8..63c484832bf 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -28,15 +28,26 @@ import ch.njol.skript.entity.BoatData; import ch.njol.skript.entity.EntityData; import ch.njol.skript.entity.RabbitData; -import ch.njol.skript.util.*; +import ch.njol.skript.util.BlockUtils; +import ch.njol.skript.util.Date; +import ch.njol.skript.util.EnchantmentType; +import ch.njol.skript.util.Experience; +import ch.njol.skript.util.GameruleValue; import ch.njol.skript.util.StructureType; +import ch.njol.skript.util.Time; +import ch.njol.skript.util.Timeperiod; +import ch.njol.skript.util.Timespan; +import ch.njol.skript.util.RecipeUtils; import ch.njol.skript.util.WeatherType; import ch.njol.skript.util.slot.EquipmentSlot; import ch.njol.skript.util.slot.Slot; import ch.njol.skript.util.slot.SlotWithIndex; import ch.njol.util.StringUtils; import ch.njol.util.coll.CollectionUtils; -import org.bukkit.*; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.command.CommandSender; @@ -50,8 +61,6 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.Recipe; -import org.bukkit.inventory.ShapedRecipe; import org.bukkit.potion.PotionEffectType; import org.skriptlang.skript.lang.comparator.Comparator; import org.skriptlang.skript.lang.comparator.Comparators; diff --git a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java index 1ac5de68ea3..87b71a0b894 100644 --- a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java +++ b/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java @@ -11,7 +11,6 @@ import ch.njol.skript.util.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java index 4187bed39e5..0ae0d3d9644 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java @@ -19,8 +19,6 @@ import org.bukkit.inventory.Recipe; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; - @Name("Recipe Result") @Description("The result item for a recipe") @Examples({ diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java index 226158a85f4..c0a337142c9 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java @@ -15,8 +15,6 @@ import org.bukkit.inventory.Recipe; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; - @Name("Recipe Type") @Description("Get the recipe type of a recipe") @Examples({ diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java index 2c749ea88a6..0155e3120e3 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java @@ -78,7 +78,7 @@ }) @Since("INSERT VERSION") public class SecRegisterRecipe extends Section { - + private static final boolean RUNNING_1_20 = Skript.isRunningMinecraft(1, 20, 0); static { diff --git a/src/main/java/ch/njol/skript/util/NamespacedUtils.java b/src/main/java/ch/njol/skript/util/NamespacedUtils.java index 29fbe6bfb5b..112e8bb531c 100644 --- a/src/main/java/ch/njol/skript/util/NamespacedUtils.java +++ b/src/main/java/ch/njol/skript/util/NamespacedUtils.java @@ -16,6 +16,7 @@ public class NamespacedUtils { * Gets a namespaced key. This method will try to get existing keys first, but if that fails * it will create the key in Skript's namespace. * @param key the unparsed key + * @param usingMinecraft whether to have it as Skript or Minecraft namespace * @return the resulting NamespacedKey */ public static NamespacedKey getNamespacedKey(String key, Boolean usingMinecraft) { @@ -38,7 +39,8 @@ public static NamespacedKey getNamespacedKey(String key, Boolean usingMinecraft) * This key will be created in Skript's namespace. * * @param key The key to use - * @return a NamespacedKey with the encoded key in Skript's namespace + * @param usingMinecraft whether to have it as Skript or Minecraft's namespace + * @return a NamespacedKey with the encoded key in corresponding Namespace */ public static NamespacedKey createNamespacedKey(String key, Boolean usingMinecraft) { // TODO: add tests for this From 793c3eea37c10b5000465e1fe2bf95204f20c74c Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:00:02 -0400 Subject: [PATCH 15/20] One more fix --- src/main/java/ch/njol/skript/classes/data/BukkitClasses.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index eb8ef11b58a..69e3237df00 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -71,13 +71,13 @@ import org.bukkit.event.player.PlayerQuitEvent.QuitReason; import org.bukkit.event.player.PlayerResourcePackStatusEvent.Status; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.inventory.BlockInventoryHolder; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.recipe.CookingBookCategory; import org.bukkit.inventory.recipe.CraftingBookCategory; import org.bukkit.inventory.Recipe; -import org.bukkit.inventory.BlockInventoryHolder; import org.bukkit.metadata.Metadatable; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; From 9a628ea29cf8b64135ddfec4082c5a9138282408 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:04:42 -0400 Subject: [PATCH 16/20] Fix Test Gotta love 1.19 --- .../skript/tests/syntaxes/expressions/ExprRecipeIngredients.sk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/skript/tests/syntaxes/expressions/ExprRecipeIngredients.sk b/src/test/skript/tests/syntaxes/expressions/ExprRecipeIngredients.sk index d000f6700d7..d7cab51a6a3 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprRecipeIngredients.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprRecipeIngredients.sk @@ -46,7 +46,7 @@ test "recipe stonecutting input": assert the recipe input item of {_last} = {_input} with "Mismatch of recipe input item from last registered recipe" assert the recipe input item of {_get} = {_input} with "Mismatch of recipe input item from get recipe" -test "recipe base, template and addition item": +test "recipe base, template and addition item" when running minecraft "1.20": set {_base} to diamond named "test_recipe_base_template_addition" set {_template} to netherite ingot named "test_recipe_base_template_addition" set {_addition} to emerald named "test_recipe_base_template_addition" From ed8f1dbc85393994d099a65bce9ba47dc164c3e2 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:25:46 -0400 Subject: [PATCH 17/20] Change RecipeType class register --- .../java/ch/njol/skript/classes/data/BukkitClasses.java | 8 -------- .../java/ch/njol/skript/classes/data/SkriptClasses.java | 9 +++++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index 266d02a877a..5fb9c7726c4 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -99,7 +99,6 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.util.CachedServerIcon; import org.bukkit.util.Vector; -import ch.njol.skript.util.RecipeUtils; import org.jetbrains.annotations.Nullable; import java.io.StreamCorruptedException; @@ -1563,13 +1562,6 @@ public String toVariableNameString(EnchantmentOffer eo) { .since("INSERT VERSION") .defaultExpression(new EventValueExpression<>(Recipe.class))); - Classes.registerClass(new EnumClassInfo<>(RecipeUtils.RecipeType.class, "recipetype", "recipe types") - .user("recipe type") - .name("Recipe Type") - .description("Represents recipe types") - .since("INSERT VERSION") - ); - Classes.registerClass(new EnumClassInfo<>(CraftingBookCategory.class, "craftingbookcategory", "crafting book categories") .user("crafting book category") .name("Crafting Book Category") diff --git a/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java b/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java index c846b00e680..3a73440a21e 100644 --- a/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java @@ -8,6 +8,7 @@ import ch.njol.skript.bukkitutil.ItemUtils; import ch.njol.skript.classes.Changer; import ch.njol.skript.classes.ClassInfo; +import ch.njol.skript.classes.EnumClassInfo; import ch.njol.skript.classes.EnumSerializer; import ch.njol.skript.classes.Parser; import ch.njol.skript.classes.Serializer; @@ -25,6 +26,7 @@ import ch.njol.skript.util.EnchantmentType; import ch.njol.skript.util.Experience; import ch.njol.skript.util.GameruleValue; +import ch.njol.skript.util.RecipeUtils; import ch.njol.skript.util.SkriptColor; import ch.njol.skript.util.StructureType; import ch.njol.skript.util.Time; @@ -668,6 +670,13 @@ public String toVariableNameString(VisualEffect e) { .since("2.5") .serializer(new YggdrasilSerializer()) ); + + Classes.registerClass(new EnumClassInfo<>(RecipeUtils.RecipeType.class, "recipetype", "recipe types") + .user("recipe type") + .name("Recipe Type") + .description("Represents recipe types") + .since("INSERT VERSION") + ); } } From 1cc3c24eb7298b67e8199f802301a7f1784dc1d6 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:39:41 -0400 Subject: [PATCH 18/20] Module + Changes --- src/main/java/ch/njol/skript/Skript.java | 2 + .../skript/classes/data/BukkitClasses.java | 26 -------- .../classes/data/DefaultComparators.java | 10 --- .../skript/classes/data/SkriptClasses.java | 9 --- .../java/ch/njol/skript/util/RecipeUtils.java | 7 +- .../skript/bukkit/recipes/RecipeModule.java | 66 +++++++++++++++++++ .../elements}/CondDiscoveredRecipes.java | 5 +- .../recipes/elements}/CondRecipeExists.java | 6 +- .../recipes/elements}/EffDiscoverRecipe.java | 22 +++---- .../recipes/elements}/EffRemoveRecipe.java | 8 +-- .../recipes/elements}/EffResetRecipes.java | 4 +- .../recipes/elements}/EvtDiscoverRecipe.java | 12 ++-- .../recipes/elements}/ExprAllRecipes.java | 15 +++-- .../recipes/elements}/ExprGetRecipe.java | 8 +-- .../recipes/elements}/ExprLastRecipe.java | 5 +- .../recipes/elements}/ExprRecipeCategory.java | 2 +- .../elements}/ExprRecipeCookingTime.java | 14 ++-- .../elements}/ExprRecipeExperience.java | 7 +- .../recipes/elements}/ExprRecipeGroup.java | 11 ++-- .../elements}/ExprRecipeIngredients.java | 2 +- .../recipes/elements}/ExprRecipeKey.java | 2 +- .../elements}/ExprRecipeKeyConverter.java | 2 +- .../recipes/elements}/ExprRecipeResult.java | 2 +- .../recipes/elements}/ExprRecipeType.java | 2 +- .../recipes/elements}/SecRegisterRecipe.java | 4 +- 25 files changed, 139 insertions(+), 114 deletions(-) create mode 100644 src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java rename src/main/java/{ch/njol/skript/conditions => org/skriptlang/skript/bukkit/recipes/elements}/CondDiscoveredRecipes.java (94%) rename src/main/java/{ch/njol/skript/conditions => org/skriptlang/skript/bukkit/recipes/elements}/CondRecipeExists.java (91%) rename src/main/java/{ch/njol/skript/effects => org/skriptlang/skript/bukkit/recipes/elements}/EffDiscoverRecipe.java (78%) rename src/main/java/{ch/njol/skript/effects => org/skriptlang/skript/bukkit/recipes/elements}/EffRemoveRecipe.java (86%) rename src/main/java/{ch/njol/skript/effects => org/skriptlang/skript/bukkit/recipes/elements}/EffResetRecipes.java (88%) rename src/main/java/{ch/njol/skript/events => org/skriptlang/skript/bukkit/recipes/elements}/EvtDiscoverRecipe.java (80%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprAllRecipes.java (91%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprGetRecipe.java (92%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprLastRecipe.java (89%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprRecipeCategory.java (98%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprRecipeCookingTime.java (86%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprRecipeExperience.java (92%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprRecipeGroup.java (92%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprRecipeIngredients.java (99%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprRecipeKey.java (97%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprRecipeKeyConverter.java (97%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprRecipeResult.java (98%) rename src/main/java/{ch/njol/skript/expressions => org/skriptlang/skript/bukkit/recipes/elements}/ExprRecipeType.java (96%) rename src/main/java/{ch/njol/skript/sections => org/skriptlang/skript/bukkit/recipes/elements}/SecRegisterRecipe.java (99%) diff --git a/src/main/java/ch/njol/skript/Skript.java b/src/main/java/ch/njol/skript/Skript.java index 0bd0a4877b7..a6eb9403d27 100644 --- a/src/main/java/ch/njol/skript/Skript.java +++ b/src/main/java/ch/njol/skript/Skript.java @@ -95,6 +95,7 @@ import org.junit.runner.notification.Failure; import org.skriptlang.skript.bukkit.SkriptMetrics; import org.skriptlang.skript.bukkit.displays.DisplayModule; +import org.skriptlang.skript.bukkit.recipes.RecipeModule; import org.skriptlang.skript.lang.comparator.Comparator; import org.skriptlang.skript.lang.comparator.Comparators; import org.skriptlang.skript.lang.converter.Converter; @@ -555,6 +556,7 @@ public void onEnable() { getAddonInstance().loadClasses("org.skriptlang.skript.bukkit", "misc"); // todo: become proper module once registry api is merged DisplayModule.load(); + RecipeModule.load(); } catch (final Exception e) { exception(e, "Could not load required .class files: " + e.getLocalizedMessage()); setEnabled(false); diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index 5fb9c7726c4..1174f17097f 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -91,9 +91,6 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.recipe.CookingBookCategory; -import org.bukkit.inventory.recipe.CraftingBookCategory; -import org.bukkit.inventory.Recipe; import org.bukkit.metadata.Metadatable; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -1552,29 +1549,6 @@ public String toVariableNameString(EnchantmentOffer eo) { .since("@VERSION") .requiredPlugins("Minecraft 1.21+") .documentationId("WolfVariant")); - - Classes.registerClass(new ClassInfo<>(Recipe.class, "recipe") - .user("recipes?") - .name("Recipe") - .description("") - .usage("") - .examples("") - .since("INSERT VERSION") - .defaultExpression(new EventValueExpression<>(Recipe.class))); - - Classes.registerClass(new EnumClassInfo<>(CraftingBookCategory.class, "craftingbookcategory", "crafting book categories") - .user("crafting book category") - .name("Crafting Book Category") - .description("Represents a category for crafting recipe types") - .since("INSERT VERSION") - ); - - Classes.registerClass(new EnumClassInfo<>(CookingBookCategory.class, "cookingbookcategory", "cooking book categories") - .user("cooking book category") - .name("Cooking Book Category") - .description("Represents a category for cooking recipe types") - .since("INSERT VERSION") - ); } } diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java index afdacd142b8..c88a98bdf88 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -38,7 +38,6 @@ import ch.njol.skript.util.Time; import ch.njol.skript.util.Timeperiod; import ch.njol.skript.util.Timespan; -import ch.njol.skript.util.RecipeUtils; import ch.njol.skript.util.WeatherType; import ch.njol.skript.util.slot.EquipmentSlot; import ch.njol.skript.util.slot.Slot; @@ -671,15 +670,6 @@ public boolean supportsOrdering() { Comparators.registerComparator(Color.class, Color.class, (one, two) -> Relation.get(one.asBukkitColor().equals(two.asBukkitColor()))); Comparators.registerComparator(Color.class, org.bukkit.Color.class, (one, two) -> Relation.get(one.asBukkitColor().equals(two))); Comparators.registerComparator(org.bukkit.Color.class, org.bukkit.Color.class, (one, two) -> Relation.get(one.equals(two))); - - Comparators.registerComparator(RecipeUtils.RecipeType.class, RecipeUtils.RecipeType.class, new Comparator() { - @Override - public Relation compare(RecipeUtils.RecipeType type1, RecipeUtils.RecipeType type2) { - if (type1.getRecipeClass() != null && type2.getRecipeClass() != null) - return Relation.get(type2.getRecipeClass().isAssignableFrom(type1.getRecipeClass())); - return Relation.NOT_EQUAL; - } - }); } } diff --git a/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java b/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java index 3a73440a21e..c846b00e680 100644 --- a/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/SkriptClasses.java @@ -8,7 +8,6 @@ import ch.njol.skript.bukkitutil.ItemUtils; import ch.njol.skript.classes.Changer; import ch.njol.skript.classes.ClassInfo; -import ch.njol.skript.classes.EnumClassInfo; import ch.njol.skript.classes.EnumSerializer; import ch.njol.skript.classes.Parser; import ch.njol.skript.classes.Serializer; @@ -26,7 +25,6 @@ import ch.njol.skript.util.EnchantmentType; import ch.njol.skript.util.Experience; import ch.njol.skript.util.GameruleValue; -import ch.njol.skript.util.RecipeUtils; import ch.njol.skript.util.SkriptColor; import ch.njol.skript.util.StructureType; import ch.njol.skript.util.Time; @@ -670,13 +668,6 @@ public String toVariableNameString(VisualEffect e) { .since("2.5") .serializer(new YggdrasilSerializer()) ); - - Classes.registerClass(new EnumClassInfo<>(RecipeUtils.RecipeType.class, "recipetype", "recipe types") - .user("recipe type") - .name("Recipe Type") - .description("Represents recipe types") - .since("INSERT VERSION") - ); } } diff --git a/src/main/java/ch/njol/skript/util/RecipeUtils.java b/src/main/java/ch/njol/skript/util/RecipeUtils.java index 8cecb3ead8f..b101b3f4d09 100644 --- a/src/main/java/ch/njol/skript/util/RecipeUtils.java +++ b/src/main/java/ch/njol/skript/util/RecipeUtils.java @@ -15,10 +15,10 @@ public class RecipeUtils { // Due to 1.19 not having 'CraftingRecipe.class' static { - if (Skript.classExists("org.bukkit.inventory.CraftingRecipe")) { + if (Skript.classExists("org.bukkit.inventory.CraftingRecipe")) CRAFTING_CLASS = CraftingRecipe.class; - } } + public enum RecipeType { SHAPED(ShapedRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class), SHAPELESS(ShapelessRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapelessRecipeEvent.class), @@ -65,7 +65,6 @@ public static RecipeType getRecipeTypeFromRecipe(Recipe providedRecipe) { } // Custom Events used for SecRegisterRecipe - public static class RegisterRecipeEvent extends Event { private ItemStack resultItem; private boolean errorInEffect = false; @@ -287,4 +286,4 @@ public RecipeChoice getInput() { } } -} \ No newline at end of file +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java new file mode 100644 index 00000000000..fc74588797e --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java @@ -0,0 +1,66 @@ +package org.skriptlang.skript.bukkit.recipes; + +import ch.njol.skript.Skript; +import ch.njol.skript.classes.ClassInfo; +import ch.njol.skript.classes.EnumClassInfo; +import ch.njol.skript.expressions.base.EventValueExpression; +import ch.njol.skript.registrations.Classes; +import ch.njol.skript.util.RecipeUtils; +import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.recipe.CookingBookCategory; +import org.bukkit.inventory.recipe.CraftingBookCategory; +import org.skriptlang.skript.lang.comparator.Comparator; +import org.skriptlang.skript.lang.comparator.Comparators; +import org.skriptlang.skript.lang.comparator.Relation; + +import java.io.IOException; + +public class RecipeModule { + + public static void load() throws IOException { + if (!Skript.classExists("org.bukkit.inventory.Recipe")) + return; + + Skript.getAddonInstance().loadClasses("org.skriptlang.skript.bukkit", "recipes"); + + Classes.registerClass(new ClassInfo<>(Recipe.class, "recipe") + .user("recipes?") + .name("Recipe") + .description("Represents a recipe type") + .usage("recipes") + .examples("all recipes") + .since("INSERT VERSION") + .defaultExpression(new EventValueExpression<>(Recipe.class))); + + Classes.registerClass(new EnumClassInfo<>(CraftingBookCategory.class, "craftingbookcategory", "crafting book categories") + .user("crafting book category") + .name("Crafting Book Category") + .description("Represents the different categories of crafting recipes") + .since("INSERT VERSION") + ); + + Classes.registerClass(new EnumClassInfo<>(CookingBookCategory.class, "cookingbookcategory", "cooking book categories") + .user("cooking book category") + .name("Cooking Book Category") + .description("Represents the different categories of cooking recipes") + .since("INSERT VERSION") + ); + + Classes.registerClass(new EnumClassInfo<>(RecipeUtils.RecipeType.class, "recipetype", "recipe types") + .user("recipe type") + .name("Recipe Type") + .description("Represents recipe types") + .since("INSERT VERSION") + ); + + Comparators.registerComparator(RecipeUtils.RecipeType.class, RecipeUtils.RecipeType.class, new Comparator() { + @Override + public Relation compare(RecipeUtils.RecipeType type1, RecipeUtils.RecipeType type2) { + if (type1.getRecipeClass() != null && type2.getRecipeClass() != null) + return Relation.get(type2.getRecipeClass().isAssignableFrom(type1.getRecipeClass())); + return Relation.NOT_EQUAL; + } + }); + } + +} diff --git a/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondDiscoveredRecipes.java similarity index 94% rename from src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondDiscoveredRecipes.java index f6fe06caa37..3ef2ffc6808 100644 --- a/src/main/java/ch/njol/skript/conditions/CondDiscoveredRecipes.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondDiscoveredRecipes.java @@ -1,4 +1,4 @@ -package ch.njol.skript.conditions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; @@ -38,9 +38,10 @@ public class CondDiscoveredRecipes extends Condition { private Expression recipes; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + //noinspection unchecked players = (Expression) exprs[0]; + //noinspection unchecked recipes = (Expression) exprs[1]; setNegated(matchedPattern == 1); return true; diff --git a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondRecipeExists.java similarity index 91% rename from src/main/java/ch/njol/skript/conditions/CondRecipeExists.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondRecipeExists.java index 87b71a0b894..ddc4968c0ba 100644 --- a/src/main/java/ch/njol/skript/conditions/CondRecipeExists.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondRecipeExists.java @@ -1,4 +1,4 @@ -package ch.njol.skript.conditions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; @@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable; @Name("Recipe Exists") -@Description("Checks to see if a recipe exists using the name") +@Description("Checks to see if the specified recipe exists.") @Examples({ "if the recipe \"my_recipe\" exists:", "\tremove the recipe \"my_recipe\" from the server" @@ -32,8 +32,8 @@ public class CondRecipeExists extends Condition { private Expression recipes; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + //noinspection unchecked recipes = (Expression) exprs[0]; setNegated(matchedPattern == 1); return true; diff --git a/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffDiscoverRecipe.java similarity index 78% rename from src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffDiscoverRecipe.java index 5ea0c5d0f4d..d0b19bf7f3b 100644 --- a/src/main/java/ch/njol/skript/effects/EffDiscoverRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffDiscoverRecipe.java @@ -1,4 +1,4 @@ -package ch.njol.skript.effects; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; @@ -17,7 +17,7 @@ import org.jetbrains.annotations.Nullable; @Name("Discover Recipe") -@Description("Discover or undiscover recipes for players.") +@Description("Discovers or forgets the recipes for the specified players.") @Examples({ "make player discover recipe \"my_recipe\"", "make player undiscover recipe \"my_recipe\"", @@ -30,9 +30,9 @@ public class EffDiscoverRecipe extends Effect { static { Skript.registerEffect(EffDiscoverRecipe.class, "make %players% (discover|unlock) recipe[s] %strings%", - "make %players% (undiscover|lock) recipe[s] %strings%", + "make %players% (undiscover|lock|forget) recipe[s] %strings%", "(discover|unlock) recipe[s] %strings% for %players%", - "(undiscover|lock) recipe[s] %strings% for %players%"); + "(undiscover|lock|forget) recipe[s] %strings% for %players%"); } private Expression players; @@ -40,26 +40,25 @@ public class EffDiscoverRecipe extends Effect { private boolean isDiscover = false; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { isDiscover = matchedPattern == 0 || matchedPattern == 2; + //noinspection unchecked players = (Expression) (matchedPattern <= 1 ? exprs[0] : exprs[1]); + //noinspection unchecked recipes = (Expression) (matchedPattern <= 1 ? exprs[1] : exprs[0]); return true; } @Override protected void execute(Event event) { - for (Player player : players.getArray(event)) { - for (String recipe : recipes.getArray(event)) { - NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe, false); - if (Bukkit.getRecipe(key) != null) { + for (String recipe : recipes.getArray(event)) { + NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe, false); + if (Bukkit.getRecipe(key) != null) { + for (Player player : players.getArray(event)) { if (isDiscover) player.discoverRecipe(key); else player.undiscoverRecipe(key); - } else { - break; } } } @@ -69,4 +68,5 @@ protected void execute(Event event) { public String toString(@Nullable Event event, boolean debug) { return "make " + players.toString(event, debug) + (isDiscover ? " discover" : " undiscover") + " recipes " + recipes.toString(event, debug); } + } diff --git a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffRemoveRecipe.java similarity index 86% rename from src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffRemoveRecipe.java index c02436908bd..05e60e49740 100644 --- a/src/main/java/ch/njol/skript/effects/EffRemoveRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffRemoveRecipe.java @@ -1,4 +1,4 @@ -package ch.njol.skript.effects; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; @@ -17,8 +17,8 @@ @Name("Remove Recipe") @Description({ - "Remove a recipe or multiple recipes from the server", - "Removing a recipe from a server will cause all players who have discovered the recipe to be undiscovered." + "Remove the specified recipes from the server.", + "This will cause all players who have discovered the recipe to forget it." }) @Examples("remove the recipe \"my_recipe\" from the server") @Since("INSERT VERSION") @@ -32,8 +32,8 @@ public class EffRemoveRecipe extends Effect { private Expression recipes; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + //noinspection unchecked recipes = (Expression) exprs[0]; return true; } diff --git a/src/main/java/ch/njol/skript/effects/EffResetRecipes.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffResetRecipes.java similarity index 88% rename from src/main/java/ch/njol/skript/effects/EffResetRecipes.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffResetRecipes.java index 5f4567be020..7a91758a48e 100644 --- a/src/main/java/ch/njol/skript/effects/EffResetRecipes.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffResetRecipes.java @@ -1,4 +1,4 @@ -package ch.njol.skript.effects; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; @@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; @Name("Reset Recipes") -@Description("Resets recipes of server to default.") +@Description("Resets the recipes to the Minecraft-provided defaults.") @Examples("reset server recipes") @Since("INSERT VERSION") public class EffResetRecipes extends Effect { diff --git a/src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EvtDiscoverRecipe.java similarity index 80% rename from src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EvtDiscoverRecipe.java index f0fe70b3b1d..a2d6f581ba1 100644 --- a/src/main/java/ch/njol/skript/events/EvtDiscoverRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EvtDiscoverRecipe.java @@ -1,4 +1,4 @@ -package ch.njol.skript.events; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; @@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable; @Name("Player Discover Recipe") -@Description("Called when a player discovers a recipe") +@Description("Called when a player discovers a new recipe.") @Examples({ "on player discovered recipe:", "\tbroadcast event-recipe", @@ -28,14 +28,14 @@ public class EvtDiscoverRecipe extends SkriptEvent { static { Skript.registerEvent("Player Discover Recipe", EvtDiscoverRecipe.class, PlayerRecipeDiscoverEvent.class, - "[player] discover[ed] recipe [of %strings%]"); + "[player] discover[ed|ing] recipe[s] [of %-strings%]"); } - private Expression recipes; + private @Nullable Expression recipes; @Override - @SuppressWarnings("unchecked") public boolean init(Literal[] exprs, int matchedPattern, ParseResult parseResult) { + //noinspection unchecked recipes = (Expression) exprs[0]; return true; } @@ -52,6 +52,6 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - return "player discovered" + (recipes == null ? "" : " of " + recipes.toString(event, debug)); + return "player discovered recipes" + (recipes == null ? "" : " of " + recipes.toString(event, debug)); } } diff --git a/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprAllRecipes.java similarity index 91% rename from src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprAllRecipes.java index 10179d4f538..f0c9ec945b0 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprAllRecipes.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprAllRecipes.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; @@ -27,10 +27,12 @@ @Name("All Recipes") @Description({ "Retrieve all recipes registered in the server", - "You can retrieve all recipes of a recipe type", - "You can retrieve all recipes of an item, including custom items", - "You can retrieve all minecraft recipes", - "You can retrieve all custom recipes made by any and all plugins" + "
    ", + "
  • You can retrieve all recipes of a recipe type.
  • ", + "
  • You can retrieve all recipes of an item, including custom items.
  • ", + "
  • You can retrieve all minecraft recipes.
  • ", + "
  • You can retrieve all custom recipes made by any and all plugins.
  • ", + "
" }) @Examples({ "set {_list::*} to all of the recipe of type shaped recipe for netherite ingot", @@ -55,8 +57,8 @@ public class ExprAllRecipes extends SimpleExpression { private boolean getMinecraft, getCustom; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + //noinspection unchecked recipeTypeExpr = matchedPattern >= 3 ? (Expression) exprs[0] : null; itemExpr = parseResult.hasTag("items") ? exprs[1] : null; getMinecraft = matchedPattern == 1 || matchedPattern == 4; @@ -66,7 +68,6 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override protected Recipe @Nullable [] get(Event event) { - List recipeList = new ArrayList<>(); Iterator iterator = null; if (itemExpr != null) { diff --git a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprGetRecipe.java similarity index 92% rename from src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprGetRecipe.java index 0e920cbebe8..87b28162355 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprGetRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprGetRecipe.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; @@ -20,8 +20,8 @@ import java.util.ArrayList; import java.util.List; -@Name("Get Recipe") -@Description("Get a recipe registered under the provided key") +@Name("Recipe") +@Description("Returns the recipe registered with the provided name.") @Examples({ "set {_recipe} to recipe with the key \"my_recipe\"", "set {_recipes::*} to recipes with the ids \"my_recipe\" and \"custom_recipe\"" @@ -37,8 +37,8 @@ public class ExprGetRecipe extends SimpleExpression { private Expression recipeNames; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + //noinspection unchecked recipeNames = (Expression) exprs[0]; return true; } diff --git a/src/main/java/ch/njol/skript/expressions/ExprLastRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprLastRecipe.java similarity index 89% rename from src/main/java/ch/njol/skript/expressions/ExprLastRecipe.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprLastRecipe.java index 5b2f9ee4362..9ccfd5db136 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprLastRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprLastRecipe.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; @@ -9,14 +9,13 @@ import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; -import ch.njol.skript.sections.SecRegisterRecipe; import ch.njol.util.Kleenean; import org.bukkit.event.Event; import org.bukkit.inventory.Recipe; import org.jetbrains.annotations.Nullable; @Name("Last Registered Recipe") -@Description("Gets the recipe that was last registered through the Register Recipe Section.") +@Description("Gets the recipe that was most recently registered through the Register Recipe Section.") @Examples({ "register a new shapeless recipe with the key \"my_recipe\":", "\tset ingredients to diamond, emerald and iron ingot", diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCategory.java similarity index 98% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCategory.java index 0b84620fa08..2269f95448d 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCategory.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCategory.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.classes.Changer.ChangeMode; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCookingTime.java similarity index 86% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCookingTime.java index a0499ce1517..3b921b796bd 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeCookingTime.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCookingTime.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.classes.Changer.ChangeMode; @@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable; @Name("Recipe Cooking Time") -@Description("The cooking time of a Cooking, Blasting, Furnace, Campfire and Smoking Recipe.") +@Description("The cooking time of a blasting, furnace, campfire or smoking recipe.") @Examples({ "register a new blasting recipe with the key \"my_recipe\":", "\tset the recipe input item to raw gold named \"Impure Gold\"", @@ -33,24 +33,23 @@ public class ExprRecipeCookingTime extends PropertyExpression { static { - Skript.registerExpression(ExprRecipeCookingTime.class, Timespan.class, ExpressionType.PROPERTY, - "[the] recipe cook[ing] time [of %-recipes%]"); + Skript.registerExpression(ExprRecipeCookingTime.class, Timespan.class, ExpressionType.PROPERTY, "[the] recipe cook[ing] time [of %-recipes%]"); } private boolean isEvent = false; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { if (exprs[0] != null) { + //noinspection unchecked setExpr((Expression) exprs[0]); } else { if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { - Skript.error("There is no 'recipe' in a " + getParser().getCurrentEventName() + " event."); + Skript.error("There is no recipe in a " + getParser().getCurrentEventName() + " event."); return false; } if (!getParser().isCurrentEvent(CookingRecipeEvent.class)) { - Skript.error("This can only be used when registering a Cooking, Blasting, Furnace, Campfire or Smoking Recipe."); + Skript.error("This can only be used when registering a blasting, furnace, campfire or smoking Recipe."); return false; } isEvent = true; @@ -97,4 +96,5 @@ public Class getReturnType() { public String toString(@Nullable Event event, boolean debug) { return "the recipe cooking time of " + getExpr().toString(event, debug); } + } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeExperience.java similarity index 92% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeExperience.java index c2ba33c961d..d8d3adf4e22 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeExperience.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeExperience.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.classes.Changer.ChangeMode; @@ -21,7 +21,7 @@ import org.jetbrains.annotations.Nullable; @Name("Recipe Experience") -@Description("The experience of a Cooking, Blasting, Furnace, Campfire, and Smoking Recipe.") +@Description("The experience of a blasting, furnace, campfire, or smoking recipe.") @Examples({ "register a new blasting recipe with the key \"my_recipe\":", "\tset the recipe input item to a raw copper named \"Impure Copper\"", @@ -49,7 +49,7 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye return false; } if (!getParser().isCurrentEvent(CookingRecipeEvent.class)) { - Skript.error("This can only be used when registering a Cooking, Blasting, Furnace, Campfire or Smoking Recipe."); + Skript.error("This can only be used when registering a blasting, furnace, campfire or smoking recipe."); return false; } isEvent = true; @@ -96,4 +96,5 @@ public Class getReturnType() { public String toString(@Nullable Event event, boolean debug) { return "the recipe experience of " + getExpr().toString(event, debug); } + } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeGroup.java similarity index 92% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeGroup.java index cfdfec939a4..eaf829a79e4 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeGroup.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeGroup.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.classes.Changer.ChangeMode; @@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable; @Name("Recipe Group") -@Description("The recipe group of a Shaped, Shapeless, Cooking, Blasting, Furnace, Campfire and Smoking Recipe.") +@Description("The recipe group of a shaped, shapeless, blasting, furnace, campfire or smoking recipe.") @Examples({ "register a new shapeless recipe with the key \"my_recipe\":", "\tset the recipe ingredients to 3 diamonds, 3 emeralds and 3 netherite ingots", @@ -64,7 +64,6 @@ protected String[] get(Event event, Recipe[] source) { return null; return get(source, recipe -> { - if (recipe instanceof CookingRecipe cookingRecipe) { return cookingRecipe.getGroup(); } else if (SUPPORT_CRAFTING_TYPE && recipe instanceof CraftingRecipe craftingRecipe) { @@ -91,10 +90,11 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { if (group.isEmpty()) return; - if (event instanceof CookingRecipeEvent cookingEvent) + if (event instanceof CookingRecipeEvent cookingEvent) { cookingEvent.setGroup(group); - else if (event instanceof CraftingRecipeEvent craftingEvent) + } else if (event instanceof CraftingRecipeEvent craftingEvent) { craftingEvent.setGroup(group); + } } @Override @@ -106,4 +106,5 @@ public Class getReturnType() { public String toString(@Nullable Event event, boolean debug) { return "the recipe group of " + getExpr().toString(event, debug); } + } diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeIngredients.java similarity index 99% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeIngredients.java index e628d983c2e..af14ec6bf4f 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeIngredients.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeIngredients.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.aliases.ItemType; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKey.java similarity index 97% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKey.java index 193b8f61350..8de5561f310 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeKey.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKey.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeKeyConverter.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKeyConverter.java similarity index 97% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeKeyConverter.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKeyConverter.java index 0c9b8791b17..23f5434ab5b 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeKeyConverter.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKeyConverter.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeResult.java similarity index 98% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeResult.java index 0ae0d3d9644..ce93186b77d 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeResult.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeResult.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; diff --git a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeType.java similarity index 96% rename from src/main/java/ch/njol/skript/expressions/ExprRecipeType.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeType.java index c0a337142c9..77fca9efed6 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRecipeType.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeType.java @@ -1,4 +1,4 @@ -package ch.njol.skript.expressions; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.doc.Description; diff --git a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/SecRegisterRecipe.java similarity index 99% rename from src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java rename to src/main/java/org/skriptlang/skript/bukkit/recipes/elements/SecRegisterRecipe.java index 0155e3120e3..7cecb29dec8 100644 --- a/src/main/java/ch/njol/skript/sections/SecRegisterRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/SecRegisterRecipe.java @@ -1,4 +1,4 @@ -package ch.njol.skript.sections; +package org.skriptlang.skript.bukkit.recipes.elements; import ch.njol.skript.Skript; import ch.njol.skript.config.Node; @@ -269,4 +269,4 @@ public String toString(@Nullable Event event, boolean debug) { return "register a new " + providedType + " recipe with the namespacekey " + providedName.toString(event, debug); } -} \ No newline at end of file +} From 48a6c1fd8c78e5e6b592760868e0d6130c8b7460 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:45:34 -0400 Subject: [PATCH 19/20] Fuse's Changes --- .../ch/njol/skript/classes/data/BukkitEventValues.java | 4 ++++ .../skriptlang/skript/bukkit/recipes/RecipeModule.java | 10 +++++----- src/main/resources/lang/default.lang | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java index fa79159af17..cc3c1c20aea 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -1394,12 +1394,14 @@ public Player get(final PrepareItemCraftEvent e) { return null; } }, 0); + EventValues.registerEventValue(PrepareItemCraftEvent.class, Recipe.class, new Getter() { @Override public @Nullable Recipe get(PrepareItemCraftEvent event) { return event.getRecipe(); } }, EventValues.TIME_NOW); + // CraftEvents - recipe namespaced key strings EventValues.registerEventValue(CraftItemEvent.class, String.class, new Getter() { @Nullable @@ -1429,12 +1431,14 @@ public ItemStack get(CraftItemEvent e) { return e.getRecipe().getResult(); } }, 0); + EventValues.registerEventValue(CraftItemEvent.class, Recipe.class, new Getter() { @Override public @Nullable Recipe get(CraftItemEvent event) { return event.getRecipe(); } }, EventValues.TIME_NOW); + //InventoryOpenEvent EventValues.registerEventValue(InventoryOpenEvent.class, Player.class, new Getter() { @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java index fc74588797e..5fc038281be 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java @@ -21,33 +21,33 @@ public static void load() throws IOException { if (!Skript.classExists("org.bukkit.inventory.Recipe")) return; - Skript.getAddonInstance().loadClasses("org.skriptlang.skript.bukkit", "recipes"); + Skript.getAddonInstance().loadClasses("org.skriptlang.skript.bukkit.recipes", "elements"); Classes.registerClass(new ClassInfo<>(Recipe.class, "recipe") .user("recipes?") .name("Recipe") - .description("Represents a recipe type") + .description("Represents a recipe") .usage("recipes") .examples("all recipes") .since("INSERT VERSION") .defaultExpression(new EventValueExpression<>(Recipe.class))); Classes.registerClass(new EnumClassInfo<>(CraftingBookCategory.class, "craftingbookcategory", "crafting book categories") - .user("crafting book category") + .user("crafting ?book ?categor(y|ies)") .name("Crafting Book Category") .description("Represents the different categories of crafting recipes") .since("INSERT VERSION") ); Classes.registerClass(new EnumClassInfo<>(CookingBookCategory.class, "cookingbookcategory", "cooking book categories") - .user("cooking book category") + .user("cooking ?book ?categor(y|ies)") .name("Cooking Book Category") .description("Represents the different categories of cooking recipes") .since("INSERT VERSION") ); Classes.registerClass(new EnumClassInfo<>(RecipeUtils.RecipeType.class, "recipetype", "recipe types") - .user("recipe type") + .user("recipe ?types?") .name("Recipe Type") .description("Represents recipe types") .since("INSERT VERSION") diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index 6ac2de36ffc..fe3833a6cd0 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2382,7 +2382,7 @@ cooking book categories: # -- Recipe Types -- recipe types: - crafting: crafting recipe + crafting: crafting recipe, crafting recipes shaped: shaped recipe, shaped crafting recipe, shaped recipes, shaped crafting recipes shapeless: shapeless recipe, shapeless crafting recipe, shapeless recipes, shapeless crafting recipes cooking: cooking recipe, cooking recipes From db3e501883b6b52568a04d742ef4ab49773290e1 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 <82696841+TheAbsolutionism@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:33:35 -0400 Subject: [PATCH 20/20] Partial Changes --- .../{util => bukkitutil}/NamespacedUtils.java | 17 ++++--- .../classes/data/BukkitEventValues.java | 23 --------- .../java/ch/njol/skript/util/RecipeUtils.java | 17 +++---- .../skript/bukkit/recipes/RecipeModule.java | 11 ++-- .../elements/CondDiscoveredRecipes.java | 34 ++++++++----- .../recipes/elements/CondRecipeExists.java | 4 +- .../recipes/elements/EffDiscoverRecipe.java | 51 +++++++++++++------ .../recipes/elements/EffRemoveRecipe.java | 27 ++++++---- .../recipes/elements/EffResetRecipes.java | 3 +- .../recipes/elements/EvtDiscoverRecipe.java | 3 +- .../recipes/elements/ExprAllRecipes.java | 32 +++++++----- .../recipes/elements/ExprGetRecipe.java | 5 +- .../recipes/elements/ExprLastRecipe.java | 1 + .../recipes/elements/ExprRecipeCategory.java | 4 +- .../elements/ExprRecipeIngredients.java | 8 +-- .../recipes/elements/ExprRecipeKey.java | 2 +- .../elements/ExprRecipeKeyConverter.java | 4 +- .../recipes/elements/ExprRecipeResult.java | 5 +- .../recipes/elements/ExprRecipeType.java | 5 +- .../recipes/elements/RecipeEventValues.java | 41 +++++++++++++++ .../recipes/elements/SecRegisterRecipe.java | 29 +++++------ 21 files changed, 193 insertions(+), 133 deletions(-) rename src/main/java/ch/njol/skript/{util => bukkitutil}/NamespacedUtils.java (94%) create mode 100644 src/main/java/org/skriptlang/skript/bukkit/recipes/elements/RecipeEventValues.java diff --git a/src/main/java/ch/njol/skript/util/NamespacedUtils.java b/src/main/java/ch/njol/skript/bukkitutil/NamespacedUtils.java similarity index 94% rename from src/main/java/ch/njol/skript/util/NamespacedUtils.java rename to src/main/java/ch/njol/skript/bukkitutil/NamespacedUtils.java index 112e8bb531c..94728b9651c 100644 --- a/src/main/java/ch/njol/skript/util/NamespacedUtils.java +++ b/src/main/java/ch/njol/skript/bukkitutil/NamespacedUtils.java @@ -1,4 +1,4 @@ -package ch.njol.skript.util; +package ch.njol.skript.bukkitutil; import ch.njol.skript.Skript; import ch.njol.util.Pair; @@ -15,18 +15,21 @@ public class NamespacedUtils { /** * Gets a namespaced key. This method will try to get existing keys first, but if that fails * it will create the key in Skript's namespace. + * * @param key the unparsed key * @param usingMinecraft whether to have it as Skript or Minecraft namespace * @return the resulting NamespacedKey */ - public static NamespacedKey getNamespacedKey(String key, Boolean usingMinecraft) { + public static NamespacedKey getNamespacedKey(String key, boolean usingMinecraft) { NamespacedKey namespacedKey; - if (usingMinecraft) + if (usingMinecraft) { namespacedKey = NamespacedKey.fromString(key); - else + } else { namespacedKey = NamespacedKey.fromString(key, Skript.getInstance()); + } if (namespacedKey != null) return namespacedKey; + NamespacedKey convertedKey = createNamespacedKey(key, usingMinecraft); if (!Skript.testing()) Skript.info("The key provided '" + key + "' has been converted to '" + convertedKey.toString() + "' due to invalid characters." + @@ -42,12 +45,10 @@ public static NamespacedKey getNamespacedKey(String key, Boolean usingMinecraft) * @param usingMinecraft whether to have it as Skript or Minecraft's namespace * @return a NamespacedKey with the encoded key in corresponding Namespace */ - public static NamespacedKey createNamespacedKey(String key, Boolean usingMinecraft) { - // TODO: add tests for this + public static NamespacedKey createNamespacedKey(String key, boolean usingMinecraft) { StringBuilder encodedKeyBuilder = new StringBuilder(); // keys must be all lowercase - key = key.toLowerCase(); - key = key.replace(' ', '_'); + key = key.toLowerCase().replace(' ', '_'); int keyLength = key.length(); for (int i = 0; i < keyLength; i++) { char currentChar = key.charAt(i); diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java index cc3c1c20aea..8e990273964 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java @@ -160,7 +160,6 @@ import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.event.player.PlayerToggleFlightEvent; -import org.bukkit.event.player.PlayerRecipeDiscoverEvent; import org.bukkit.event.server.ServerCommandEvent; import org.bukkit.event.vehicle.VehicleDamageEvent; import org.bukkit.event.vehicle.VehicleDestroyEvent; @@ -1395,13 +1394,6 @@ public Player get(final PrepareItemCraftEvent e) { } }, 0); - EventValues.registerEventValue(PrepareItemCraftEvent.class, Recipe.class, new Getter() { - @Override - public @Nullable Recipe get(PrepareItemCraftEvent event) { - return event.getRecipe(); - } - }, EventValues.TIME_NOW); - // CraftEvents - recipe namespaced key strings EventValues.registerEventValue(CraftItemEvent.class, String.class, new Getter() { @Nullable @@ -1432,13 +1424,6 @@ public ItemStack get(CraftItemEvent e) { } }, 0); - EventValues.registerEventValue(CraftItemEvent.class, Recipe.class, new Getter() { - @Override - public @Nullable Recipe get(CraftItemEvent event) { - return event.getRecipe(); - } - }, EventValues.TIME_NOW); - //InventoryOpenEvent EventValues.registerEventValue(InventoryOpenEvent.class, Player.class, new Getter() { @Override @@ -2008,13 +1993,5 @@ public Entity[] get(BlockDropItemEvent event) { return event.getItems().toArray(Entity[]::new); } }, EventValues.TIME_NOW); - - // PlayerRecipeDiscoverEvent - EventValues.registerEventValue(PlayerRecipeDiscoverEvent.class, Recipe.class, new Getter() { - @Override - public @Nullable Recipe get(PlayerRecipeDiscoverEvent event) { - return Bukkit.getRecipe(event.getRecipe()); - } - }, EventValues.TIME_NOW); } } diff --git a/src/main/java/ch/njol/skript/util/RecipeUtils.java b/src/main/java/ch/njol/skript/util/RecipeUtils.java index b101b3f4d09..a06045de1af 100644 --- a/src/main/java/ch/njol/skript/util/RecipeUtils.java +++ b/src/main/java/ch/njol/skript/util/RecipeUtils.java @@ -11,18 +11,10 @@ public class RecipeUtils { - private static Class CRAFTING_CLASS = null; - - // Due to 1.19 not having 'CraftingRecipe.class' - static { - if (Skript.classExists("org.bukkit.inventory.CraftingRecipe")) - CRAFTING_CLASS = CraftingRecipe.class; - } - public enum RecipeType { SHAPED(ShapedRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapedRecipeEvent.class), SHAPELESS(ShapelessRecipe.class, RegisterRecipeEvent.CraftingRecipeEvent.ShapelessRecipeEvent.class), - CRAFTING(CRAFTING_CLASS, RegisterRecipeEvent.CraftingRecipeEvent.class), + CRAFTING(getCraftingRecipeClass(), RegisterRecipeEvent.CraftingRecipeEvent.class), BLASTING(BlastingRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.BlastingRecipeEvent.class), FURNACE(FurnaceRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.FurnaceRecipeEvent.class), CAMPFIRE(CampfireRecipe.class, RegisterRecipeEvent.CookingRecipeEvent.CampfireRecipeEvent.class), @@ -49,6 +41,13 @@ public enum RecipeType { public @Nullable Class getEventClass() { return eventClass; } + + // Due to 1.19 not having 'CraftingRecipe.class' + private static @Nullable Class getCraftingRecipeClass() { + if (Skript.classExists("org.bukkit.inventory.CraftingRecipe")) + return CraftingRecipe.class; + return null; + } } public static RecipeType getRecipeTypeFromRecipeClass(Class providedClass) { diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java index 5fc038281be..abe918ca223 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/RecipeModule.java @@ -18,15 +18,12 @@ public class RecipeModule { public static void load() throws IOException { - if (!Skript.classExists("org.bukkit.inventory.Recipe")) - return; - Skript.getAddonInstance().loadClasses("org.skriptlang.skript.bukkit.recipes", "elements"); Classes.registerClass(new ClassInfo<>(Recipe.class, "recipe") .user("recipes?") .name("Recipe") - .description("Represents a recipe") + .description("Represents a recipe.") .usage("recipes") .examples("all recipes") .since("INSERT VERSION") @@ -35,21 +32,21 @@ public static void load() throws IOException { Classes.registerClass(new EnumClassInfo<>(CraftingBookCategory.class, "craftingbookcategory", "crafting book categories") .user("crafting ?book ?categor(y|ies)") .name("Crafting Book Category") - .description("Represents the different categories of crafting recipes") + .description("Represents the different categories of crafting recipes.") .since("INSERT VERSION") ); Classes.registerClass(new EnumClassInfo<>(CookingBookCategory.class, "cookingbookcategory", "cooking book categories") .user("cooking ?book ?categor(y|ies)") .name("Cooking Book Category") - .description("Represents the different categories of cooking recipes") + .description("Represents the different categories of cooking recipes.") .since("INSERT VERSION") ); Classes.registerClass(new EnumClassInfo<>(RecipeUtils.RecipeType.class, "recipetype", "recipe types") .user("recipe ?types?") .name("Recipe Type") - .description("Represents recipe types") + .description("Represents recipe types.") .since("INSERT VERSION") ); diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondDiscoveredRecipes.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondDiscoveredRecipes.java index 3ef2ffc6808..d8a0c53fcd9 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondDiscoveredRecipes.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondDiscoveredRecipes.java @@ -8,16 +8,18 @@ import ch.njol.skript.lang.Condition; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.NamespacedUtils; +import ch.njol.skript.bukkitutil.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; +import org.bukkit.Keyed; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; import org.bukkit.event.Event; +import org.bukkit.inventory.Recipe; import org.jetbrains.annotations.Nullable; @Name("Has Discovered Recipe") -@Description("Checks whether a player or players have discovered a recipe.") +@Description("Checks whether players have discovered a recipe.") @Examples({ "if player has discovered recipe \"custom_recipe\":", "\tgive player 1 diamond", @@ -30,20 +32,21 @@ public class CondDiscoveredRecipes extends Condition { static { Skript.registerCondition(CondDiscoveredRecipes.class, - "%players% (has|have) (discovered|unlocked) recipe[s] %strings%", - "%players% (hasn't|has not|haven't|have not) (discovered|unlocked) recipe[s] %strings%"); + "%players% (has|have) (discovered|unlocked) [the] recipe[s] [with [the] (key|id)[s]] %recipes%", + "%players% (has|have) (discovered|unlocked) [the] recipe[s] %recipes%", + "%players% (hasn't|has not|haven't|have not) (discovered|unlocked) [the] recipe[s] [with [the] (key|id)[s]] %strings%", + "%players% (hasn't|has not|haven't|have not) (discovered|unlocked) [the] recipe[s] %recipes%"); } private Expression players; - private Expression recipes; + private Expression recipes; @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { //noinspection unchecked players = (Expression) exprs[0]; - //noinspection unchecked - recipes = (Expression) exprs[1]; - setNegated(matchedPattern == 1); + recipes = exprs[1]; + setNegated(matchedPattern >= 2); return true; } @@ -52,10 +55,15 @@ public boolean check(Event event) { return players.check(event, player -> recipes.check(event, recipe -> { - NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe, false); - if (Bukkit.getRecipe(key) != null) - return player.hasDiscoveredRecipe(key); - return false; + if (recipe instanceof String recipeName) { + NamespacedKey key = NamespacedUtils.getNamespacedKey(recipeName, false); + if (Bukkit.getRecipe(key) != null) + return player.hasDiscoveredRecipe(key); + return isNegated(); + } else if (recipe instanceof Recipe actualRecipe && actualRecipe instanceof Keyed recipeKey) { + return player.hasDiscoveredRecipe(recipeKey.getKey()); + } + return isNegated(); } ) ); @@ -63,6 +71,6 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - return players.toString(event, debug) + (isNegated() ? "have not" : "have") + " found recipes " + recipes.toString(event, debug); + return players.toString(event, debug) + (isNegated() ? " have not" : " have") + " found recipes " + recipes.toString(event, debug); } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondRecipeExists.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondRecipeExists.java index ddc4968c0ba..1af4ad0d996 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondRecipeExists.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/CondRecipeExists.java @@ -8,7 +8,7 @@ import ch.njol.skript.lang.Condition; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.NamespacedUtils; +import ch.njol.skript.bukkitutil.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; import org.bukkit.event.Event; @@ -46,6 +46,6 @@ public boolean check(Event event) { @Override public String toString(@Nullable Event event, boolean debug) { - return "recipes " + recipes.toString(event, debug) + (isNegated() ? "does not" : "") + "exists"; + return "recipes " + recipes.toString(event, debug) + (isNegated() ? " do not" : "") + "exist"; } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffDiscoverRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffDiscoverRecipe.java index d0b19bf7f3b..9c44ee1a966 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffDiscoverRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffDiscoverRecipe.java @@ -8,16 +8,21 @@ import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.NamespacedUtils; +import ch.njol.skript.bukkitutil.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; +import org.bukkit.Keyed; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; import org.bukkit.event.Event; +import org.bukkit.inventory.Recipe; import org.jetbrains.annotations.Nullable; +import java.util.HashSet; +import java.util.Set; + @Name("Discover Recipe") -@Description("Discovers or forgets the recipes for the specified players.") +@Description("Makes the specified players discover or forget the recipes.") @Examples({ "make player discover recipe \"my_recipe\"", "make player undiscover recipe \"my_recipe\"", @@ -29,36 +34,50 @@ public class EffDiscoverRecipe extends Effect { static { Skript.registerEffect(EffDiscoverRecipe.class, - "make %players% (discover|unlock) recipe[s] %strings%", - "make %players% (undiscover|lock|forget) recipe[s] %strings%", - "(discover|unlock) recipe[s] %strings% for %players%", - "(undiscover|lock|forget) recipe[s] %strings% for %players%"); + "make %players% (discover|unlock) recipe[s] [with [the] (key|id)[s]] %strings%", + "make %players% (discover|unlock) recipe[s] %recipes%", + "make %players% (undiscover|lock|forget) recipe[s] [with [the] (key|id)[s]] %strings%", + "make %players% (undiscover|lock|forget) recipe[s] %recipes%", + "(discover|unlock) recipe[s] [with [the] (key|id)[s]] %strings% for %players%", + "(discover|unlock) recipe[s] %recipes% for %players%", + "(undiscover|lock|forget) recipe[s] [with [the] (key|id)[s]] %strings% for %players%", + "(undiscover|lock|forget) recipe[s] %recipes% for %players%"); } + private static final Set discoverPatterns = Set.of(0, 1, 4, 5); + private Expression players; - private Expression recipes; + private Expression recipes; private boolean isDiscover = false; @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - isDiscover = matchedPattern == 0 || matchedPattern == 2; - //noinspection unchecked - players = (Expression) (matchedPattern <= 1 ? exprs[0] : exprs[1]); + isDiscover = discoverPatterns.contains(matchedPattern); //noinspection unchecked - recipes = (Expression) (matchedPattern <= 1 ? exprs[1] : exprs[0]); + players = (Expression) (matchedPattern <= 3 ? exprs[0] : exprs[1]); + recipes = matchedPattern <= 3 ? exprs[1] : exprs[0]; return true; } @Override protected void execute(Event event) { - for (String recipe : recipes.getArray(event)) { - NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe, false); - if (Bukkit.getRecipe(key) != null) { + for (Object object : recipes.getArray(event)) { + NamespacedKey key = null; + if (object instanceof String recipeName) { + key = NamespacedUtils.getNamespacedKey(recipeName, false); + if (Bukkit.getRecipe(key) == null) + key = null; + + } else if (object instanceof Recipe actualRecipe && actualRecipe instanceof Keyed recipeKey) { + key = recipeKey.getKey(); + } + if (key != null) { for (Player player : players.getArray(event)) { - if (isDiscover) + if (isDiscover) { player.discoverRecipe(key); - else + } else { player.undiscoverRecipe(key); + } } } } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffRemoveRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffRemoveRecipe.java index 05e60e49740..8e31a684802 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffRemoveRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffRemoveRecipe.java @@ -8,17 +8,20 @@ import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.NamespacedUtils; +import ch.njol.skript.bukkitutil.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; +import org.bukkit.Keyed; import org.bukkit.NamespacedKey; import org.bukkit.event.Event; +import org.bukkit.inventory.Recipe; import org.jetbrains.annotations.Nullable; @Name("Remove Recipe") @Description({ "Remove the specified recipes from the server.", - "This will cause all players who have discovered the recipe to forget it." + "This will cause all players who have discovered the recipe to forget it.", + "Removing a minecraft recipe is not persistent across server restart." }) @Examples("remove the recipe \"my_recipe\" from the server") @Since("INSERT VERSION") @@ -26,23 +29,28 @@ public class EffRemoveRecipe extends Effect { static { Skript.registerEffect(EffRemoveRecipe.class, - "(remove|delete|clear) [the] recipe[s] [with [the] key] %strings% [from the server]"); + "(remove|delete|clear) [the] recipe[s] [with [the] (key|id)] %strings% [from [the] server]", + "(remove|delete|clear) [the] recipe[s] %recipes% [from [the] server]"); } - private Expression recipes; + private Expression recipes; @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - //noinspection unchecked - recipes = (Expression) exprs[0]; + recipes = exprs[0]; return true; } @Override protected void execute(Event event) { - for (String recipe : recipes.getArray(event)) { - NamespacedKey key = NamespacedUtils.getNamespacedKey(recipe, false); - if (Bukkit.getRecipe(key) != null) + for (Object object : recipes.getArray(event)) { + NamespacedKey key = null; + if (object instanceof String recipeName) { + key = NamespacedUtils.getNamespacedKey(recipeName, false); + } else if (object instanceof Recipe actualRecipe && actualRecipe instanceof Keyed recipeKey) { + key = recipeKey.getKey(); + } + if (key != null && Bukkit.getRecipe(key) != null) Bukkit.removeRecipe(key); } } @@ -51,4 +59,5 @@ protected void execute(Event event) { public String toString(@Nullable Event event, boolean debug) { return "remove recipes " + recipes.toString(event, debug) + " from the server"; } + } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffResetRecipes.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffResetRecipes.java index 7a91758a48e..6722d4f052c 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffResetRecipes.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EffResetRecipes.java @@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; @Name("Reset Recipes") -@Description("Resets the recipes to the Minecraft-provided defaults.") +@Description("Resets the recipes of the server; not including Minecraft defaults and datapacks.") @Examples("reset server recipes") @Since("INSERT VERSION") public class EffResetRecipes extends Effect { @@ -38,4 +38,5 @@ protected void execute(Event event) { public String toString(@Nullable Event event, boolean debug) { return "reset server recipes"; } + } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EvtDiscoverRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EvtDiscoverRecipe.java index a2d6f581ba1..ce3804cbb68 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EvtDiscoverRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/EvtDiscoverRecipe.java @@ -9,7 +9,7 @@ import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.NamespacedUtils; +import ch.njol.skript.bukkitutil.NamespacedUtils; import org.bukkit.event.Event; import org.bukkit.event.player.PlayerRecipeDiscoverEvent; import org.jetbrains.annotations.Nullable; @@ -54,4 +54,5 @@ public boolean check(Event event) { public String toString(@Nullable Event event, boolean debug) { return "player discovered recipes" + (recipes == null ? "" : " of " + recipes.toString(event, debug)); } + } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprAllRecipes.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprAllRecipes.java index f0c9ec945b0..10228d602fc 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprAllRecipes.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprAllRecipes.java @@ -26,12 +26,11 @@ @Name("All Recipes") @Description({ - "Retrieve all recipes registered in the server", + "Retrieve all recipes registered in the server. Including the options to:", "
    ", - "
  • You can retrieve all recipes of a recipe type.
  • ", - "
  • You can retrieve all recipes of an item, including custom items.
  • ", - "
  • You can retrieve all minecraft recipes.
  • ", - "
  • You can retrieve all custom recipes made by any and all plugins.
  • ", + "
  • Get only recipes provided by Minecraft or custom recipes
  • ", + "
  • Specific recipe types
  • ", + "
  • For specific items
  • ", "
" }) @Examples({ @@ -44,12 +43,12 @@ public class ExprAllRecipes extends SimpleExpression { static { Skript.registerExpression(ExprAllRecipes.class, Recipe.class, ExpressionType.SIMPLE, - "all [of the] recipes [items:for %-itemstacks/itemtypes%]", - "all [of the] (mc|minecraft|vanilla) recipes [items:for %-itemstacks/itemtypes%]", - "all [of the] custom recipes [items:for %-itemstacks/itemtypes%]", - "all [of the] %recipetype% [items:for %-itemstacks/itemtypes%]", - "all [of the] (mc|minecraft|vanilla) %recipetype% [items:for %-itemstacks/itemtypes%]", - "all [of the] custom %recipetype% [items:for %-itemstacks/itemtypes%]"); + "all [of the] recipes [for %-itemstacks/itemtypes%]", + "all [of the] (mc|minecraft|vanilla) recipes [for %-itemstacks/itemtypes%]", + "all [of the] custom recipes [for %-itemstacks/itemtypes%]", + "all [of the] %recipetype% [for %-itemstacks/itemtypes%]", + "all [of the] (mc|minecraft|vanilla) %recipetype% [for %-itemstacks/itemtypes%]", + "all [of the] custom %recipetype% [for %-itemstacks/itemtypes%]"); } private Expression recipeTypeExpr; @@ -58,9 +57,13 @@ public class ExprAllRecipes extends SimpleExpression { @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - //noinspection unchecked - recipeTypeExpr = matchedPattern >= 3 ? (Expression) exprs[0] : null; - itemExpr = parseResult.hasTag("items") ? exprs[1] : null; + if (matchedPattern <= 2 && exprs[0] != null) { + itemExpr = exprs[0]; + } else if (matchedPattern >= 3) { + //noinspection unchecked + recipeTypeExpr = (Expression) exprs[0]; + itemExpr = exprs[1] != null ? exprs[1] : null; + } getMinecraft = matchedPattern == 1 || matchedPattern == 4; getCustom = matchedPattern == 2 || matchedPattern == 5; return true; @@ -128,4 +131,5 @@ public String toString(@Nullable Event event, boolean debug) { (recipeTypeExpr != null ? " of type " + recipeTypeExpr.toString(event, debug) : "") + (itemExpr != null ? " for " + itemExpr.toString(event, debug) : ""); } + } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprGetRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprGetRecipe.java index 87b28162355..637519c4e03 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprGetRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprGetRecipe.java @@ -9,7 +9,7 @@ import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; -import ch.njol.skript.util.NamespacedUtils; +import ch.njol.skript.bukkitutil.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; @@ -31,7 +31,7 @@ public class ExprGetRecipe extends SimpleExpression { static { Skript.registerExpression(ExprGetRecipe.class, Recipe.class, ExpressionType.SIMPLE, - "[the] recipe[s] with [the] (key|id)[s] %strings%"); + "[the] recipe[s] [with [the] (key|id)[s]] %strings%"); } private Expression recipeNames; @@ -69,4 +69,5 @@ public Class getReturnType() { public String toString(@Nullable Event event, boolean debug) { return "recipes with the keys " + recipeNames.toString(event, debug); } + } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprLastRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprLastRecipe.java index 9ccfd5db136..299d028ccb6 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprLastRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprLastRecipe.java @@ -53,4 +53,5 @@ public Class getReturnType() { public String toString(@Nullable Event event, boolean debug) { return "the last registered recipe"; } + } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCategory.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCategory.java index 2269f95448d..786ac38c3a2 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCategory.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeCategory.java @@ -21,7 +21,7 @@ import org.jetbrains.annotations.Nullable; @Name("Recipe Category") -@Description("The recipe category of a Shaped, Shapeless, Cooking, Blasting, Furnace, Campfire and Smoking Recipe.") +@Description("The recipe category of a shaped, shapeless, blasting, furnace, campfire or smoking recipe.") @Examples({ "register a new shaped recipe with the key \"my_recipe\":", "\tset the recipe ingredients to diamond, air, diamond, air, emerald, air, diamond, air and diamond", @@ -53,10 +53,10 @@ public class ExprRecipeCategory extends PropertyExpression { private boolean isEvent = false; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { isCrafting = matchedPattern == 0; if (exprs[0] != null) { + //noinspection unchecked setExpr((Expression) exprs[0]); } else { if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeIngredients.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeIngredients.java index af14ec6bf4f..0fa0e99f401 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeIngredients.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeIngredients.java @@ -27,10 +27,10 @@ @Name("Recipe Ingredients") @Description({ - "The ingredients of a Shaped or Shapeless recipe", - "The ingredients of a row for a Shaped recipe", - "The input item of a Cooking, Blasting, Furnace, Campfire, Smoking and Stonecutting recipe", - "The base, template, addition items of a Smithing Transform and Smithing Trim recipe" + "The ingredients of a shaped or shapeless recipe.", + "The ingredients of a row for a shaped recipe.", + "The input item of a blasting, furnace, campfire, smoking and stonecutting recipe.", + "The base, template, addition items of a smithing transform and smithing trim recipe." }) @Examples({ "register a new shaped recipe with the key \"my_recipe\":", diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKey.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKey.java index 8de5561f310..7ec8c50f160 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKey.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKey.java @@ -19,7 +19,7 @@ import java.util.List; @Name("Recipe Name") -@Description("Get the namespacekey of a recipe") +@Description("Get the namespaced key of a recipe.") @Examples({ "loop all recipes:", "\tbroadcast the recipe key of loop-recipe", diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKeyConverter.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKeyConverter.java index 23f5434ab5b..e7574e60dd7 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKeyConverter.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeKeyConverter.java @@ -9,7 +9,7 @@ import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.skript.lang.util.SimpleExpression; -import ch.njol.skript.util.NamespacedUtils; +import ch.njol.skript.bukkitutil.NamespacedUtils; import ch.njol.util.Kleenean; import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; @@ -19,7 +19,7 @@ @Name("Recipe Key Converter") @Description({ "Converts a string to a valid key to be used with recipes.", - "'using minecraft namespace' will convert the string to a minecraft namespace key" + "'using minecraft namespace' will convert the string to a minecraft namespaced key." }) @Examples({ "send the converted recipe key from \"my_recipe\"", diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeResult.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeResult.java index ce93186b77d..f2366759799 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeResult.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeResult.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable; @Name("Recipe Result") -@Description("The result item for a recipe") +@Description("The result item for a recipe.") @Examples({ "register a new shaped recipe with the key \"my_recipe\":", "\tset the recipe ingredients of 1st row to diamond, air and diamond", @@ -37,9 +37,9 @@ public class ExprRecipeResult extends PropertyExpression { private boolean isEvent = false; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { if (exprs[0] != null) { + //noinspection unchecked setExpr((Expression) exprs[0]); } else { if (!getParser().isCurrentEvent(RegisterRecipeEvent.class)) { @@ -85,4 +85,5 @@ public Class getReturnType() { public String toString(@Nullable Event event, boolean debug) { return "the recipe result item of " + getExpr().toString(event, debug); } + } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeType.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeType.java index 77fca9efed6..29d8ad94844 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeType.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/ExprRecipeType.java @@ -16,7 +16,7 @@ import org.jetbrains.annotations.Nullable; @Name("Recipe Type") -@Description("Get the recipe type of a recipe") +@Description("Get the recipe type of a recipe.") @Examples({ "loop all recipes:", "\tbroadcast the recipe type of loop-recipe" @@ -31,8 +31,8 @@ public class ExprRecipeType extends PropertyExpression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + //noinspection unchecked setExpr((Expression) exprs[0]); return true; } @@ -51,4 +51,5 @@ public Class getReturnType() { public String toString(@Nullable Event event, boolean debug) { return "the recipe type of " + getExpr().toString(event, debug); } + } diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/RecipeEventValues.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/RecipeEventValues.java new file mode 100644 index 00000000000..6e2134af996 --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/RecipeEventValues.java @@ -0,0 +1,41 @@ +package org.skriptlang.skript.bukkit.recipes.elements; + +import ch.njol.skript.registrations.EventValues; +import ch.njol.skript.util.Getter; +import org.bukkit.Bukkit; +import org.bukkit.event.inventory.CraftItemEvent; +import org.bukkit.event.inventory.PrepareItemCraftEvent; +import org.bukkit.event.player.PlayerRecipeDiscoverEvent; +import org.bukkit.inventory.Recipe; +import org.jetbrains.annotations.Nullable; + +public class RecipeEventValues { + + public RecipeEventValues() {} + + static { + //PrepareItemCraftEvent + EventValues.registerEventValue(PrepareItemCraftEvent.class, Recipe.class, new Getter() { + @Override + public @Nullable Recipe get(PrepareItemCraftEvent event) { + return event.getRecipe(); + } + }, EventValues.TIME_NOW); + + //CraftItemEvent + EventValues.registerEventValue(CraftItemEvent.class, Recipe.class, new Getter() { + @Override + public @Nullable Recipe get(CraftItemEvent event) { + return event.getRecipe(); + } + }, EventValues.TIME_NOW); + + // PlayerRecipeDiscoverEvent + EventValues.registerEventValue(PlayerRecipeDiscoverEvent.class, Recipe.class, new Getter() { + @Override + public @Nullable Recipe get(PlayerRecipeDiscoverEvent event) { + return Bukkit.getRecipe(event.getRecipe()); + } + }, EventValues.TIME_NOW); + } +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/SecRegisterRecipe.java b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/SecRegisterRecipe.java index 7cecb29dec8..441aaa2c480 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/SecRegisterRecipe.java +++ b/src/main/java/org/skriptlang/skript/bukkit/recipes/elements/SecRegisterRecipe.java @@ -9,7 +9,7 @@ import ch.njol.skript.doc.Since; import ch.njol.skript.lang.*; import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.util.NamespacedUtils; +import ch.njol.skript.bukkitutil.NamespacedUtils; import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent; import ch.njol.skript.util.RecipeUtils.RecipeType; import ch.njol.skript.util.RecipeUtils.RegisterRecipeEvent.*; @@ -30,15 +30,14 @@ @Name("Register Recipe") @Description({ "Create a custom recipe for any of the following types:", - "Shaped, Shapeless, Blasting, Furnace, Campfire, Smoking, Smithing Transform, Smithing Trim or Stonecutting", + "Shaped, Shapeless, Blasting, Furnace, Campfire, Smoking, Smithing Transform, Smithing Trim or Stonecutting.", "NOTES:", - "All recipes except Smithing Trim require a 'result item'", - "Shaped and Shapeless Ingredients allows custom items only on Paper", - "Shaped and Shapeless have a maximum of 9 and minimum requirement of 2 ingredients", - "Blasting, Furnace, Campfire and Smoking all fall under Cooking Recipe Type", - "Groups only apply to Shaped, Shapeless and Cooking Recipes", - "Category only applies to Shaped, Shapeless and Cooking Recipes", - "You can not create a Cooking, Crafting and Complex Recipe type." + "All recipes except Smithing Trim require a 'result item'.", + "Blasting, Furnace, Campfire and Smoking all fall under Cooking Recipe Type.", + "Groups only apply to Shaped, Shapeless and Cooking Recipes.", + "Category only applies to Shaped, Shapeless and Cooking Recipes.", + "You can not create a Cooking, Crafting and Complex Recipe type.", + "Custom recipes are not persistent across server restart." }) @Examples({ "register a new shaped recipe with the name \"my_recipe\":", @@ -79,7 +78,8 @@ @Since("INSERT VERSION") public class SecRegisterRecipe extends Section { - private static final boolean RUNNING_1_20 = Skript.isRunningMinecraft(1, 20, 0); + private static final boolean SUPPORT_SMITHING = !Skript.isRunningMinecraft(1, 20, 0); + public static Recipe lastRegistered; static { Skript.registerSection(SecRegisterRecipe.class, "(register|create) [a] [new] %*recipetype% with [the] (key|id) %string%"); @@ -90,16 +90,15 @@ public class SecRegisterRecipe extends Section { private Trigger trigger; private Node thisNode; private String thisScript; - public static Recipe lastRegistered; @Override - @SuppressWarnings("unchecked") public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult, SectionNode sectionNode, List triggerItems) { + //noinspection unchecked providedType = ((Literal) exprs[0]).getSingle(); if (providedType == RecipeType.COOKING || providedType == RecipeType.CRAFTING || providedType == RecipeType.COMPLEX) { Skript.error("You can not register a '" + providedType + "' recipe type."); return false; - } else if (providedType == RecipeType.SMITHING && RUNNING_1_20) { + } else if (providedType == RecipeType.SMITHING && SUPPORT_SMITHING) { Skript.error("You can not register a 'smithing' recipe type on MC version 1.20+"); return false; } @@ -144,8 +143,8 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye case SHAPED, SHAPELESS -> { if (recipeEvent instanceof CraftingRecipeEvent craftingEvent) { RecipeChoice[] ingredients = craftingEvent.getIngredients(); - if (ingredients.length < 2 || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < 2) { - customError("You must have at least 2 ingredients when registering a '" + recipeType + "' recipe."); + if (ingredients.length == 0 || Arrays.stream(ingredients).filter(Objects::nonNull).toArray().length < 2) { + customError("You must have at least 1 ingredient when registering a '" + recipeType + "' recipe."); return super.walk(event, false); } String group = craftingEvent.getGroup();