diff --git a/config.yml b/config.yml index 08a7f07..f4aea28 100644 --- a/config.yml +++ b/config.yml @@ -61,7 +61,9 @@ version: '1.2' # -- Recipes for Potions -- # name: Different names for bad/normal/good (Formatting codes possible: such as &6) -# ingredients: List of material/amount +# ingredients: List of 'material or id,data/amount' (Item-ids instead of material are deprecated by bukkit and may not work in the future!) +# A list of materials can be found here: http://jd.bukkit.org/beta/apidocs/org/bukkit/Material.html +# You can specify a data value, omitting it will ignore the data value of the added ingredient # cookingtime: Time in real minutes ingredients have to boil # distillruns: How often it has to be distilled for full alcohol (0=without distilling) # wood: Wood of the barrel 0=any 1=Birch 2=Oak 3=Jungle 4=Spruce @@ -183,6 +185,7 @@ recipes: # cooked: EVERY possible ingredient and the names for the originating potions after fermenting: +# [Example] MATERIAL_or_id: Name after cooking cooked: WHEAT: Fermented wheat diff --git a/src/com/dre/brewery/BCauldron.java b/src/com/dre/brewery/BCauldron.java index 894bdb5..c5d35bf 100644 --- a/src/com/dre/brewery/BCauldron.java +++ b/src/com/dre/brewery/BCauldron.java @@ -20,7 +20,7 @@ public class BCauldron { private int state = 1; private boolean someRemoved = false; - public BCauldron(Block block, Material ingredient) { + public BCauldron(Block block, ItemStack ingredient) { this.block = block; add(ingredient); bcauldrons.add(this); @@ -48,11 +48,12 @@ public class BCauldron { } // add an ingredient to the cauldron - public void add(Material ingredient) { + public void add(ItemStack ingredient) { if (someRemoved) { ingredients = ingredients.clone(); someRemoved = false; } + ingredient = new ItemStack(ingredient.getType(), 1, ingredient.getDurability()); ingredients.add(ingredient); block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0); if (state > 1) { @@ -71,7 +72,7 @@ public class BCauldron { } // get cauldron from block and add given ingredient - public static boolean ingredientAdd(Block block, Material ingredient) { + public static boolean ingredientAdd(Block block, ItemStack ingredient) { // if not empty if (getFillLevel(block) != 0) { BCauldron bcauldron = get(block); diff --git a/src/com/dre/brewery/BIngredients.java b/src/com/dre/brewery/BIngredients.java index ea25664..f7d71ce 100644 --- a/src/com/dre/brewery/BIngredients.java +++ b/src/com/dre/brewery/BIngredients.java @@ -17,7 +17,8 @@ public class BIngredients { private static int lastId = 0; private int id; - private Map ingredients = new HashMap(); + private ArrayList ingredients = new ArrayList(); + private Map materials = new HashMap(); // Merged List Of ingredients that doesnt consider Durability private int cookedTime; // Represents ingredients in Cauldron, Brew @@ -28,20 +29,35 @@ public class BIngredients { } // Load from File - public BIngredients(Map ingredients, int cookedTime) { + public BIngredients(ArrayList ingredients, int cookedTime) { this.ingredients = ingredients; this.cookedTime = cookedTime; this.id = lastId; lastId++; + + for (ItemStack item : ingredients) { + addMaterial(item); + } } // Add an ingredient to this - public void add(Material ingredient) { - if (ingredients.containsKey(ingredient)) { - int newAmount = ingredients.get(ingredient) + 1; - ingredients.put(ingredient, newAmount); + public void add(ItemStack ingredient) { + addMaterial(ingredient); + for (ItemStack item : ingredients) { + if (item.isSimilar(ingredient)) { + item.setAmount(item.getAmount() + ingredient.getAmount()); + return; + } + } + ingredients.add(ingredient); + } + + private void addMaterial(ItemStack ingredient) { + if (materials.containsKey(ingredient.getType())) { + int newAmount = materials.get(ingredient.getType()) + ingredient.getAmount(); + materials.put(ingredient.getType(), newAmount); } else { - this.ingredients.put(ingredient, 1); + materials.put(ingredient.getType(), ingredient.getAmount()); } } @@ -76,10 +92,10 @@ public class BIngredients { cookedName = P.p.languageReader.get("Brew_ThickBrew"); potion.setDurability(Brew.PotionColor.BLUE.getColorId(false)); } else { - for (Material ingredient : ingredients.keySet()) { + for (Material ingredient : materials.keySet()) { if (cookedNames.containsKey(ingredient)) { // if more than half of the ingredients is of one kind - if (ingredients.get(ingredient) > (getIngredientsCount() / 2)) { + if (materials.get(ingredient) > (getIngredientsCount() / 2)) { cookedName = cookedNames.get(ingredient); potion.setDurability(Brew.PotionColor.CYAN.getColorId(true)); } @@ -104,8 +120,8 @@ public class BIngredients { // returns amount of ingredients private int getIngredientsCount() { int count = 0; - for (int value : ingredients.values()) { - count += value; + for (ItemStack item : ingredients) { + count += item.getAmount(); } return count; } @@ -211,9 +227,21 @@ public class BIngredients { // when ingredients are not complete return -1; } - for (Material ingredient : ingredients.keySet()) { - count = ingredients.get(ingredient); - if (recipe.amountOf(ingredient) == 0) { + ArrayList mergedChecked = new ArrayList(); + for (ItemStack ingredient : ingredients) { + if (mergedChecked.contains(ingredient.getType())) { + // This ingredient type was already checked as part of a merged material + continue; + } + int amountInRecipe = recipe.amountOf(ingredient); + // If we dont consider durability for this ingredient, check the merged material + if (recipe.hasExactData(ingredient)) { + count = ingredient.getAmount(); + } else { + mergedChecked.add(ingredient.getType()); + count = materials.get(ingredient.getType()); + } + if (amountInRecipe == 0) { // this ingredient doesnt belong into the recipe if (count > (getIngredientsCount() / 2)) { // when more than half of the ingredients dont fit into the @@ -231,7 +259,7 @@ public class BIngredients { } } // calculate the quality - quality -= ((float) Math.abs(count - recipe.amountOf(ingredient)) / recipe.allowedCountDiff(recipe.amountOf(ingredient))) * 10.0; + quality -= ((float) Math.abs(count - amountInRecipe) / recipe.allowedCountDiff(amountInRecipe)) * 10.0; } if (quality >= 0) { return Math.round(quality); @@ -290,7 +318,8 @@ public class BIngredients { // Creates a copy ingredients public BIngredients clone() { BIngredients copy = new BIngredients(); - copy.ingredients.putAll(ingredients); + copy.ingredients.addAll(ingredients); + copy.materials.putAll(materials); copy.cookedTime = cookedTime; return copy; } @@ -308,8 +337,9 @@ public class BIngredients { //convert the ingredient Material to String public Map serializeIngredients() { Map mats = new HashMap(); - for (Map.Entry entry : ingredients.entrySet()) { - mats.put(entry.getKey().name(), entry.getValue()); + for (ItemStack item : ingredients) { + String mat = item.getType().name() + "," + item.getDurability(); + mats.put(mat, item.getAmount()); } return mats; } diff --git a/src/com/dre/brewery/BRecipe.java b/src/com/dre/brewery/BRecipe.java index 2d5467a..571daaa 100644 --- a/src/com/dre/brewery/BRecipe.java +++ b/src/com/dre/brewery/BRecipe.java @@ -1,16 +1,18 @@ package com.dre.brewery; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.HashMap; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; public class BRecipe { private String[] name; - private Map ingredients = new HashMap();// material and amount + private ArrayList ingredients = new ArrayList();// material and amount private int cookingTime;// time to cook in cauldron private int distillruns;// runs through the brewer private byte wood;// type of wood the barrel has to consist of @@ -38,9 +40,23 @@ public class BRecipe { for (String item : ingredientsList) { String[] ingredParts = item.split("/"); if (ingredParts.length == 2) { - Material mat = Material.matchMaterial(ingredParts[0]); + String[] matParts; + if (ingredParts[0].contains(",")) { + matParts = ingredParts[0].split(","); + } else if (ingredParts[0].contains(":")) { + matParts = ingredParts[0].split(":"); + } else if (ingredParts[0].contains(";")) { + matParts = ingredParts[0].split(";"); + } else { + matParts = ingredParts[0].split("\\."); + } + Material mat = Material.matchMaterial(matParts[0]); if (mat != null) { - this.ingredients.put(Material.matchMaterial(ingredParts[0]), P.p.parseInt(ingredParts[1])); + ItemStack stack = new ItemStack(mat, P.p.parseInt(ingredParts[1]), (short) -1); + if (matParts.length == 2) { + stack.setDurability((short) P.p.parseInt(matParts[1])); + } + this.ingredients.add(stack); } else { P.p.errorLog("Unknown Material: " + ingredParts[0]); this.ingredients = null; @@ -124,19 +140,39 @@ public class BRecipe { return age != 0; } - // true if given map misses an ingredient - public boolean isMissingIngredients(Map map) { - if (map.size() < ingredients.size()) { + // true if given list misses an ingredient + public boolean isMissingIngredients(List list) { + if (list.size() < ingredients.size()) { return true; } - for (Material ingredient : ingredients.keySet()) { - if (!map.containsKey(ingredient)) { - return true; + for (ItemStack ingredient : ingredients) { + for (ItemStack used : list) { + if (!ingredientsMatch(used, ingredient)) { + return true; + } } } return false; } + // Returns true if this ingredient cares about durability + public boolean hasExactData(ItemStack item) { + for (ItemStack ingredient : ingredients) { + if (ingredient.getType().equals(item.getType())) { + return ingredient.getDurability() != -1; + } + } + return true; + } + + // Returns true if this item matches the item from a recipe + public static boolean ingredientsMatch(ItemStack usedItem, ItemStack recipeItem) { + if (!recipeItem.getType().equals(usedItem.getType())) { + return false; + } + return recipeItem.getDurability() == -1 || recipeItem.getDurability() == usedItem.getDurability(); + } + // true if name and ingredients are correct public boolean isValid() { return (name != null && ingredients != null && !ingredients.isEmpty()); @@ -146,9 +182,11 @@ public class BRecipe { // Getter // how many of a specific ingredient in the recipe - public int amountOf(Material material) { - if (ingredients.containsKey(material)) { - return ingredients.get(material); + public int amountOf(ItemStack item) { + for (ItemStack ingredient : ingredients) { + if (ingredientsMatch(item, ingredient)) { + return ingredient.getAmount(); + } } return 0; } diff --git a/src/com/dre/brewery/ConfigUpdater.java b/src/com/dre/brewery/ConfigUpdater.java index ffd3427..fbde79e 100644 --- a/src/com/dre/brewery/ConfigUpdater.java +++ b/src/com/dre/brewery/ConfigUpdater.java @@ -375,4 +375,76 @@ public class ConfigUpdater { } } + // Update de from 1.2 to 1.3 + private void update12de() { + updateVersion("1.3"); + + // Add the Example to the Cooked Section + int index = indexOfStart("# cooked:"); + if (index != -1) { + addLines(index, "# [Beispiel] MATERIAL_oder_id: Name nach Gähren"); + } + + // Add new ingredients description + String replacedLine = "# ingredients: Auflistung von 'Material oder ID,Data/Anzahl' (Item-ids anstatt Material werden von Bukkit nicht mehr unterstützt und funktionieren möglicherweise in Zukunft nicht mehr!)"; + String[] lines = new String[] { + "# Eine Liste von allen Materialien kann hier gefunden werden: http://jd.bukkit.org/beta/apidocs/org/bukkit/Material.html", + "# Es kann ein Data-Wert angegeben werden, weglassen ignoriert diesen beim hinzufügen einer Zutat" + }; + index = indexOfStart("# ingredients:"); + if (index != -1) { + setLine(index, replacedLine); + addLines(index, lines); + } else { + index = indexOfStart("# name:"); + if (index != -1) { + addLines(index, lines); + addLines(index, replacedLine); + } else { + index = indexOfStart("# -- Rezepte für Getränke --"); + if (index != -1) { + addLines(index, lines); + addLines(index, "", replacedLine); + } + } + } + + } + + // Update en from 1.2 to 1.3 + private void update12en() { + updateVersion("1.3"); + + // Add the Example to the Cooked Section + int index = indexOfStart("# cooked:"); + if (index != -1) { + addLines(index, "# [Example] MATERIAL_or_id: Name after cooking"); + } + + // Add new ingredients description + String replacedLine = "# ingredients: List of 'material or id,data/amount' (Item-ids instead of material are deprecated by bukkit and may not work in the future!)"; + String[] lines = new String[] { + "# A list of materials can be found here: http://jd.bukkit.org/beta/apidocs/org/bukkit/Material.html", + "# You can specify a data value, omitting it will ignore the data value of the added ingredient" + }; + index = indexOfStart("# ingredients:"); + if (index != -1) { + setLine(index, replacedLine); + addLines(index, lines); + } else { + index = indexOfStart("# name:"); + if (index != -1) { + addLines(index, lines); + addLines(index, replacedLine); + } else { + index = indexOfStart("# -- Recipes for Potions --"); + if (index != -1) { + addLines(index, lines); + addLines(index, "", replacedLine); + } + } + } + + } + } diff --git a/src/com/dre/brewery/P.java b/src/com/dre/brewery/P.java index 9e38827..2b93db5 100644 --- a/src/com/dre/brewery/P.java +++ b/src/com/dre/brewery/P.java @@ -11,6 +11,7 @@ import java.util.UUID; import java.util.logging.Level; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -302,10 +303,7 @@ public class P extends JavaPlugin { ConfigurationSection matSection = section.getConfigurationSection(id + ".mats"); if (matSection != null) { // matSection has all the materials + amount as Integers - Map ingredients = new HashMap(); - for (String mat : matSection.getKeys(false)) { - ingredients.put(Material.getMaterial(mat), matSection.getInt(mat)); - } + ArrayList ingredients = deserializeIngredients(matSection); ingMap.put(id, new BIngredients(ingredients, section.getInt(id + ".cookedTime", 0))); } else { errorLog("Ingredient id: '" + id + "' incomplete in data.yml"); @@ -369,6 +367,19 @@ public class P extends JavaPlugin { } } + public ArrayList deserializeIngredients(ConfigurationSection matSection) { + ArrayList ingredients = new ArrayList(); + for (String mat : matSection.getKeys(false)) { + String[] matSplit = mat.split(","); + ItemStack item = new ItemStack(Material.getMaterial(matSplit[0]), matSection.getInt(mat)); + if (matSplit.length == 2) { + item.setDurability((short) P.p.parseInt(matSplit[1])); + } + ingredients.add(item); + } + return ingredients; + } + // returns Ingredients by id from the specified ingMap public BIngredients getIngredients(Map ingMap, String id) { if (!ingMap.isEmpty()) { @@ -383,11 +394,7 @@ public class P extends JavaPlugin { // loads BIngredients from an ingredient section public BIngredients loadIngredients(ConfigurationSection section) { if (section != null) { - Map ingredients = new HashMap(); - for (String mat : section.getKeys(false)) { - ingredients.put(Material.getMaterial(mat), section.getInt(mat)); - } - return new BIngredients(ingredients, 0); + return new BIngredients(deserializeIngredients(section), 0); } else { errorLog("Cauldron is missing Ingredient Section"); } diff --git a/src/com/dre/brewery/listeners/PlayerListener.java b/src/com/dre/brewery/listeners/PlayerListener.java index 313e35f..61dc7bc 100644 --- a/src/com/dre/brewery/listeners/PlayerListener.java +++ b/src/com/dre/brewery/listeners/PlayerListener.java @@ -74,7 +74,7 @@ public class PlayerListener implements Listener { // contitions } else if (BIngredients.possibleIngredients.contains(materialInHand)) { if (player.hasPermission("brewery.cauldron.insert")) { - if (BCauldron.ingredientAdd(clickedBlock, materialInHand)) { + if (BCauldron.ingredientAdd(clickedBlock, item)) { boolean isBucket = item.getType().equals(Material.WATER_BUCKET) || item.getType().equals(Material.LAVA_BUCKET) || item.getType().equals(Material.MILK_BUCKET);