From 23a9f2340ac27c0eb3574bc746a6d8ab08d82930 Mon Sep 17 00:00:00 2001 From: Sn0wStorm Date: Sun, 28 Apr 2013 23:57:41 +0200 Subject: [PATCH] Added Brew, Distilling, Barrel --- config.yml | 55 +++- src/com/dre/brewery/BCauldron.java | 39 ++- src/com/dre/brewery/BIngredients.java | 268 +++++++++++++----- src/com/dre/brewery/BRecipe.java | 145 ++++++++-- src/com/dre/brewery/Barrel.java | 257 +++++++++++++++++ src/com/dre/brewery/Brew.java | 223 +++++++++++++++ src/com/dre/brewery/P.java | 16 +- .../dre/brewery/listeners/BlockListener.java | 39 ++- .../dre/brewery/listeners/EntityListener.java | 23 ++ .../dre/brewery/listeners/PlayerListener.java | 79 ++++-- 10 files changed, 985 insertions(+), 159 deletions(-) create mode 100644 src/com/dre/brewery/Brew.java create mode 100644 src/com/dre/brewery/listeners/EntityListener.java diff --git a/config.yml b/config.yml index 1c64afe..dd66316 100644 --- a/config.yml +++ b/config.yml @@ -1,23 +1,26 @@ # name: versch. Namen für schlecht/mittel/gut # ingredients: material/anzahl -# cookingtime: Zeit in minuten die die zutaten kochen müssen (o=kein kochen) -# destillruns: wie oft destilliert werden muss (0=ohne Destillieren) -# filter: filter in der destille (leer wenn egal) -# destillpotion: trank, der in der destille beigemischt wird (leer für wasser) -# wood: Holz des Fasses 0=ohne fass 1=Birch 2=Oak 3=Jungle 4=Pine +# cookingtime: Zeit in echtminuten die die zutaten kochen müssen +# distillruns: wie oft destilliert werden muss 0-10 (0=ohne Destillieren) +# wood: Holz des Fasses 0=alle Holzsorten 1=Birch 2=Oak 3=Jungle 4=Pine +# age: Zeit in Minecraft Tagen, die das getränk im fass reifen muss 0=kein reifen +# color: Farbe des Getränks nach destillieren/reifen # difficulty: 1-10 genauigkeit der Einhaltung der Vorgaben # alcohol: Alkoholgehalt 0-100 in Vol.% bei perfektem Getränk -#cooked: Auflistung ALLER möglichen Zutaten und die daraus entstehenden Tranknahmen (leer für undef.) +#cooked: Auflistung ALLER möglichen Zutaten und die daraus entstehenden Tranknamen: (leer für undef.) recipes: 1: name: Ranziges Weißbier/Weißbier/Feines Weißbier ingredients: - - WHEAT/6 + - WHEAT/3 cookingtime: 8 + distillruns: 0 wood: 1 + age: 2 + color: BRIGHT_GREY difficulty: 1 alcohol: 5 2: @@ -25,15 +28,21 @@ recipes: ingredients: - WHEAT/6 cookingtime: 8 - wood: 2 + distillruns: 0 + wood: 0 + age: 3 + color: ORANGE difficulty: 1 - alcohol: 5 + alcohol: 6 3: name: Ranziges Dunkelbier/Dunkelbier/Feines Dunkelbier ingredients: - WHEAT/6 cookingtime: 8 + distillruns: 0 wood: 4 + age: 8 + color: BLACK difficulty: 2 alcohol: 7 4: @@ -41,30 +50,46 @@ recipes: ingredients: - SUGAR_CANE/6 cookingtime: 3 + distillruns: 0 wood: 2 + age: 4 + color: ORANGE difficulty: 2 - alcohol: 8 + alcohol: 10 5: name: Apfelmet/Süßer Apfelmet/Goldensüßer Apfelmet ingredients: - SUGAR_CANE/6 - APPLE/2 cookingtime: 4 - destillruns: 0 + distillruns: 0 wood: 2 + age: 4 + COLOR: ORANGE difficulty: 4 - alcohol: 10 + alcohol: 12 6: name: Rum/Goldener Rum/Perfekter Rum ingredients: - SUGAR_CANE/14 cookingtime: 5 - destillruns: 2 + distillruns: 2 wood: 2 + age: 14 + color: DARK_RED difficulty: 6 alcohol: 60 + 7: + name: Kartoffelsuppe + ingredients: + - POTATO_ITEM/5 + - LONG_GRASS/3 + cookingtime: 3 + color: PINK + difficulty: 1 cooked: - WHEAT: Getreidemaische + WHEAT: Getreideferment SUGAR_CANE: Zuckersud APPLE: Apfelmost - POTATO_ITEM: Kartoffelmaische \ No newline at end of file + POTATO_ITEM: Kartoffelmaische + LONG_GRASS: Kräuterbrühe \ No newline at end of file diff --git a/src/com/dre/brewery/BCauldron.java b/src/com/dre/brewery/BCauldron.java index 3642780..2768dfa 100644 --- a/src/com/dre/brewery/BCauldron.java +++ b/src/com/dre/brewery/BCauldron.java @@ -2,30 +2,15 @@ package com.dre.brewery; import java.util.concurrent.CopyOnWriteArrayList; -//import java.util.List; -//import java.util.ArrayList; - -import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.entity.Player; -import org.bukkit.entity.HumanEntity; import org.bukkit.Material; -import org.bukkit.material.Cauldron; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.inventory.ItemStack; -//import org.bukkit.inventory.meta.ItemMeta; -//import org.bukkit.inventory.meta.PotionMeta; -//import org.bukkit.potion.Potion; -//import org.bukkit.potion.PotionEffect; -//import org.bukkit.potion.PotionEffectType; -import org.bukkit.World; import org.bukkit.Effect; -//import org.bukkit.block.BrewingStand; - import com.dre.brewery.BIngredients; -import com.dre.brewery.P; - public class BCauldron { public static CopyOnWriteArrayList bcauldrons=new CopyOnWriteArrayList(); @@ -34,7 +19,6 @@ public class BCauldron { private int state; public BCauldron(Block block,Material ingredient){ - P.p.log("aaand we got a fresh cauldron"); this.block = block; this.state = 1; this.ingredients = new BIngredients(); @@ -44,10 +28,17 @@ public class BCauldron { public void onUpdate(){ - state++;//wie lange es schon kocht + //Check if fire still alive + if(block.getRelative(BlockFace.DOWN).getType() == Material.FIRE || + block.getRelative(BlockFace.DOWN).getType() == Material.STATIONARY_LAVA || + block.getRelative(BlockFace.DOWN).getType() == Material.LAVA){ + //add a minute to cooking time + state++; + } } + //add an ingredient to the cauldron public void add(Material ingredient){ ingredients.add(ingredient); block.getWorld().playEffect(block.getLocation(),Effect.EXTINGUISH,0); @@ -56,11 +47,12 @@ public class BCauldron { } } + //get cauldron from block and add given ingredient public static boolean ingredientAdd(Block block,Material ingredient){ + //if not empty if(block.getData() != 0){ for(BCauldron bcauldron:bcauldrons){ if(bcauldron.block.equals(block)){ - P.p.log("is existing Cauldron"); bcauldron.add(ingredient); return true; } @@ -71,12 +63,15 @@ public class BCauldron { return false; } + //fills players bottle with cooked brew public static boolean fill(Player player,Block block){ for(BCauldron bcauldron:bcauldrons){ if(bcauldron.block.equals(block)){ ItemStack potion = bcauldron.ingredients.cook(bcauldron.state); if(potion != null){ - giveItem(player,potion);//Bukkit Bug, but could also just use deprecated updateInventory() + //Bukkit Bug, inventory not updating while in event so this will delay the give + //but could also just use deprecated updateInventory() + giveItem(player,potion); //player.getInventory().addItem(potion); //player.getInventory().updateInventory(); if(block.getData() > 3){ @@ -94,14 +89,16 @@ public class BCauldron { return false; } + //reset to normal cauldron public static void remove(Block block){ for(BCauldron bcauldron:bcauldrons){ if(bcauldron.block.equals(block)){ - bcauldrons.remove(bcauldron);//reset to normal cauldron (when refilling it) + bcauldrons.remove(bcauldron); } } } + //bukkit bug not updating the inventory while executing event, have to schedule the give public static void giveItem(final Player player,final ItemStack item){ P.p.getServer().getScheduler().runTaskLater(P.p, new Runnable() { public void run() { diff --git a/src/com/dre/brewery/BIngredients.java b/src/com/dre/brewery/BIngredients.java index 893d673..a1ea63a 100644 --- a/src/com/dre/brewery/BIngredients.java +++ b/src/com/dre/brewery/BIngredients.java @@ -1,22 +1,17 @@ package com.dre.brewery; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.ArrayList; import java.util.Map; import java.util.HashMap; import org.bukkit.inventory.ItemStack; import org.bukkit.Material; -import org.bukkit.potion.Potion; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionType; import org.bukkit.potion.PotionEffectType; import org.bukkit.inventory.meta.PotionMeta; -//import java.util.List; - import com.dre.brewery.P; import com.dre.brewery.BRecipe; +import com.dre.brewery.Brew; @@ -26,110 +21,245 @@ public class BIngredients { public static Map cookedNames=new HashMap(); private Map ingredients=new HashMap(); - //private int quality = 10; - private String cookedName; private int cookedTime; - private PotionEffect cookedEffect = (PotionEffectType.CONFUSION).createEffect(200,0);//vorrübergehend + //Represents ingredients in Cauldron, Brew + //Init a new BIngredients public BIngredients(){ } + //Init a copy of BIngredients with existing values + public BIngredients(Map ingredients,int cookedTime){ + this.ingredients.putAll(ingredients); + this.cookedTime = cookedTime; + } + + //Add an ingredient to this public void add(Material ingredient){ if(ingredients.containsKey(ingredient)){ int newAmount = ingredients.get(ingredient) + 1; ingredients.put(ingredient,newAmount); - P.p.log("Now "+newAmount+" of this in here"); } else { this.ingredients.put(ingredient,1); } } + //returns an Potion item with cooked ingredients public ItemStack cook(int state){ - for(BRecipe recipe:recipes){ - if(recipe.isCookingOnly()){ - //Nur Kochen - } - } + ItemStack potion = new ItemStack(Material.POTION); + PotionMeta potionMeta = (PotionMeta) potion.getItemMeta(); + + //cookedTime is always time in minutes, state may differ with number of ticks + cookedTime = state; + String cookedName = null; + BRecipe cookRecipe = getCookRecipe(); + + int uid = Brew.generateUID(); + + if(cookRecipe != null){ + //Potion is best with cooking only, can still be destilled, etc. + int quality =(int) Math.round((getIngredientQuality(cookRecipe) + getCookingQuality(cookRecipe)) / 2.0); + P.p.log("cooked potion has Quality: "+quality); + new Brew(uid,quality,new BIngredients(ingredients,cookedTime)); + + cookedName = cookRecipe.getName(quality); + potion.setDurability(Brew.PotionColor.valueOf(cookRecipe.getColor()).getColorId(false)); - if(state == 0){//TESTING sonst 1 - cookedName = "Schlammiger Sud";//not cooked long enough } else { - for(Material ingredient:ingredients.keySet()){ - if(cookedNames.containsKey(ingredient)){ - P.p.log("Trank aus "+getIngredientsAmount()+" Zutaten"); - if(ingredients.get(ingredient) > (getIngredientsAmount() / 2)){//if more than half of the ingredients is of one kind - cookedName = cookedNames.get(ingredient); + //new base potion + new Brew(uid,new BIngredients(ingredients,cookedTime)); + + if(state == 0){//TESTING sonst 1 + cookedName = "Schlammiger Sud"; + potion.setDurability(Brew.PotionColor.BLUE.getColorId(false)); + } else { + for(Material ingredient:ingredients.keySet()){ + if(cookedNames.containsKey(ingredient)){ + //if more than half of the ingredients is of one kind + if(ingredients.get(ingredient) > (getIngredientsCount() / 2)){ + cookedName = cookedNames.get(ingredient); + potion.setDurability(Brew.PotionColor.CYAN.getColorId(true)); + } } } } } if(cookedName == null){ + //if no name could be found cookedName = "Undefinierbarer Sud"; + potion.setDurability(Brew.PotionColor.CYAN.getColorId(true)); } - cookedTime = state * 2; - - ItemStack potion = new ItemStack(Material.POTION); - //new Potion(PotionType.getByEffect(PotionEffectType.SLOW)).toItemStack(1); - - PotionMeta potionMeta = (PotionMeta) potion.getItemMeta(); potionMeta.setDisplayName(cookedName); - //List lore = new ArrayList(); - //lore.add("gesöff vom feinsten"); - //potionMeta.setLore(lore); - potionMeta.clearCustomEffects(); - potionMeta.addCustomEffect(cookedEffect,true);//Add our own effects, overriding existing ones + //This effect stores the UID in its Duration + potionMeta.addCustomEffect((PotionEffectType.REGENERATION).createEffect((uid * 4),0),true); potion.setItemMeta(potionMeta); - return potion; + } + //returns amount of ingredients + private int getIngredientsCount(){ + int count = 0; + for(int value:ingredients.values()){ + count += value; + } + return count; + } - /* while(i < possibleIngredients.size()){ - //Plain drinks - if(getAmountOf(possibleIngredients.get(i)) > (ingredients.size() / 2)){ - cookedPotion = new Potion(PotionType.getByEffect(PotionEffectType.SLOW)); - P.p.log("making a plain potion"); - return cookedPotion; - } + //best recipe for current state of potion, STILL not always returns the correct one... + public BRecipe getBestRecipe(byte wood,float time){ + float quality = 0; + int ingredientQuality = 0; + int cookingQuality = 0; + int woodQuality = 0; + int ageQuality = 0; + BRecipe bestRecipe = null; + for(BRecipe recipe:recipes){ + ingredientQuality = getIngredientQuality(recipe); + cookingQuality = getCookingQuality(recipe); - //Special Recipies - //Shroom Wodka - if((getAmountOf(possibleIngredients.get(2)) * 3) >= (getAmountOf(badIngredients.get(0)) * 2)){ - if((getAmountOf(possibleIngredients.get(2)) * 2) <= (getAmountOf(badIngredients.get(0)) * 3)){ - //Type Shroom wodka + if(ingredientQuality > -1){ + P.p.log("Ingredient Quality: "+ingredientQuality+" Cooking Quality: "+cookingQuality+" Wood Quality: "+getWoodQuality(recipe,wood)+" age Quality: "+getAgeQuality(recipe,time)+" for "+recipe.getName(5)); + if(recipe.needsToAge()){ + //needs riping in barrel + ageQuality = getAgeQuality(recipe,time); + woodQuality = getWoodQuality(recipe,wood); + + //is this recipe better than the previous best? + if((((float)ingredientQuality + cookingQuality + woodQuality + ageQuality) / 4) > quality){ + quality = ((float)ingredientQuality + cookingQuality + woodQuality + ageQuality) / 4; + bestRecipe = recipe; + } + } else { + //calculate quality without age and barrel + if((((float)ingredientQuality + cookingQuality) / 2) > quality){ + quality = ((float)ingredientQuality + cookingQuality) / 2; + bestRecipe = recipe; + } } } - - - - i++; - }*/ - } - - private int getIngredientsAmount(){ - int amount = 0; - for(int value:ingredients.values()){ - amount += value; } - return amount; + + P.p.log("best recipe: "+bestRecipe.getName(5)+" has Quality= "+quality); + return bestRecipe; } + //returns recipe that is cooking only and matches the ingredients and cooking time + public BRecipe getCookRecipe(){ + BRecipe bestRecipe = getBestRecipe((byte)0,0); - - - - /*private int getAmountOf(Material ingredient){ - int amount = 0; - for(Material bingredient:ingredients){ - if(bingredient == ingredient){ - amount++; + //Check if best recipe is cooking only + if(bestRecipe != null){ + if(bestRecipe.isCookingOnly()){ + return bestRecipe; } } - P.p.log("Amount="+amount); - return amount; - }*/ + return null; + } + + //returns the currently best matching recipe for distilling for the ingredients and cooking time + public BRecipe getdistillRecipe(){ + BRecipe bestRecipe = getBestRecipe((byte)0,0); + + //Check if best recipe needs to be destilled + if(bestRecipe != null){ + if(bestRecipe.getDistillRuns() != 0){ + return bestRecipe; + } + } + return null; + } + + //returns currently best matching recipe for ingredients, cooking- and ageingtime + public BRecipe getAgeRecipe(byte wood,float time){ + BRecipe bestRecipe = getBestRecipe(wood,time); + + if(bestRecipe != null){ + if(bestRecipe.needsToAge()){ + return bestRecipe; + } + } + return null; + } + + //returns the quality of the ingredients conditioning given recipe, -1 if no recipe is near them + public int getIngredientQuality(BRecipe recipe){ + float quality = 10; + int count = 0; + int badStuff = 0; + if(recipe.isMissingIngredients(ingredients)){ + //when ingredients are not complete + return -1; + } + for(Material ingredient:ingredients.keySet()){ + count = ingredients.get(ingredient); + if(recipe.amountOf(ingredient) == 0){ + //this ingredient doesnt belong into the recipe + if(count > (getIngredientsCount() / 2)){ + //when more than half of the ingredients dont fit into the recipe + return -1; + } + badStuff++; + if(badStuff < ingredients.size()){ + //when there are other ingredients + quality -= count * 2; + continue; + } else { + //ingredients dont fit at all + return -1; + } + } + //calculate the quality + quality -= (((float) Math.abs(count - recipe.amountOf(ingredient)) / recipe.allowedCountDiff(recipe.amountOf(ingredient))) * 10.0); + } + /* if(quality != 0){ + quality /= ingredients.size(); + }*/ + if(quality >= 0){ + return Math.round(quality); + } + return -1; + } + + //returns the quality regarding the cooking-time conditioning given Recipe + public int getCookingQuality(BRecipe recipe){ + int quality = 10 - (int) Math.round(((float) Math.abs(cookedTime - recipe.getCookingTime()) / recipe.allowedTimeDiff(recipe.getCookingTime())) * 10.0); + + if(quality > 0){ + return quality; + } + return 0; + } + + //returns the quality regarding the barrel wood conditioning given Recipe + public int getWoodQuality(BRecipe recipe,byte wood){ + if(recipe.getWood() == 0x8){ + //type of wood doesnt matter + return 10; + } + int quality = 10 - (int) Math.round(recipe.getWoodDiff(wood) * recipe.getDifficulty()); + + if(quality > 0){ + return quality; + } + return 0; + } + + //returns the quality regarding the ageing time conditioning given Recipe + public int getAgeQuality(BRecipe recipe,float time){ + int quality = 10 - (int) Math.round( Math.abs(time - recipe.getAge()) * ((float)recipe.getDifficulty() / 2) ); + + if(quality > 0){ + return quality; + } + return 0; + } + + + + } \ No newline at end of file diff --git a/src/com/dre/brewery/BRecipe.java b/src/com/dre/brewery/BRecipe.java index fe9743e..73c458f 100644 --- a/src/com/dre/brewery/BRecipe.java +++ b/src/com/dre/brewery/BRecipe.java @@ -1,28 +1,22 @@ package com.dre.brewery; -//import java.util.concurrent.CopyOnWriteArrayList; import java.util.List; import java.util.Map; import java.util.HashMap; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.Material; -//import org.bukkit.potion.Potion; -//import org.bukkit.potion.PotionType; -//import org.bukkit.potion.PotionEffectType; -import com.dre.brewery.P; -import com.dre.brewery.BIngredients; public class BRecipe { - private String[] name;// = new String[3]; + private String[] name; private Map ingredients = new HashMap();//material and amount private int cookingTime;//time to cook in cauldron - private int destillruns;//runs through the brewer - private Material filter;//filter on top of the brewer - private Material destillPotion;//potion to add to custom ones in brewer + private int distillruns;//runs through the brewer private int wood;//type of wood the barrel has to consist of + private int age;//time in minecraft days for the potions to age in barrels + private String color;//color of the destilled/finished potion private int difficulty;//difficulty to brew the potion, how exact the instruction has to be followed private int alcohol;//Vol% of alcohol in perfect potion @@ -34,7 +28,6 @@ public class BRecipe { this.name = new String[1]; this.name[0] = name[0]; } - P.p.log("nameLength="+name.length); List ingredientsList = configSectionRecipes.getStringList(recipeId+".ingredients"); for(String item:ingredientsList){ String[] ingredParts = item.split("/"); @@ -42,25 +35,141 @@ public class BRecipe { this.ingredients.put(Material.getMaterial(ingredParts[0]),P.p.parseInt(ingredParts[1])); } this.cookingTime = configSectionRecipes.getInt(recipeId+".cookingtime"); - this.destillruns = configSectionRecipes.getInt(recipeId+".destillruns"); - this.filter = Material.getMaterial(configSectionRecipes.getString(recipeId+".filter")); - this.destillPotion = Material.getMaterial(configSectionRecipes.getString(recipeId+".destillpotion")); - if(destillPotion == null){ - destillPotion = Material.POTION; - } + this.distillruns = configSectionRecipes.getInt(recipeId+".distillruns"); this.wood = configSectionRecipes.getInt(recipeId+".wood"); + this.age = configSectionRecipes.getInt(recipeId+".age"); + this.color = configSectionRecipes.getString(recipeId+".color"); this.difficulty = configSectionRecipes.getInt(recipeId+".difficulty"); this.alcohol = configSectionRecipes.getInt(recipeId+".alcohol"); } + //allowed deviation to the recipes count of ingredients at the given difficulty + public int allowedCountDiff(int count){ + int allowedCountDiff = Math.round((float)((11.0 - difficulty) * (count / 10.0))); + + if(allowedCountDiff == 0){ + return 1; + } + return allowedCountDiff; + } + + //allowed deviation to the recipes cooking-time at the given difficulty + public int allowedTimeDiff(int time){ + int allowedTimeDiff = Math.round((float)((11.0 - difficulty) * (time / 10.0))); + + while(allowedTimeDiff >= time){ + allowedTimeDiff -= 1; + } + if(allowedTimeDiff == 0){ + return 1; + } + return allowedTimeDiff; + } + + //difference between given and recipe-wanted woodtype + public float getWoodDiff(byte wood){ + int woodType = 0; + if(wood == 0x0){ + woodType = 2; + }else if(wood == 0x1){ + woodType = 4; + } else if(wood == 0x2){ + woodType = 1; + } else if(wood == 0x3){ + woodType = 3; + } + return Math.abs(woodType - wood); + } + public boolean isCookingOnly(){ - if(wood == 0 && destillruns == 0){ + if(age == 0 && distillruns == 0){ return true; } return false; } + public boolean needsToAge(){ + if(age == 0){ + return false; + } + return true; + } + + //true if given map misses an ingredient + public boolean isMissingIngredients(Map map){ + if(map.size() < ingredients.size()){ + return true; + } + for(Material ingredient:ingredients.keySet()){ + if(!map.containsKey(ingredient)){ + return true; + } + } + return false; + } + + + + //Getter + + //how many of a specific ingredient in the recipe + public int amountOf(Material material){ + if(ingredients.containsKey(material)){ + return ingredients.get(material); + } + return 0; + } + + //name that fits the quality + public String getName(int quality){ + if(name.length > 2){ + if(quality <= 3){ + return name[0]; + } else if(quality <= 7){ + return name[1]; + } else { + return name[2]; + } + } else { + return name[0]; + } + } + + public int getCookingTime(){ + return cookingTime; + } + + public int getDistillRuns(){ + return distillruns; + } + + public String getColor(){ + return color.toUpperCase(); + } + + //get the woodtype in blockData-byte + public byte getWood(){ + if(wood == 1){ + return 0x2; + } else if(wood == 2){ + return 0x0; + } else if(wood == 3){ + return 0x3; + } else if(wood == 4){ + return 0x1; + } + return 0x8; + } + + public float getAge(){ + return (float) age; + } + + public int getDifficulty(){ + return difficulty; + } + } \ No newline at end of file diff --git a/src/com/dre/brewery/Barrel.java b/src/com/dre/brewery/Barrel.java index 01f0d09..671d765 100644 --- a/src/com/dre/brewery/Barrel.java +++ b/src/com/dre/brewery/Barrel.java @@ -1,5 +1,262 @@ package com.dre.brewery; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.bukkit.entity.Player; +import org.bukkit.block.Block; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + public class Barrel { +public static CopyOnWriteArrayList barrels = new CopyOnWriteArrayList(); + +//private CopyOnWriteArrayList brews = new CopyOnWriteArrayList(); +private Block spigot; +private Inventory inventory; +private float time; + + public Barrel(Block spigot){ + this.spigot = spigot; + } + + public static void onUpdate(){ + Block broken; + for(Barrel barrel:barrels){ + broken = getBrokenBlock(barrel.spigot); + //remove the barrel if it was destroyed + if(broken != null){ + barrel.remove(broken); + } else { + //Minecraft day is 20 min, so add 1/20 to the time every minute + barrel.time += 1.0/20.0; + } + } + } + + //player opens the barrel + public void open(Player player){ + if(inventory == null){ + inventory = org.bukkit.Bukkit.createInventory(null, 54, "Fass"); + } else { + //if nobody has the inventory opened + if(inventory.getViewers().isEmpty()){ + //if inventory contains potions + if(inventory.contains(373)){ + for(ItemStack item:inventory.getContents()){ + if(item != null){ + if(item.getTypeId() == 373){ + if(item.hasItemMeta()){ + Brew.age(item,time,getWood()); + } + } + } + } + } + } + } + //reset barreltime, potions have new age + time = 0; + player.openInventory(inventory); + } + + public static Barrel get(Block spigot){ + for(Barrel barrel:barrels){ + if(barrel.spigot.equals(spigot)){ + return barrel; + } + } + return null; + } + + //creates a new Barrel out of a sign + public static boolean create(Block block){ + Block spigot = getSpigotOfSign(block); + if(getBrokenBlock(spigot) == null){ + if(get(spigot) == null){ + barrels.add(new Barrel(spigot)); + return true; + } + } + return false; + } + + //removes a barrel, throwing included potions to the ground + public void remove(Block broken){ + if(inventory != null){ + ItemStack[] items = inventory.getContents(); + for(ItemStack item:items){ + if(item != null){ + if(item.getTypeId() == 373){ + //Brew before throwing + Brew.age(item,time,getWood()); + } + //broken is the block that was broken, throw them there! + if(broken != null){ + broken.getLocation().getWorld().dropItem(broken.getLocation(), item); + } else { + spigot.getLocation().getWorld().dropItem(spigot.getLocation(), item); + } + } + } + } + barrels.remove(this); + } + + //direction of the barrel from the spigot + public static int getDirection(Block spigot){ + int direction = 0;//1=x+ 2=x- 3=z+ 4=z- + if(spigot.getRelative(0,0,1).getTypeId() == 5){ + direction = 3; + } + if(spigot.getRelative(0,0,-1).getTypeId() == 5){ + if(direction == 0){ + direction = 4; + } else { + return 0; + } + } + if(spigot.getRelative(1,0,0).getTypeId() == 5){ + if(direction == 0){ + direction = 1; + } else { + return 0; + } + } + if(spigot.getRelative(-1,0,0).getTypeId() == 5){ + if(direction == 0){ + direction = 2; + } else { + return 0; + } + } + return direction; + } + + //woodtype of the block the spigot is attached to + public byte getWood(){ + int direction = getDirection(this.spigot);//1=x+ 2=x- 3=z+ 4=z- + Block wood = null; + if(direction == 0){ + return 0; + } else if (direction == 1){ + wood = this.spigot.getRelative(1,0,0); + } else if (direction == 2){ + wood = this.spigot.getRelative(-1,0,0); + } else if (direction == 3){ + wood = this.spigot.getRelative(0,0,1); + } else { + wood = this.spigot.getRelative(0,0,-1); + } + if(wood.getTypeId() == 5){ + return wood.getData(); + } + return 0; + } + + //returns null if Barrel is correctly placed, block that is missing when not + //the barrel needs to be formed correctly + public static Block getBrokenBlock(Block spigot){ + if(spigot == null){ + return spigot; + } + int direction = getDirection(spigot);//1=x+ 2=x- 3=z+ 4=z- + if(direction == 0){ + return spigot; + } + int startX = 0; + int startZ = 0; + int endX; + int endZ; + + if (direction == 1){ + startX = 1; + endX = startX + 3; + startZ = -1; + endZ = 1; + } else if (direction == 2){ + startX = -4; + endX = startX + 3; + startZ = -1; + endZ = 1; + } else if (direction == 3){ + startX = -1; + endX = 1; + startZ = 1; + endZ = startZ + 3; + } else { + startX = -1; + endX = 1; + startZ = -4; + endZ = startZ + 3; + } + + int typeId; + int x = startX; + int y = 0; + int z = startZ; + //P.p.log("startX="+startX+" startZ="+startZ+" endX="+endX+" endZ="+endZ+" direction="+direction); + while(y <= 2){ + while(x <= endX){ + while(z <= endZ){ + typeId = spigot.getRelative(x,y,z).getTypeId(); + //spigot.getRelative(x,y,z).setTypeId(1); + if(direction == 1 || direction == 2){ + if(y == 1 && z == 0){ + if(x == -2 || x == -3 || x == 2 || x == 3){ + z++; + continue; + } else if (x == -1 || x == -4 || x == 1 || x == 4){ + if(typeId != 0){ + z++; + continue; + } + } + } + } else { + if(y == 1 && x == 0){ + if(z == -2 || z == -3 || z == 2 || z == 3){ + z++; + continue; + } else if (z == -1 || z == -4 || z == 1 || z == 4){ + if(typeId != 0){ + z++; + continue; + } + } + } + } + if(typeId == 5 || typeId == 53 || typeId == 134 || typeId == 135 || typeId == 136){ + z++; + continue; + } else { + return spigot.getRelative(x,y,z); + } + } + z = startZ; + x++; + } + z = startZ; + x = startX; + y++; + } + return null; + + } + + //returns the fence above/below a block + public static Block getSpigotOfSign(Block block){ + + int y = -2; + while(y <= 1){ + //Fence and Netherfence + if(block.getRelative(0,y,0).getTypeId() == 85 || + block.getRelative(0,y,0).getTypeId() == 113){ + return (block.getRelative(0,y,0)); + } + y++; + } + return null; + } + } diff --git a/src/com/dre/brewery/Brew.java b/src/com/dre/brewery/Brew.java new file mode 100644 index 0000000..5623400 --- /dev/null +++ b/src/com/dre/brewery/Brew.java @@ -0,0 +1,223 @@ +package com.dre.brewery; + +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; + +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.inventory.BrewerInventory; + +import com.dre.brewery.BIngredients; + +import com.dre.brewery.P; + +public class Brew { + + public static Map potions=new HashMap(); + + //represents the liquid in the brewed Potions + + private BIngredients ingredients; + private int quality; + private int distillRuns; + private float ageTime; + + public Brew(int uid,BIngredients ingredients){ + this.ingredients = ingredients; + potions.put(uid,this); + } + + //quality already set + public Brew(int uid,int quality,BIngredients ingredients){ + this.ingredients = ingredients; + this.quality = quality; + potions.put(uid,this); + } + + //remove potion from map (drinking, despawning, should be more!) + public static void remove(ItemStack item){ + PotionMeta meta = (PotionMeta) item.getItemMeta(); + Brew brew = get(meta); + if(brew != null){ + potions.remove(brew); + } + } + + + //generate an UID + public static int generateUID(){ + int uid = -2; + while(potions.containsKey(uid)){ + uid -= 1; + } + return uid; + } + + //returns a Brew by its UID + public static Brew getByUID(int uid){ + if(uid < -1){ + if(!potions.containsKey(uid)){ + P.p.log("Database failure! unable to find UID "+uid+" of a custom Potion in the db!"); + return null;//throw some exception? + } + } else { + return null; + } + return potions.get(uid); + + } + + //returns a Brew by PotionMeta + public static Brew get(PotionMeta meta){ + if(meta.hasCustomEffects()){ + for(PotionEffect effect:meta.getCustomEffects()){ + if(effect.getType().equals(PotionEffectType.REGENERATION)){ + return getByUID(effect.getDuration()); + } + } + } + return null; + } + + //returns a Brew by ItemStack + /*public static Brew get(ItemStack item){ + if(item.getTypeId() == 373){ + PotionMeta potionMeta = (PotionMeta) item.getItemMeta(); + return get(potionMeta); + } + return null; + }*/ + + + + + //Distilling section --------------- + + + //distill all custom potions in the brewer + public static void distillAll(BrewerInventory inv,Integer[] contents){ + int slot = 0; + while (slot < 3){ + if(contents[slot] == 1){ + distillSlot(inv,slot); + } + slot++; + } + } + + //distill custom potion in given slot + public static void distillSlot(BrewerInventory inv,int slot){ + ItemStack slotItem = inv.getItem(slot); + PotionMeta potionMeta = (PotionMeta) slotItem.getItemMeta(); + Brew brew = get(potionMeta); + BRecipe recipe = brew.ingredients.getdistillRecipe(); + + if(recipe != null){ + //calculate quality of ingredients and cookingtime + float quality = brew.ingredients.getIngredientQuality(recipe) + brew.ingredients.getCookingQuality(recipe); + quality /= 2; + + /*if(recipe.getDistillRuns() > 1){ + quality -= Math.abs(recipe.getDistillRuns() - (brew.distillRuns + 1)) * 2; + }*/ + + brew.quality = (int)Math.round(quality); + P.p.log("destilled "+recipe.getName(5)+" has Quality: "+brew.quality); + brew.distillRuns += 1; + //distillRuns will have an effect on the amount of alcohol, not the quality + if(brew.distillRuns > 1){ + ArrayList lore = new ArrayList(); + lore.add(brew.distillRuns+" fach Destilliert"); + potionMeta.setLore(lore); + } + + potionMeta.setDisplayName(recipe.getName(brew.quality)); + + //if the potion should be further distillable + if(recipe.getDistillRuns() > 1){ + slotItem.setDurability(PotionColor.valueOf(recipe.getColor()).getColorId(true)); + } else { + slotItem.setDurability(PotionColor.valueOf(recipe.getColor()).getColorId(false)); + } + } else { + potionMeta.setDisplayName("Undefinierbares Destillat"); + slotItem.setDurability(PotionColor.GREY.getColorId(true)); + } + + slotItem.setItemMeta(potionMeta); + } + + + + + //Ageing Section ------------------ + + + public static void age(ItemStack item,float time,byte wood){ + PotionMeta potionMeta = (PotionMeta) item.getItemMeta(); + Brew brew = get(potionMeta); + if(brew != null){ + brew.ageTime += time; + //if younger than half a day, it shouldnt get aged form + if(brew.ageTime > 0.5){ + BRecipe recipe = brew.ingredients.getAgeRecipe(wood,brew.ageTime); + if(recipe != null){ + + //calculate quality from all of the factors + float quality =( + + brew.ingredients.getIngredientQuality(recipe) + + brew.ingredients.getCookingQuality(recipe) + + brew.ingredients.getWoodQuality(recipe,wood) + + brew.ingredients.getAgeQuality(recipe,brew.ageTime)); + + quality /= 4; + brew.quality = (int)Math.round(quality); + P.p.log("Final "+recipe.getName(5)+" has Quality: "+brew.quality); + + potionMeta.setDisplayName(recipe.getName(brew.quality)); + item.setDurability(PotionColor.valueOf(recipe.getColor()).getColorId(false)); + item.setItemMeta(potionMeta); + } + } + } + } + + + + + public static enum PotionColor{ + PINK(1), + CYAN(2), + ORANGE(3), + GREEN(4), + BRIGHT_RED(5), + BLUE(6), + BLACK(8), + RED(9), + GREY(10), + WATER(11), + DARK_RED(12), + BRIGHT_GREY(14); + + private final int colorId; + + private PotionColor(int colorId) { + this.colorId = colorId; + } + + //gets the Damage Value, that sets a color on the potion + //offset +32 is not accepted by brewer, so not further destillable + public short getColorId(boolean destillable){ + if(destillable){ + return (short) (colorId + 64); + } + return (short) (colorId + 32); + } + } + + +} \ No newline at end of file diff --git a/src/com/dre/brewery/P.java b/src/com/dre/brewery/P.java index 5c2c9c1..45577b2 100644 --- a/src/com/dre/brewery/P.java +++ b/src/com/dre/brewery/P.java @@ -9,8 +9,8 @@ import org.apache.commons.lang.math.NumberUtils; import com.dre.brewery.listeners.BlockListener; import com.dre.brewery.listeners.PlayerListener; +import com.dre.brewery.listeners.EntityListener; import org.bukkit.event.HandlerList; -import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.ChatColor; @@ -19,15 +19,13 @@ import java.io.IOException; import org.bukkit.inventory.ItemStack; -import com.dre.brewery.BIngredients; -import com.dre.brewery.BRecipe; - public class P extends JavaPlugin{ public static P p; //Listeners public BlockListener blockListener; public PlayerListener playerListener; + public EntityListener entityListener; @Override @@ -39,10 +37,12 @@ public class P extends JavaPlugin{ //Listeners blockListener = new BlockListener(); playerListener = new PlayerListener(); + entityListener = new EntityListener(); p.getServer().getPluginManager().registerEvents(blockListener, p); p.getServer().getPluginManager().registerEvents(playerListener, p); - p.getServer().getScheduler().runTaskTimer(p, new BreweryRunnable(), 2400, 2400); + p.getServer().getPluginManager().registerEvents(entityListener, p); + p.getServer().getScheduler().runTaskTimer(p, new BreweryRunnable(), 1200, 1200); this.log(this.getDescription().getName()+" enabled!"); @@ -62,6 +62,7 @@ public class P extends JavaPlugin{ File datafile = new File(p.getDataFolder(), "data.yml"); FileConfiguration configFile = new YamlConfiguration(); + //braucht eine gute db ItemStack test = new ItemStack(2);//speichert später die custom potions (nicht als itemstack) configFile.set("ItemStack.Stack", test); @@ -92,6 +93,7 @@ public class P extends JavaPlugin{ } FileConfiguration config = getConfig(); + //loading recipes ConfigurationSection configSection = config.getConfigurationSection("recipes"); if(configSection != null){ for(String recipeId:configSection.getKeys(false)){ @@ -99,6 +101,7 @@ public class P extends JavaPlugin{ } } + //loading cooked names and possible ingredients configSection = config.getConfigurationSection("cooked"); if(configSection != null){ for(String ingredient:configSection.getKeys(false)){ @@ -124,8 +127,9 @@ public class P extends JavaPlugin{ public void run() { p.log("Update"); for(BCauldron cauldron:BCauldron.bcauldrons){ - cauldron.onUpdate();//runs every 2 min to update cooking time + cauldron.onUpdate();//runs every min to update cooking time } + Barrel.onUpdate();//runs every min to check and update ageing time } } diff --git a/src/com/dre/brewery/listeners/BlockListener.java b/src/com/dre/brewery/listeners/BlockListener.java index e1b99fe..61bac90 100644 --- a/src/com/dre/brewery/listeners/BlockListener.java +++ b/src/com/dre/brewery/listeners/BlockListener.java @@ -1,17 +1,50 @@ package com.dre.brewery.listeners; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.SignChangeEvent; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import com.dre.brewery.BCauldron; +import com.dre.brewery.Barrel; +import com.dre.brewery.P; public class BlockListener implements Listener{ - @EventHandler + @EventHandler(priority = EventPriority.NORMAL) public void onSignChange(SignChangeEvent event){ String[] lines = event.getLines(); - if(lines[0].equalsIgnoreCase("[Barrel]")){ - event.getPlayer().sendMessage("Barrel created!"); + if(lines[0].equalsIgnoreCase("Fass")){ + if(Barrel.create(event.getBlock())){ + P.p.msg(event.getPlayer(),"Fass erfolgreich erstellt"); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onBlockBreak(BlockBreakEvent event){ + Block block=event.getBlock(); + //remove cauldron + if(block.getType() == Material.CAULDRON){ + if(block.getRelative(BlockFace.DOWN).getType() == Material.FIRE || + block.getRelative(BlockFace.DOWN).getType() == Material.STATIONARY_LAVA || + block.getRelative(BlockFace.DOWN).getType() == Material.LAVA){ + if(block.getData() != 0){ + //will only remove when existing + BCauldron.remove(block); + } + } + //remove barrel and throw potions on the ground + } else if(block.getType() == Material.FENCE || block.getType() == Material.NETHER_FENCE){ + Barrel barrel = Barrel.get(block); + if(barrel != null){ + barrel.remove(null); + } } } } diff --git a/src/com/dre/brewery/listeners/EntityListener.java b/src/com/dre/brewery/listeners/EntityListener.java new file mode 100644 index 0000000..5dcb50a --- /dev/null +++ b/src/com/dre/brewery/listeners/EntityListener.java @@ -0,0 +1,23 @@ +package com.dre.brewery.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.ItemDespawnEvent; +//import org.bukkit.event.entity.EntityCombustEvent; +import org.bukkit.inventory.ItemStack; + +import com.dre.brewery.Brew; + +public class EntityListener implements Listener{ + + //Remove the Potion from Brew when it despawns + @EventHandler(priority = EventPriority.NORMAL) + public void onItemDespawn(ItemDespawnEvent event){ + ItemStack item = event.getEntity().getItemStack(); + if(item.getTypeId() == 373){ + Brew.remove(item); + } + } + +} diff --git a/src/com/dre/brewery/listeners/PlayerListener.java b/src/com/dre/brewery/listeners/PlayerListener.java index 0ecbfa3..0e40205 100644 --- a/src/com/dre/brewery/listeners/PlayerListener.java +++ b/src/com/dre/brewery/listeners/PlayerListener.java @@ -3,7 +3,6 @@ package com.dre.brewery.listeners; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerItemConsumeEvent; -import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.BrewEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -11,18 +10,18 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.event.inventory.InventoryType.SlotType; +import org.bukkit.inventory.BrewerInventory; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.block.BrewingStand; import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionEffect; import com.dre.brewery.BCauldron; import com.dre.brewery.BIngredients; +import com.dre.brewery.Brew; +import com.dre.brewery.Barrel; import com.dre.brewery.P; @@ -35,13 +34,14 @@ public class PlayerListener implements Listener{ if(event.getAction() == Action.RIGHT_CLICK_BLOCK){ if(clickedBlock.getType() == Material.CAULDRON){ if(clickedBlock.getRelative(BlockFace.DOWN).getType() == Material.FIRE || - clickedBlock.getRelative(BlockFace.DOWN).getType() == Material.STATIONARY_LAVA){ - P.p.log("heat underneath cauldron"); + clickedBlock.getRelative(BlockFace.DOWN).getType() == Material.STATIONARY_LAVA || + clickedBlock.getRelative(BlockFace.DOWN).getType() == Material.LAVA){ Material materialInHand = event.getMaterial(); Player player = event.getPlayer(); ItemStack item = event.getItem(); - if(BIngredients.possibleIngredients.contains(materialInHand)){//add ingredient to cauldron that meet the previous contitions + //add ingredient to cauldron that meet the previous contitions + if(BIngredients.possibleIngredients.contains(materialInHand)){ if(BCauldron.ingredientAdd(clickedBlock,materialInHand)){ if(item.getAmount() > 1){ item.setAmount(item.getAmount() -1); @@ -49,9 +49,9 @@ public class PlayerListener implements Listener{ player.setItemInHand(new ItemStack(0)); } } - } else if(materialInHand == Material.GLASS_BOTTLE){//fill a glass bottle with potion + //fill a glass bottle with potion + } else if(materialInHand == Material.GLASS_BOTTLE){ if(BCauldron.fill(player,clickedBlock)){ - P.p.log("custom potion done"); event.setCancelled(true); if(item.getAmount() > 1){ item.setAmount(item.getAmount() -1); @@ -59,14 +59,29 @@ public class PlayerListener implements Listener{ player.setItemInHand(new ItemStack(0)); } } - } else if(materialInHand == Material.WATER_BUCKET){//reset cauldron when refilling to prevent unlimited source of potions + //reset cauldron when refilling to prevent unlimited source of potions + } else if(materialInHand == Material.WATER_BUCKET){ if(clickedBlock.getData() != 0){ if(clickedBlock.getData() < 3){ + //will only remove when existing BCauldron.remove(clickedBlock); } } } } + //access a barrel + } else if (clickedBlock.getType() == Material.FENCE || clickedBlock.getType() == Material.NETHER_FENCE){ + Barrel barrel = Barrel.get(clickedBlock); + if(barrel != null){ + event.setCancelled(true); + Block broken = Barrel.getBrokenBlock(clickedBlock); + //barrel is built correctly + if(broken == null){ + barrel.open(event.getPlayer()); + } else { + barrel.remove(broken); + } + } } } } @@ -74,45 +89,55 @@ public class PlayerListener implements Listener{ } -//TESTING! + @EventHandler(priority = EventPriority.HIGH) public void onBrew(BrewEvent event){ - P.p.log("Brewing"); int slot = 0; + BrewerInventory inv = event.getContents(); + ItemStack item; + boolean custom = false; + Integer[] contents = new Integer[3]; while(slot < 3){ - ItemStack item = event.getContents().getItem(slot); + item = inv.getItem(slot); + contents[slot] = 0; if(item != null){ if(item.getType() == Material.POTION){ if(item.hasItemMeta()){ - if(item.getItemMeta().getDisplayName().equals("Alkohol")){//TESTING only! neew a way to store get UID - P.p.log("is Alcohol"); - event.getContents().setItem(slot,new ItemStack(2)); - if(!event.isCancelled()){ - event.setCancelled(true); + PotionMeta potionMeta = ((PotionMeta) item.getItemMeta()); + if(potionMeta.hasCustomEffect(PotionEffectType.REGENERATION)){ + if(Brew.get(potionMeta) != null){ + //has custom potion in "slot" + contents[slot] = 1; + custom = true; } - } else { - event.getContents().setItem(slot,new ItemStack(Material.GLASS_BOTTLE)); } - } else { - event.getContents().setItem(slot,new ItemStack(Material.GLASS_BOTTLE)); } } } slot++; } + if(custom){ + event.setCancelled(true); + Brew.distillAll(inv,contents); + } } - @EventHandler(priority = EventPriority.HIGH) + //player drinks a custom potion + @EventHandler(priority = EventPriority.NORMAL) public void onPlayerItemConsume(PlayerItemConsumeEvent event){ if(event.getItem() != null){ if(event.getItem().getType() == Material.POTION){ - P.p.log("consuming a potion"); if(event.getItem().hasItemMeta()){ PotionMeta potionMeta = ((PotionMeta) event.getItem().getItemMeta()); - if(potionMeta.hasCustomEffect(PotionEffectType.CONFUSION)){ - P.p.log("hasConfusion"); + if(potionMeta.hasCustomEffect(PotionEffectType.REGENERATION)){ + for(PotionEffect effect:potionMeta.getCustomEffects()){ + if(effect.getType().getId() == 10){ + //tell him the ID for testing + P.p.msg(event.getPlayer(),"ID: "+effect.getDuration()); + } + } } } }