From b5e06f34f60578c237474f8f7ab0ede4d59d862b Mon Sep 17 00:00:00 2001 From: jameslfc19 Date: Fri, 15 May 2020 20:20:14 +0100 Subject: [PATCH] AutoCraft additions Not finished. --- .../minecraft/chests/crafting/Crafting.java | 149 +++++++++++++----- .../chests/crafting/UserShapedRecipe.java | 81 ++++++++++ .../chests/listeners/InventoryListener.java | 55 +++++-- 3 files changed, 229 insertions(+), 56 deletions(-) create mode 100644 src/main/java/com/jamesdpeters/minecraft/chests/crafting/UserShapedRecipe.java diff --git a/src/main/java/com/jamesdpeters/minecraft/chests/crafting/Crafting.java b/src/main/java/com/jamesdpeters/minecraft/chests/crafting/Crafting.java index d5f3bf4..07b0f83 100644 --- a/src/main/java/com/jamesdpeters/minecraft/chests/crafting/Crafting.java +++ b/src/main/java/com/jamesdpeters/minecraft/chests/crafting/Crafting.java @@ -4,18 +4,17 @@ import com.jamesdpeters.minecraft.chests.interfaces.VirtualCraftingHolder; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.CraftingInventory; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.Recipe; import org.bukkit.inventory.RecipeChoice; import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapelessRecipe; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -40,9 +39,9 @@ public class Crafting { for(ShapelessRecipe shapelessRecipe : shapelessRecipes) { if (matchesShapeless(shapelessRecipe.getChoiceList(), craftingTable)) return shapelessRecipe.getResult(); } -// for(ShapedRecipe shapedRecipe : shapedRecipes) { -// if (matchesShaped(shapedRecipe, craftingTable)) return shapedRecipe.getResult(); -// } + for(ShapedRecipe shapedRecipe : shapedRecipes) { + if (matchesShaped(shapedRecipe, craftingTable)) return shapedRecipe.getResult(); + } return null; } @@ -68,43 +67,15 @@ public class Crafting { } private static boolean matchesShaped(ShapedRecipe shape, List items) { - String[] map = shape.getShape(); - Map choices = shape.getChoiceMap(); - for (Map.Entry entry : choices.entrySet()) { - if (entry.getValue() == null) - continue; + //validateItemList(items); + if(shape.getResult().getType().equals(Material.WHITE_WOOL)){ + Bukkit.broadcastMessage(items.toString()); + Bukkit.broadcastMessage(Arrays.toString(shape.getShape())); + Bukkit.broadcastMessage(shape.getChoiceMap().toString()); } - int index = 0; - - boolean test = true; - - for (String s : map) { - if (!test) - break; - for (Character c : s.toCharArray()) { - RecipeChoice currentChoice = choices.get(c); - if (currentChoice == null) { - if (index < items.size() && items.get(index) != null - && items.get(index).getType() != Material.AIR) { - test = false; - break; - } - index++; - continue; - } - if (index >= items.size()) { - test = false; - break; - } - if (!currentChoice.test(items.get(index))) { - test = false; - break; - } - index++; - } - } - - return test; + UserShapedRecipe userShapedRecipe = getUserShapedRecipe(items); + if(userShapedRecipe == null) return false; + return userShapedRecipe.matchesRecipe(shape); } public static void updateCrafting(Inventory inventory){ @@ -118,4 +89,98 @@ public class Crafting { Inventory craft = new VirtualCraftingHolder().getInventory(); player.openInventory(craft); } + + private static void validateItemList(List itemStacks){ + if(itemStacks.size() >=9) { + int rowsToRemove = 0; + int colsToRemove = 0; + + for (int row = 0; row < 3; row++) { + boolean removeRow = true; + for (int col = 0; col < 3; col++) { + if (itemStacks.get((row * 3) + col) != null) { + removeRow = false; + break; + } + } + if (removeRow) rowsToRemove++; + } + + for (int col = 0; col < 3; col++) { + boolean removeCol = true; + for (int row = 0; row < 3; row++) { + if (itemStacks.get((row * 3) + col) != null) { + removeCol = false; + break; + } + } + if (removeCol) colsToRemove++; + } + + + Bukkit.broadcastMessage("Rows to remove: "+rowsToRemove+" Cols: "+colsToRemove); + + int index = 1; + Iterator iter = itemStacks.iterator(); + while (iter.hasNext()) { + iter.next(); + int row = (index) / 3; + int column = (index % 3) - 1; + Bukkit.broadcastMessage("row: "+row+" col: "+column); + if ((row < rowsToRemove) || (column < colsToRemove)) iter.remove(); + index++; + } + + Bukkit.broadcastMessage("Items: "+itemStacks.toString()); + + //itemStacks.replaceAll(itemStack -> itemStack == null ? new ItemStack(Material.AIR) : itemStack); + } + } + + private static UserShapedRecipe getUserShapedRecipe(List itemStacks){ + if(itemStacks.size() < 9) return null; + Character[] chars = new Character[]{'a','b','c','d','e','f','g','h','i'}; + int rowsToRemove = 0; + int colsToRemove = 0; + + for (int row = 0; row < 3; row++) { + boolean removeRow = true; + for (int col = 0; col < 3; col++) { + if (itemStacks.get((row * 3) + col) != null) { + removeRow = false; + break; + } + } + if (removeRow) rowsToRemove++; + } + + for (int col = 0; col < 3; col++) { + boolean removeCol = true; + for (int row = 0; row < 3; row++) { + if (itemStacks.get((row * 3) + col) != null) { + removeCol = false; + break; + } + } + if (removeCol) colsToRemove++; + } + + int index = 0; + String[] shape = new String[3-rowsToRemove]; + Map itemMap = new HashMap<>(); + for(int row=rowsToRemove; row < 3; row++){ + StringBuilder shapeRow = new StringBuilder(); + for(int col=colsToRemove; col < 3; col++){ + shapeRow.append(chars[index]); + itemMap.put(chars[index],itemStacks.get((row*3)+col)); + } + shape[row-rowsToRemove] = shapeRow.toString(); + } + + UserShapedRecipe recipe = new UserShapedRecipe(); + recipe.setIngredientMap(itemMap); + recipe.setShape(shape); + + return recipe; + } } diff --git a/src/main/java/com/jamesdpeters/minecraft/chests/crafting/UserShapedRecipe.java b/src/main/java/com/jamesdpeters/minecraft/chests/crafting/UserShapedRecipe.java new file mode 100644 index 0000000..46915c9 --- /dev/null +++ b/src/main/java/com/jamesdpeters/minecraft/chests/crafting/UserShapedRecipe.java @@ -0,0 +1,81 @@ +package com.jamesdpeters.minecraft.chests.crafting; + +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.ShapedRecipe; + +import java.util.Arrays; +import java.util.Map; + +public class UserShapedRecipe { + + String[] shape; + Map ingredientMap; + + public UserShapedRecipe(){ + + } + + public String[] getShape() { + return shape; + } + + public UserShapedRecipe setShape(String[] shape) { + this.shape = shape; + return this; + } + + public Map getIngredientMap() { + return ingredientMap; + } + + public UserShapedRecipe setIngredientMap(Map ingredientMap) { + this.ingredientMap = ingredientMap; + return this; + } + + public boolean matchesRecipe(ShapedRecipe recipe){ + // convert both shapes and ingredient maps to common ItemStack array. + ItemStack[] matrix1 = shapeToMatrix(getShape(), getIngredientMap()); + ItemStack[] matrix2 = shapeToMatrix(recipe.getShape(), recipe.getIngredientMap()); + + if(!Arrays.equals(matrix1, matrix2)) // compare arrays and if they don't match run another check with one shape mirrored. + { + mirrorMatrix(matrix1); + + return Arrays.equals(matrix1, matrix2); + } + + return true; // ingredients match + } + + private static ItemStack[] shapeToMatrix(String[] shape, Map map) + { + ItemStack[] matrix = new ItemStack[9]; + int slot = 0; + + for(int r = 0; r < shape.length; r++) + { + for(char col : shape[r].toCharArray()) + { + matrix[slot] = map.get(col); + slot++; + } + + slot = ((r + 1) * 3); + } + + return matrix; + } + + private static void mirrorMatrix(ItemStack[] matrix) + { + ItemStack tmp; + + for(int r = 0; r < 3; r++) + { + tmp = matrix[(r * 3)]; + matrix[(r * 3)] = matrix[(r * 3) + 2]; + matrix[(r * 3) + 2] = tmp; + } + } +} diff --git a/src/main/java/com/jamesdpeters/minecraft/chests/listeners/InventoryListener.java b/src/main/java/com/jamesdpeters/minecraft/chests/listeners/InventoryListener.java index 3330df2..dd1e4e8 100644 --- a/src/main/java/com/jamesdpeters/minecraft/chests/listeners/InventoryListener.java +++ b/src/main/java/com/jamesdpeters/minecraft/chests/listeners/InventoryListener.java @@ -19,6 +19,7 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.CraftingInventory; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; public class InventoryListener implements Listener { @@ -80,37 +81,63 @@ public class InventoryListener implements Listener { public void inventoryDragEvent(InventoryDragEvent event){ Inventory inventory = event.getInventory(); if(inventory.getHolder() instanceof VirtualCraftingHolder){ - event.setCancelled(true); + Player p = (Player) event.getWhoClicked(); + Bukkit.broadcastMessage(event.getRawSlots().toString()); + for(int slot : event.getRawSlots()) { + if(slot >= p.getOpenInventory().getTopInventory().getSize()) + continue; + + Bukkit.broadcastMessage("Drag! "+slot+" cursor: "+event.getOldCursor()); + setCraftingItem(event.getInventory(),slot,event.getOldCursor()); + event.setCancelled(true); + } } } @EventHandler(priority = EventPriority.HIGHEST) public void onCraftingPlayerUpdate(InventoryClickEvent event){ - Inventory inventory = event.getClickedInventory(); - if(inventory != null && event.getInventory().getHolder() instanceof VirtualCraftingHolder){ - if(event.getClick() == ClickType.DOUBLE_CLICK){ - if(event.getClickedInventory() == event.getView().getBottomInventory()){ - event.getInventory().setItem(event.getSlot(),event.getCurrentItem()); - event.setCurrentItem(null); - } + Player player = (Player) event.getWhoClicked(); + + if(event.getView().getTopInventory().getHolder() instanceof VirtualCraftingHolder){ + Bukkit.broadcastMessage("Click: "+event.getAction()); + + if(event.getAction() == InventoryAction.COLLECT_TO_CURSOR || + event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY || + event.getAction() == InventoryAction.NOTHING) { + Bukkit.broadcastMessage("Cancelled!"); event.setCancelled(true); + player.updateInventory(); + return; } - if(event.getClickedInventory() == event.getView().getTopInventory()){ + + if(event.getClickedInventory() == player.getOpenInventory().getTopInventory()){ + Bukkit.broadcastMessage("Clicked: "+event.getSlot()); + if(event.getSlot() == 0) event.setCancelled(true); if(event.getSlot() >= 1 && event.getSlot() <= 9){ - Bukkit.broadcastMessage("Click: "+event.getSlot()); - event.getClickedInventory().setItem(event.getSlot(),event.getCurrentItem()); + setCraftingItem(event.getInventory(),event.getSlot(),event.getCursor()); + event.setCancelled(true); + craftingUpdate(event); } - event.setCancelled(true); - craftingUpdate(event); } } } + private void setCraftingItem(Inventory inventory, int slot, ItemStack cursor){ + ItemStack clone = null; + if(cursor != null){ + clone = cursor.clone(); + clone.setAmount(1); + } + inventory.setItem(slot,clone); + } + private void craftingUpdate(InventoryInteractEvent event){ InventoryHolder holder = event.getInventory().getHolder(); if(holder instanceof VirtualCraftingHolder){ - Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, () -> Crafting.updateCrafting(holder.getInventory()),1); + Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, () -> { + Crafting.updateCrafting(holder.getInventory()); + },1); } }