Skip to content

Commit

Permalink
crafts item event: amount context for shaped recipes
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed May 30, 2020
1 parent a8f034e commit d0cb83d
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
Expand Up @@ -4,15 +4,19 @@
import com.denizenscript.denizen.objects.InventoryTag;
import com.denizenscript.denizen.objects.ItemTag;
import com.denizenscript.denizen.objects.PlayerTag;
import com.denizenscript.denizen.utilities.debugging.Debug;
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
import com.denizenscript.denizen.events.BukkitScriptEvent;
import com.denizenscript.denizen.utilities.inventory.RecipeHelper;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.scripts.ScriptEntryData;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
Expand All @@ -32,6 +36,7 @@ public class PlayerCraftsItemScriptEvent extends BukkitScriptEvent implements Li
// @Context
// <context.inventory> returns the InventoryTag of the crafting inventory.
// <context.item> returns the ItemTag to be crafted.
// <context.amount> returns the amount of the item that will be crafted (usually 1, except when shift clicked. Can be above 64).
// <context.recipe> returns a ListTag of ItemTags in the recipe.
//
// @Determine
Expand Down Expand Up @@ -95,6 +100,13 @@ public ObjectTag getContext(String name) {
else if (name.equals("inventory")) {
return InventoryTag.mirrorBukkitInventory(event.getInventory());
}
else if (name.equals("amount")) {
int amount = event.getRecipe().getResult().getAmount();
if (event.getClick() == ClickType.SHIFT_LEFT) {
amount *= RecipeHelper.getMaximumOutputQuantity(event.getRecipe(), event.getInventory());
}
return new ElementTag(amount);
}
else if (name.equals("recipe")) {
ListTag recipe = new ListTag();
for (ItemStack itemStack : event.getInventory().getMatrix()) {
Expand Down
@@ -0,0 +1,89 @@
package com.denizenscript.denizen.utilities.inventory;

import org.bukkit.inventory.*;

import java.util.Arrays;
import java.util.Map;

public class RecipeHelper {

public static class ShapeHelper {
public ShapeHelper(ShapedRecipe recipe) {
choiceMap = recipe.getChoiceMap();
shapeText = recipe.getShape();
int len = shapeText.length;
while (len > 0 && shapeText[len - 1].isEmpty()) {
len--;
}
while (len > 0 && shapeText[0].isEmpty()) {
shapeText = Arrays.copyOfRange(shapeText, 1, len);
len--;
}
height = len;
width = 0;
for (int i = 0; i < len; i++) {
width = Math.max(width, shapeText[i].length());
}
if (height <= 0 || width <= 0) {
throw new RuntimeException("ShapedRecipe malformed.");
}
}

public int width;
public int height;
public String[] shapeText;
public Map<Character, RecipeChoice> choiceMap;
}

public static int tryRecipeMatch(ItemStack[] matrix, int matrixWidth, ShapeHelper shape, int offsetX, int offsetY) {
int max = 64;
for (int shapeX = 0; shapeX < shape.width; shapeX++) {
for (int shapeY = 0; shapeY < shape.height; shapeY++) {
if (shape.shapeText[shapeY].length() <= shapeX) {
continue;
}
int x = offsetX + shapeX;
int y = offsetY + shapeY;
int matrixIndex = x + y * matrixWidth;
ItemStack matrixItem = matrix[matrixIndex];
RecipeChoice choices = shape.choiceMap.get(shape.shapeText[shapeY].charAt(shapeX));
if (choices != null) {
if (matrixItem == null || !choices.test(matrixItem)) {
return 0;
}
max = Math.min(max, matrixItem.getAmount());
}
}
}
return max;
}

public static int getShapedQuantity(CraftingInventory inventory, ShapeHelper shape) {
ItemStack[] matrix = inventory.getMatrix();
int matrixWidth = matrix.length == 9 ? 3 : 2;
int canMoveX = matrixWidth - shape.width;
int canMoveY = matrixWidth - shape.height;
for (int offsetX = 0; offsetX < canMoveX; offsetX++) {
for (int offsetY = 0; offsetY <= canMoveY; offsetY++) {
int result = tryRecipeMatch(matrix, matrixWidth, shape, offsetX, offsetY);
if (result > 0) {
return result;
}
}
}
return 0;
}

public static int getMaximumOutputQuantity(Recipe recipe, CraftingInventory inventory) {
if (recipe instanceof ShapedRecipe) {
return getShapedQuantity(inventory, new ShapeHelper((ShapedRecipe) recipe));
}
else if (recipe instanceof ShapelessRecipe) {
// TODO
return 1;
}
else {
return 1;
}
}
}

0 comments on commit d0cb83d

Please sign in to comment.