mirror of
https://github.com/DieReicheErethons/Brewery.git
synced 2024-11-22 11:35:16 +01:00
Rewrite of the Custom item into RecipeItem
and Ingredient with subclasses Implemented adding custom items to Ingredients Added support for plugin-items
This commit is contained in:
parent
d0263c611c
commit
7f2f9d75dd
16
pom.xml
16
pom.xml
@ -14,6 +14,7 @@
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<testSourceDirectory>test</testSourceDirectory>
|
||||
|
||||
<resources>
|
||||
<!-- Static resources -->
|
||||
@ -87,7 +88,7 @@
|
||||
<url>http://maven.sk89q.com/repo/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<!-- GriefPrevention -->
|
||||
<!-- GriefPrevention, SlimeFun -->
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
@ -226,6 +227,19 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.TheBusyBiscuit</groupId>
|
||||
<artifactId>Slimefun4</artifactId>
|
||||
<version>4bb9abd247</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- Contains proprietary api that we use for integration -->
|
||||
<groupId>com.dre</groupId>
|
||||
<artifactId>ExtPluginBridge</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
|
@ -192,6 +192,8 @@ cauldron:
|
||||
# Halte ein Item in der Hand und benutze /brew ItemName um dessen Material herauszufinden und für ein Rezept zu benutzen
|
||||
# (Item-ids anstatt Material können in Bukkit nicht mehr benutzt werden)
|
||||
# Eine Liste von allen Materialien kann hier gefunden werden: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
|
||||
# Plugin Items mit 'Plugin:Id' (Im Moment ExoticGarden, Slimefun, MMOItems, Brewery)
|
||||
# Oder ein oben definiertes Custom Item
|
||||
# cookingtime: Zeit in Echtminuten die die Zutaten kochen müssen
|
||||
# distillruns: Wie oft destilliert werden muss für vollen Alkoholgehalt (0=ohne Destillieren)
|
||||
# distilltime: Wie lange (in sekunden) ein Destillations-Durchlauf braucht (0=Standard Zeit von 40 sek) MC Standard wäre 20 sek
|
||||
@ -219,8 +221,8 @@ recipes:
|
||||
- Diamond/1
|
||||
- Spruce_Planks/8
|
||||
- Bedrock/1
|
||||
# - Brewery:Weißbier/2
|
||||
# - ExoticGarden:Grape/3
|
||||
- Brewery:Weißbier/2
|
||||
# - ExoticGarden:Grape/3
|
||||
- bsp-item/1
|
||||
cookingtime: 3
|
||||
distillruns: 2
|
||||
|
@ -193,6 +193,8 @@ cauldron:
|
||||
# With an item in your hand, use /brew ItemName to get its material for use in a recipe
|
||||
# (Item-ids instead of material are not supported by bukkit anymore and will not work)
|
||||
# A list of materials can be found here: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
|
||||
# Plugin items with 'plugin:id' (Currently supporting ExoticGarden, Slimefun, MMOItems, Brewery)
|
||||
# Or a custom item defined above
|
||||
# cookingtime: Time in real minutes ingredients have to boil
|
||||
# distillruns: How often it has to be distilled for full alcohol (0=without distilling)
|
||||
# distilltime: How long (in seconds) one distill-run takes (0=Default time of 40 sec) MC Default would be 20 sec
|
||||
@ -220,6 +222,8 @@ recipes:
|
||||
- Diamond/1
|
||||
- Spruce_Planks/8
|
||||
- Bedrock/1
|
||||
- Brewery:Wheatbeer/2
|
||||
# - ExoticGarden:Grape/3
|
||||
cookingtime: 3
|
||||
distillruns: 2
|
||||
distilltime: 60
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.dre.brewery;
|
||||
|
||||
import com.dre.brewery.api.events.IngedientAddEvent;
|
||||
import com.dre.brewery.recipe.BCauldronRecipe;
|
||||
import com.dre.brewery.recipe.RecipeItem;
|
||||
import com.dre.brewery.utility.BUtil;
|
||||
import com.dre.brewery.utility.LegacyUtil;
|
||||
import org.bukkit.Effect;
|
||||
@ -28,7 +30,7 @@ public class BCauldron {
|
||||
private BIngredients ingredients = new BIngredients();
|
||||
private final Block block;
|
||||
private int state = 1;
|
||||
private boolean someRemoved = false;
|
||||
private boolean changed = false;
|
||||
|
||||
public BCauldron(Block block) {
|
||||
this.block = block;
|
||||
@ -48,22 +50,22 @@ public class BCauldron {
|
||||
if (!BUtil.isChunkLoaded(block) || LegacyUtil.isFireForCauldron(block.getRelative(BlockFace.DOWN))) {
|
||||
// add a minute to cooking time
|
||||
state++;
|
||||
if (someRemoved) {
|
||||
ingredients = ingredients.clone();
|
||||
someRemoved = false;
|
||||
if (changed) {
|
||||
ingredients = ingredients.copy();
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add an ingredient to the cauldron
|
||||
public void add(ItemStack ingredient) {
|
||||
public void add(ItemStack ingredient, RecipeItem rItem) {
|
||||
if (ingredient == null || ingredient.getType() == Material.AIR) return;
|
||||
if (someRemoved) { // TODO no need to clone
|
||||
ingredients = ingredients.clone();
|
||||
someRemoved = false;
|
||||
if (changed) {
|
||||
ingredients = ingredients.copy();
|
||||
changed = false;
|
||||
}
|
||||
ingredient = new ItemStack(ingredient.getType(), 1, ingredient.getDurability());
|
||||
ingredients.add(ingredient);
|
||||
|
||||
ingredients.add(ingredient, rItem);
|
||||
block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0);
|
||||
if (state > 1) {
|
||||
state--;
|
||||
@ -90,10 +92,20 @@ public class BCauldron {
|
||||
bcauldron = new BCauldron(block);
|
||||
}
|
||||
|
||||
IngedientAddEvent event = new IngedientAddEvent(player, block, bcauldron, ingredient);
|
||||
if (!BCauldronRecipe.acceptedMaterials.contains(ingredient.getType()) && !ingredient.hasItemMeta()) {
|
||||
// Extremely fast way to check for most items
|
||||
return false;
|
||||
}
|
||||
// If the Item is on the list, or customized, we have to do more checks
|
||||
RecipeItem rItem = RecipeItem.getMatchingRecipeItem(ingredient, false);
|
||||
if (rItem == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IngedientAddEvent event = new IngedientAddEvent(player, block, bcauldron, ingredient.clone(), rItem);
|
||||
P.p.getServer().getPluginManager().callEvent(event);
|
||||
if (!event.isCancelled()) {
|
||||
bcauldron.add(event.getIngredient());
|
||||
bcauldron.add(event.getIngredient(), event.getRecipeItem());
|
||||
return event.willTakeItem();
|
||||
} else {
|
||||
return false;
|
||||
@ -127,7 +139,7 @@ public class BCauldron {
|
||||
if (cauldron.getLevel() <= 0) {
|
||||
bcauldrons.remove(this);
|
||||
} else {
|
||||
someRemoved = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -144,7 +156,7 @@ public class BCauldron {
|
||||
if (data == 0) {
|
||||
bcauldrons.remove(this);
|
||||
} else {
|
||||
someRemoved = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
// Bukkit Bug, inventory not updating while in event so this
|
||||
@ -250,30 +262,25 @@ public class BCauldron {
|
||||
}
|
||||
if (item == null) return;
|
||||
|
||||
// add ingredient to cauldron that meet the previous conditions
|
||||
if (BCauldronRecipe.acceptedMaterials.contains(materialInHand)) {
|
||||
if (!player.hasPermission("brewery.cauldron.insert")) {
|
||||
P.p.msg(player, P.p.languageReader.get("Perms_NoCauldronInsert"));
|
||||
return;
|
||||
}
|
||||
if (ingredientAdd(clickedBlock, item, player)) {
|
||||
boolean isBucket = item.getType().equals(Material.WATER_BUCKET)
|
||||
|| item.getType().equals(Material.LAVA_BUCKET)
|
||||
|| item.getType().equals(Material.MILK_BUCKET);
|
||||
if (item.getAmount() > 1) {
|
||||
item.setAmount(item.getAmount() - 1);
|
||||
|
||||
if (!player.hasPermission("brewery.cauldron.insert")) {
|
||||
P.p.msg(player, P.p.languageReader.get("Perms_NoCauldronInsert"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ingredientAdd(clickedBlock, item, player)) {
|
||||
boolean isBucket = item.getType().equals(Material.WATER_BUCKET)
|
||||
|| item.getType().equals(Material.LAVA_BUCKET)
|
||||
|| item.getType().equals(Material.MILK_BUCKET);
|
||||
if (item.getAmount() > 1) {
|
||||
item.setAmount(item.getAmount() - 1);
|
||||
|
||||
if (isBucket) {
|
||||
giveItem(player, new ItemStack(Material.BUCKET));
|
||||
}
|
||||
if (isBucket) {
|
||||
giveItem(player, new ItemStack(Material.BUCKET));
|
||||
}
|
||||
} else {
|
||||
if (isBucket) {
|
||||
setItemInHand(event, Material.BUCKET, handSwap);
|
||||
} else {
|
||||
if (isBucket) {
|
||||
setItemInHand(event, Material.BUCKET, handSwap);
|
||||
} else {
|
||||
setItemInHand(event, Material.AIR, handSwap);
|
||||
}
|
||||
setItemInHand(event, Material.AIR, handSwap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,13 @@
|
||||
package com.dre.brewery;
|
||||
|
||||
import com.dre.brewery.api.events.brew.BrewModifyEvent;
|
||||
import com.dre.brewery.lore.Base91EncoderStream;
|
||||
import com.dre.brewery.lore.BrewLore;
|
||||
import com.dre.brewery.recipe.BCauldronRecipe;
|
||||
import com.dre.brewery.recipe.BRecipe;
|
||||
import com.dre.brewery.recipe.Ingredient;
|
||||
import com.dre.brewery.recipe.ItemLoader;
|
||||
import com.dre.brewery.recipe.RecipeItem;
|
||||
import com.dre.brewery.utility.PotionColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@ -9,19 +15,18 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class BIngredients {
|
||||
private static int lastId = 0;
|
||||
private static int lastId = 0; // Legacy
|
||||
|
||||
private int id; // Legacy
|
||||
private List<ItemStack> ingredients = new ArrayList<>();
|
||||
private List<Ingredient> ingredients = new ArrayList<>();
|
||||
private int cookedTime;
|
||||
|
||||
// Represents ingredients in Cauldron, Brew
|
||||
@ -32,7 +37,7 @@ public class BIngredients {
|
||||
}
|
||||
|
||||
// Load from File
|
||||
public BIngredients(List<ItemStack> ingredients, int cookedTime) {
|
||||
public BIngredients(List<Ingredient> ingredients, int cookedTime) {
|
||||
this.ingredients = ingredients;
|
||||
this.cookedTime = cookedTime;
|
||||
//this.id = lastId;
|
||||
@ -40,7 +45,7 @@ public class BIngredients {
|
||||
}
|
||||
|
||||
// Load from legacy Brew section
|
||||
public BIngredients(List<ItemStack> ingredients, int cookedTime, boolean legacy) {
|
||||
public BIngredients(List<Ingredient> ingredients, int cookedTime, boolean legacy) {
|
||||
this(ingredients, cookedTime);
|
||||
if (legacy) {
|
||||
this.id = lastId;
|
||||
@ -48,15 +53,32 @@ public class BIngredients {
|
||||
}
|
||||
}
|
||||
|
||||
// Add an ingredient to this
|
||||
// Force add an ingredient to this
|
||||
// Will not check if item is acceptable
|
||||
public void add(ItemStack ingredient) {
|
||||
for (ItemStack item : ingredients) {
|
||||
if (item.isSimilar(ingredient)) {
|
||||
item.setAmount(item.getAmount() + ingredient.getAmount());
|
||||
for (Ingredient existing : ingredients) {
|
||||
if (existing.matches(ingredient)) {
|
||||
existing.setAmount(existing.getAmount() + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ingredients.add(ingredient);
|
||||
|
||||
Ingredient ing = RecipeItem.getMatchingRecipeItem(ingredient, true).toIngredient(ingredient);
|
||||
ing.setAmount(1);
|
||||
ingredients.add(ing);
|
||||
}
|
||||
|
||||
// Add an ingredient to this with corresponding RecipeItem
|
||||
public void add(ItemStack ingredient, RecipeItem rItem) {
|
||||
Ingredient ingredientItem = rItem.toIngredient(ingredient);
|
||||
for (Ingredient existing : ingredients) {
|
||||
if (existing.isSimilar(ingredientItem)) {
|
||||
existing.setAmount(existing.getAmount() + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ingredientItem.setAmount(1);
|
||||
ingredients.add(ingredientItem);
|
||||
}
|
||||
|
||||
// returns an Potion item with cooked ingredients
|
||||
@ -140,8 +162,8 @@ public class BIngredients {
|
||||
// returns amount of ingredients
|
||||
public int getIngredientsCount() {
|
||||
int count = 0;
|
||||
for (ItemStack item : ingredients) {
|
||||
count += item.getAmount();
|
||||
for (Ingredient ing : ingredients) {
|
||||
count += ing.getAmount();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@ -265,7 +287,7 @@ public class BIngredients {
|
||||
// when ingredients are not complete
|
||||
return -1;
|
||||
}
|
||||
for (ItemStack ingredient : ingredients) {
|
||||
for (Ingredient ingredient : ingredients) {
|
||||
int amountInRecipe = recipe.amountOf(ingredient);
|
||||
count = ingredient.getAmount();
|
||||
if (amountInRecipe == 0) {
|
||||
@ -346,12 +368,7 @@ public class BIngredients {
|
||||
}
|
||||
|
||||
// Creates a copy ingredients
|
||||
@Override
|
||||
public BIngredients clone() {
|
||||
try {
|
||||
super.clone();
|
||||
} catch (CloneNotSupportedException ignored) {
|
||||
}
|
||||
public BIngredients copy() {
|
||||
BIngredients copy = new BIngredients();
|
||||
copy.ingredients.addAll(ingredients);
|
||||
copy.cookedTime = cookedTime;
|
||||
@ -399,21 +416,25 @@ public class BIngredients {
|
||||
public void save(DataOutputStream out) throws IOException {
|
||||
out.writeInt(cookedTime);
|
||||
out.writeByte(ingredients.size());
|
||||
for (ItemStack item : ingredients) {
|
||||
out.writeUTF(item.getType().name());
|
||||
out.writeShort(item.getAmount());
|
||||
out.writeShort(item.getDurability());
|
||||
for (Ingredient ing : ingredients) {
|
||||
ing.saveTo(out);
|
||||
out.writeShort(Math.min(ing.getAmount(), Short.MAX_VALUE));
|
||||
}
|
||||
}
|
||||
|
||||
public static BIngredients load(DataInputStream in) throws IOException {
|
||||
public static BIngredients load(DataInputStream in, short dataVersion) throws IOException {
|
||||
int cookedTime = in.readInt();
|
||||
byte size = in.readByte();
|
||||
List<ItemStack> ing = new ArrayList<>(size);
|
||||
List<Ingredient> ing = new ArrayList<>(size);
|
||||
for (; size > 0; size--) {
|
||||
Material mat = Material.getMaterial(in.readUTF());
|
||||
if (mat != null) {
|
||||
ing.add(new ItemStack(mat, in.readShort(), in.readShort()));
|
||||
ItemLoader itemLoader = new ItemLoader(dataVersion, in, in.readUTF());
|
||||
if (Ingredient.LOADERS.containsKey(itemLoader.getSaveID())) {
|
||||
Ingredient loaded = Ingredient.LOADERS.get(itemLoader.getSaveID()).apply(itemLoader);
|
||||
int amount = in.readShort();
|
||||
if (loaded != null) {
|
||||
loaded.setAmount(amount);
|
||||
ing.add(loaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new BIngredients(ing, cookedTime);
|
||||
@ -421,8 +442,7 @@ public class BIngredients {
|
||||
|
||||
// saves data into main Ingredient section. Returns the save id
|
||||
// Only needed for legacy potions
|
||||
@Deprecated
|
||||
public int save(ConfigurationSection config) {
|
||||
public int saveLegacy(ConfigurationSection config) {
|
||||
String path = "Ingredients." + id;
|
||||
if (cookedTime != 0) {
|
||||
config.set(path + ".cookedTime", cookedTime);
|
||||
@ -432,13 +452,26 @@ public class BIngredients {
|
||||
}
|
||||
|
||||
//convert the ingredient Material to String
|
||||
public Map<String, Integer> serializeIngredients() {
|
||||
/*public Map<String, Integer> serializeIngredients() {
|
||||
Map<String, Integer> mats = new HashMap<>();
|
||||
for (ItemStack item : ingredients) {
|
||||
String mat = item.getType().name() + "," + item.getDurability();
|
||||
mats.put(mat, item.getAmount());
|
||||
}
|
||||
return mats;
|
||||
}*/
|
||||
|
||||
// Serialize Ingredients to String for storing in yml, ie for Cauldrons
|
||||
public String serializeIngredients() {
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
||||
try (DataOutputStream out = new DataOutputStream(new Base91EncoderStream(byteStream))) {
|
||||
out.writeByte(Brew.SAVE_VER);
|
||||
save(out);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
return byteStream.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import com.dre.brewery.api.events.PlayerPukeEvent;
|
||||
import com.dre.brewery.api.events.PlayerPushEvent;
|
||||
import com.dre.brewery.api.events.brew.BrewDrinkEvent;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import com.dre.brewery.recipe.BEffect;
|
||||
import com.dre.brewery.utility.BUtil;
|
||||
import org.apache.commons.lang.mutable.MutableInt;
|
||||
import org.bukkit.Location;
|
||||
|
@ -5,7 +5,7 @@ import com.dre.brewery.api.events.barrel.BarrelCreateEvent;
|
||||
import com.dre.brewery.api.events.barrel.BarrelDestroyEvent;
|
||||
import com.dre.brewery.api.events.barrel.BarrelRemoveEvent;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import com.dre.brewery.integration.LogBlockBarrel;
|
||||
import com.dre.brewery.integration.barrel.LogBlockBarrel;
|
||||
import com.dre.brewery.lore.BrewLore;
|
||||
import com.dre.brewery.utility.BUtil;
|
||||
import com.dre.brewery.utility.BoundingBox;
|
||||
|
@ -4,6 +4,8 @@ import com.dre.brewery.api.events.brew.BrewModifyEvent;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import com.dre.brewery.filedata.ConfigUpdater;
|
||||
import com.dre.brewery.lore.*;
|
||||
import com.dre.brewery.recipe.BEffect;
|
||||
import com.dre.brewery.recipe.BRecipe;
|
||||
import com.dre.brewery.utility.PotionColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@ -26,6 +28,7 @@ import java.util.Map;
|
||||
|
||||
public class Brew {
|
||||
// represents the liquid in the brewed Potions
|
||||
public static final byte SAVE_VER = 1;
|
||||
private static long saveSeed;
|
||||
private static List<Long> prevSaveSeeds = new ArrayList<>(); // Save Seeds that have been used in the past, stored to decode brews made at that time
|
||||
public static Map<Integer, Brew> legacyPotions = new HashMap<>();
|
||||
@ -207,10 +210,10 @@ public class Brew {
|
||||
if (!immutable) {
|
||||
this.quality = calcQuality();
|
||||
}
|
||||
P.p.log("Brew was made from Recipe: '" + name + "' which could not be found. '" + currentRecipe.getRecipeName() + "' used instead!");
|
||||
P.p.log("A Brew was made from Recipe: '" + name + "' which could not be found. '" + currentRecipe.getRecipeName() + "' used instead!");
|
||||
return true;
|
||||
} else {
|
||||
P.p.errorLog("Brew was made from Recipe: '" + name + "' which could not be found!");
|
||||
P.p.errorLog("A Brew was made from Recipe: '" + name + "' which could not be found!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -570,7 +573,9 @@ public class Brew {
|
||||
recipe.getColor().colorBrew(potionMeta, item, canDistill());
|
||||
} else {
|
||||
quality = 0;
|
||||
lore.convertLore(false);
|
||||
lore.removeEffects();
|
||||
currentRecipe = null;
|
||||
potionMeta.setDisplayName(P.p.color("&f" + P.p.languageReader.get("Brew_BadPotion")));
|
||||
PotionColor.GREY.colorBrew(potionMeta, item, canDistill());
|
||||
}
|
||||
@ -714,7 +719,7 @@ public class Brew {
|
||||
case 1:
|
||||
|
||||
unscrambler.start();
|
||||
brew.loadFromStream(in);
|
||||
brew.loadFromStream(in, ver);
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -748,7 +753,7 @@ public class Brew {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void loadFromStream(DataInputStream in) throws IOException {
|
||||
private void loadFromStream(DataInputStream in, byte dataVersion) throws IOException {
|
||||
quality = in.readByte();
|
||||
int bools = in.readUnsignedByte();
|
||||
if ((bools & 1) != 0) {
|
||||
@ -767,7 +772,7 @@ public class Brew {
|
||||
unlabeled = (bools & 16) != 0;
|
||||
//persistent = (bools & 32) != 0;
|
||||
immutable = (bools & 32) != 0;
|
||||
ingredients = BIngredients.load(in);
|
||||
ingredients = BIngredients.load(in, dataVersion);
|
||||
setRecipeFromString(recipe);
|
||||
}
|
||||
|
||||
@ -782,7 +787,7 @@ public class Brew {
|
||||
XORScrambleStream scrambler = new XORScrambleStream(itemSaveStream, saveSeed);
|
||||
try (DataOutputStream out = new DataOutputStream(scrambler)) {
|
||||
out.writeByte(86); // Parity/sanity
|
||||
out.writeByte(1); // Version
|
||||
out.writeByte(SAVE_VER); // Version
|
||||
if (BConfig.enableEncode) {
|
||||
scrambler.start();
|
||||
} else {
|
||||
@ -890,6 +895,7 @@ public class Brew {
|
||||
public void convertPre19(ItemStack item) {
|
||||
removeLegacy(item);
|
||||
PotionMeta potionMeta = ((PotionMeta) item.getItemMeta());
|
||||
assert potionMeta != null;
|
||||
if (hasRecipe()) {
|
||||
BrewLore lore = new BrewLore(this, potionMeta);
|
||||
lore.removeEffects();
|
||||
@ -905,8 +911,7 @@ public class Brew {
|
||||
|
||||
// Saves all data
|
||||
// Legacy method to save to data file
|
||||
@Deprecated
|
||||
public static void save(ConfigurationSection config) {
|
||||
public static void saveLegacy(ConfigurationSection config) {
|
||||
for (Map.Entry<Integer, Brew> entry : legacyPotions.entrySet()) {
|
||||
int uid = entry.getKey();
|
||||
Brew brew = entry.getValue();
|
||||
@ -940,7 +945,7 @@ public class Brew {
|
||||
idConfig.set("lastUpdate", brew.lastUpdate);
|
||||
}
|
||||
// save the ingredients
|
||||
idConfig.set("ingId", brew.ingredients.save(config.getParent()));
|
||||
idConfig.set("ingId", brew.ingredients.saveLegacy(config.getParent()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,10 @@ import com.dre.brewery.filedata.DataSave;
|
||||
import com.dre.brewery.filedata.LanguageReader;
|
||||
import com.dre.brewery.filedata.UpdateChecker;
|
||||
import com.dre.brewery.integration.IntegrationListener;
|
||||
import com.dre.brewery.integration.LogBlockBarrel;
|
||||
import com.dre.brewery.integration.barrel.LogBlockBarrel;
|
||||
import com.dre.brewery.listeners.*;
|
||||
import com.dre.brewery.recipe.BCauldronRecipe;
|
||||
import com.dre.brewery.recipe.BRecipe;
|
||||
import com.dre.brewery.utility.BUtil;
|
||||
import com.dre.brewery.utility.LegacyUtil;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
@ -442,8 +444,12 @@ public class P extends JavaPlugin {
|
||||
BCauldron.bcauldrons.clear();
|
||||
BRecipe.recipes.clear();
|
||||
BCauldronRecipe.acceptedMaterials.clear();
|
||||
BCauldronRecipe.acceptedCustom.clear();
|
||||
BCauldronRecipe.acceptedSimple.clear();
|
||||
BCauldronRecipe.recipes.clear();
|
||||
BConfig.customItems.clear();
|
||||
BConfig.hasSlimefun = null;
|
||||
BConfig.hasMMOItems = null;
|
||||
BPlayer.clear();
|
||||
Brew.legacyPotions.clear();
|
||||
Wakeup.wakeups.clear();
|
||||
@ -461,8 +467,12 @@ public class P extends JavaPlugin {
|
||||
// clear all existent config Data
|
||||
BRecipe.recipes.clear();
|
||||
BCauldronRecipe.acceptedMaterials.clear();
|
||||
BCauldronRecipe.acceptedCustom.clear();
|
||||
BCauldronRecipe.acceptedSimple.clear();
|
||||
BCauldronRecipe.recipes.clear();
|
||||
BConfig.customItems.clear();
|
||||
BConfig.hasSlimefun = null;
|
||||
BConfig.hasMMOItems = null;
|
||||
DistortChat.words.clear();
|
||||
DistortChat.ignoreText.clear();
|
||||
DistortChat.commands = null;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.dre.brewery.api;
|
||||
|
||||
import com.dre.brewery.BCauldron;
|
||||
import com.dre.brewery.BRecipe;
|
||||
import com.dre.brewery.recipe.BRecipe;
|
||||
import com.dre.brewery.Barrel;
|
||||
import com.dre.brewery.Brew;
|
||||
import org.apache.commons.lang.NotImplementedException;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.dre.brewery.api.events;
|
||||
|
||||
import com.dre.brewery.BCauldron;
|
||||
import com.dre.brewery.recipe.RecipeItem;
|
||||
import com.dre.brewery.utility.LegacyUtil;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@ -21,14 +22,16 @@ public class IngedientAddEvent extends PlayerEvent implements Cancellable {
|
||||
private final Block block;
|
||||
private final BCauldron cauldron;
|
||||
private ItemStack ingredient;
|
||||
private RecipeItem rItem;
|
||||
private boolean cancelled;
|
||||
private boolean takeItem = true;
|
||||
|
||||
public IngedientAddEvent(Player who, Block block, BCauldron bCauldron, ItemStack ingredient) {
|
||||
public IngedientAddEvent(Player who, Block block, BCauldron bCauldron, ItemStack ingredient, RecipeItem rItem) {
|
||||
super(who);
|
||||
this.block = block;
|
||||
cauldron = bCauldron;
|
||||
this.ingredient = ingredient.clone();
|
||||
this.rItem = rItem;
|
||||
this.ingredient = ingredient;
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
@ -39,6 +42,15 @@ public class IngedientAddEvent extends PlayerEvent implements Cancellable {
|
||||
return cauldron;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Recipe item that matches the ingredient.
|
||||
* This might not be the only recipe item that will match the ingredient
|
||||
* Will be recalculated if the Ingredient is changed with the setIngredient Method
|
||||
*/
|
||||
public RecipeItem getRecipeItem() {
|
||||
return rItem;
|
||||
}
|
||||
|
||||
// Get the item currently being added to the cauldron by the player
|
||||
// Can be changed directly (mutable) or with the setter Method
|
||||
// The amount is ignored and always one added
|
||||
@ -49,8 +61,11 @@ public class IngedientAddEvent extends PlayerEvent implements Cancellable {
|
||||
// Set the ingredient added to the cauldron to something else
|
||||
// Will always be accepted, even when not in a recipe or the cooked list
|
||||
// The amount is ignored and always one added
|
||||
// This also recalculates the recipeItem!
|
||||
public void setIngredient(ItemStack ingredient) {
|
||||
this.ingredient = ingredient;
|
||||
// The Ingredient has been changed. Recalculate RecipeItem!
|
||||
rItem = RecipeItem.getMatchingRecipeItem(ingredient, true);
|
||||
}
|
||||
|
||||
// If the amount of the item in the players hand should be decreased
|
||||
|
@ -1,18 +1,29 @@
|
||||
package com.dre.brewery.filedata;
|
||||
|
||||
import com.dre.brewery.*;
|
||||
import com.dre.brewery.integration.WGBarrel;
|
||||
import com.dre.brewery.integration.WGBarrel5;
|
||||
import com.dre.brewery.integration.WGBarrel6;
|
||||
import com.dre.brewery.integration.WGBarrel7;
|
||||
import com.dre.brewery.Brew;
|
||||
import com.dre.brewery.DistortChat;
|
||||
import com.dre.brewery.MCBarrel;
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.integration.barrel.WGBarrel;
|
||||
import com.dre.brewery.integration.barrel.WGBarrel5;
|
||||
import com.dre.brewery.integration.barrel.WGBarrel6;
|
||||
import com.dre.brewery.integration.barrel.WGBarrel7;
|
||||
import com.dre.brewery.integration.item.BreweryPluginItem;
|
||||
import com.dre.brewery.integration.item.MMOItemsPluginItem;
|
||||
import com.dre.brewery.integration.item.SlimefunPluginItem;
|
||||
import com.dre.brewery.recipe.BCauldronRecipe;
|
||||
import com.dre.brewery.recipe.BRecipe;
|
||||
import com.dre.brewery.recipe.PluginItem;
|
||||
import com.dre.brewery.recipe.RecipeItem;
|
||||
import com.dre.brewery.utility.BUtil;
|
||||
import com.dre.brewery.utility.CustomItem;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
@ -38,6 +49,8 @@ public class BConfig {
|
||||
public static boolean useGP; //GriefPrevention
|
||||
public static boolean hasVault; // Vault
|
||||
public static boolean useCitadel; // CivCraft/DevotedMC Citadel
|
||||
public static Boolean hasSlimefun = null; // Slimefun ; Null if not checked
|
||||
public static Boolean hasMMOItems = null; // MMOItems ; Null if not checked
|
||||
|
||||
// Barrel
|
||||
public static boolean openEverywhere;
|
||||
@ -61,7 +74,7 @@ public class BConfig {
|
||||
public static boolean alwaysShowAlc; // Always show alc%
|
||||
|
||||
//Item
|
||||
public static List<CustomItem> customItems = new ArrayList<>();
|
||||
public static List<RecipeItem> customItems = new ArrayList<>();
|
||||
|
||||
public static P p = P.p;
|
||||
|
||||
@ -189,12 +202,18 @@ public class BConfig {
|
||||
|
||||
Brew.loadSeed(config, file);
|
||||
|
||||
PluginItem.registerForConfig("brewery", BreweryPluginItem::new);
|
||||
PluginItem.registerForConfig("mmoitems", MMOItemsPluginItem::new);
|
||||
PluginItem.registerForConfig("slimefun", SlimefunPluginItem::new);
|
||||
PluginItem.registerForConfig("exoticgarden", SlimefunPluginItem::new);
|
||||
|
||||
// Loading custom items
|
||||
ConfigurationSection configSection = config.getConfigurationSection("customItems");
|
||||
if (configSection != null) {
|
||||
for (String custId : configSection.getKeys(false)) {
|
||||
CustomItem custom = CustomItem.fromConfig(configSection, custId);
|
||||
RecipeItem custom = RecipeItem.fromConfigCustom(configSection, custId);
|
||||
if (custom != null) {
|
||||
custom.makeImmutable();
|
||||
customItems.add(custom);
|
||||
} else {
|
||||
p.errorLog("Loading the Custom Item with id: '" + custId + "' failed!");
|
||||
|
@ -1,6 +1,11 @@
|
||||
package com.dre.brewery.filedata;
|
||||
|
||||
import com.dre.brewery.*;
|
||||
import com.dre.brewery.lore.Base91DecoderStream;
|
||||
import com.dre.brewery.recipe.CustomItem;
|
||||
import com.dre.brewery.recipe.Ingredient;
|
||||
import com.dre.brewery.recipe.PluginItem;
|
||||
import com.dre.brewery.recipe.SimpleItem;
|
||||
import com.dre.brewery.utility.BUtil;
|
||||
import com.dre.brewery.utility.BoundingBox;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
@ -12,14 +17,12 @@ import org.bukkit.block.Block;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class BData {
|
||||
|
||||
@ -47,18 +50,30 @@ public class BData {
|
||||
}
|
||||
}
|
||||
|
||||
// Register Item Loaders
|
||||
CustomItem.registerItemLoader();
|
||||
SimpleItem.registerItemLoader();
|
||||
PluginItem.registerItemLoader();
|
||||
|
||||
// loading Ingredients into ingMap
|
||||
// Only for Legacy Brews
|
||||
Map<String, BIngredients> ingMap = new HashMap<>();
|
||||
ConfigurationSection section = data.getConfigurationSection("Ingredients");
|
||||
if (section != null) {
|
||||
for (String id : section.getKeys(false)) {
|
||||
ConfigurationSection matSection = section.getConfigurationSection(id + ".mats");
|
||||
if (matSection != null) {
|
||||
// matSection has all the materials + amount as Integers
|
||||
ArrayList<ItemStack> ingredients = deserializeIngredients(matSection);
|
||||
ingMap.put(id, new BIngredients(ingredients, section.getInt(id + ".cookedTime", 0), true));
|
||||
if (section.isConfigurationSection(id + ".mats")) {
|
||||
// Old way of saving
|
||||
ConfigurationSection matSection = section.getConfigurationSection(id + ".mats");
|
||||
if (matSection != null) {
|
||||
// matSection has all the materials + amount as Integers
|
||||
List<Ingredient> ingredients = oldDeserializeIngredients(matSection);
|
||||
ingMap.put(id, new BIngredients(ingredients, section.getInt(id + ".cookedTime", 0), true));
|
||||
} else {
|
||||
P.p.errorLog("Ingredient id: '" + id + "' incomplete in data.yml");
|
||||
}
|
||||
} else {
|
||||
P.p.errorLog("Ingredient id: '" + id + "' incomplete in data.yml");
|
||||
// New way of saving ingredients
|
||||
ingMap.put(id, deserializeIngredients(section.getString(id + ".mats")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -110,9 +125,9 @@ public class BData {
|
||||
|
||||
for (World world : P.p.getServer().getWorlds()) {
|
||||
if (world.getName().startsWith("DXL_")) {
|
||||
loadWorldData(BUtil.getDxlName(world.getName()), world);
|
||||
loadWorldData(BUtil.getDxlName(world.getName()), world, data);
|
||||
} else {
|
||||
loadWorldData(world.getUID().toString(), world);
|
||||
loadWorldData(world.getUID().toString(), world, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,8 +136,19 @@ public class BData {
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<ItemStack> deserializeIngredients(ConfigurationSection matSection) {
|
||||
ArrayList<ItemStack> ingredients = new ArrayList<>();
|
||||
public static BIngredients deserializeIngredients(String mat) {
|
||||
try (DataInputStream in = new DataInputStream(new Base91DecoderStream(new ByteArrayInputStream(mat.getBytes())))) {
|
||||
byte ver = in.readByte();
|
||||
return BIngredients.load(in, ver);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new BIngredients();
|
||||
}
|
||||
}
|
||||
|
||||
// Loading from the old way of saving ingredients
|
||||
public static List<Ingredient> oldDeserializeIngredients(ConfigurationSection matSection) {
|
||||
List<Ingredient> ingredients = new ArrayList<>();
|
||||
for (String mat : matSection.getKeys(false)) {
|
||||
String[] matSplit = mat.split(",");
|
||||
Material m = Material.getMaterial(matSplit[0]);
|
||||
@ -135,10 +161,13 @@ public class BData {
|
||||
P.p.debugLog("converting Data Material from " + matSplit[0] + " to " + m);
|
||||
}
|
||||
if (m == null) continue;
|
||||
ItemStack item = new ItemStack(m, matSection.getInt(mat));
|
||||
SimpleItem item;
|
||||
if (matSplit.length == 2) {
|
||||
item.setDurability((short) P.p.parseInt(matSplit[1]));
|
||||
item = new SimpleItem(m, (short) P.p.parseInt(matSplit[1]));
|
||||
} else {
|
||||
item = new SimpleItem(m);
|
||||
}
|
||||
item.setAmount(matSection.getInt(mat));
|
||||
ingredients.add(item);
|
||||
}
|
||||
return ingredients;
|
||||
@ -156,134 +185,146 @@ public class BData {
|
||||
}
|
||||
|
||||
// loads BIngredients from an ingredient section
|
||||
public static BIngredients loadIngredients(ConfigurationSection section) {
|
||||
if (section != null) {
|
||||
return new BIngredients(deserializeIngredients(section), 0);
|
||||
public static BIngredients loadCauldronIng(ConfigurationSection section, String path) {
|
||||
if (section.isConfigurationSection(path)) {
|
||||
// Old way of saving
|
||||
ConfigurationSection matSection = section.getConfigurationSection(path);
|
||||
if (matSection != null) {
|
||||
// matSection has all the materials + amount as Integers
|
||||
return new BIngredients(oldDeserializeIngredients(section), 0);
|
||||
} else {
|
||||
P.p.errorLog("Cauldron is missing Ingredient Section");
|
||||
return new BIngredients();
|
||||
}
|
||||
} else {
|
||||
P.p.errorLog("Cauldron is missing Ingredient Section");
|
||||
// New way of saving ingredients
|
||||
return deserializeIngredients(section.getString(path));
|
||||
}
|
||||
return new BIngredients();
|
||||
}
|
||||
|
||||
// load Block locations of given world
|
||||
public static void loadWorldData(String uuid, World world) {
|
||||
public static void loadWorldData(String uuid, World world, FileConfiguration data) {
|
||||
|
||||
File file = new File(P.p.getDataFolder(), "data.yml");
|
||||
if (file.exists()) {
|
||||
|
||||
FileConfiguration data = YamlConfiguration.loadConfiguration(file);
|
||||
|
||||
// loading BCauldron
|
||||
if (data.contains("BCauldron." + uuid)) {
|
||||
ConfigurationSection section = data.getConfigurationSection("BCauldron." + uuid);
|
||||
for (String cauldron : section.getKeys(false)) {
|
||||
// block is splitted into x/y/z
|
||||
String block = section.getString(cauldron + ".block");
|
||||
if (block != null) {
|
||||
String[] splitted = block.split("/");
|
||||
if (splitted.length == 3) {
|
||||
|
||||
Block worldBlock = world.getBlockAt(P.p.parseInt(splitted[0]), P.p.parseInt(splitted[1]), P.p.parseInt(splitted[2]));
|
||||
BIngredients ingredients = loadIngredients(section.getConfigurationSection(cauldron + ".ingredients"));
|
||||
int state = section.getInt(cauldron + ".state", 1);
|
||||
|
||||
new BCauldron(worldBlock, ingredients, state);
|
||||
} else {
|
||||
P.p.errorLog("Incomplete Block-Data in data.yml: " + section.getCurrentPath() + "." + cauldron);
|
||||
}
|
||||
} else {
|
||||
P.p.errorLog("Missing Block-Data in data.yml: " + section.getCurrentPath() + "." + cauldron);
|
||||
}
|
||||
}
|
||||
if (data == null) {
|
||||
File file = new File(P.p.getDataFolder(), "data.yml");
|
||||
if (file.exists()) {
|
||||
data = YamlConfiguration.loadConfiguration(file);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// loading Barrel
|
||||
if (data.contains("Barrel." + uuid)) {
|
||||
ConfigurationSection section = data.getConfigurationSection("Barrel." + uuid);
|
||||
for (String barrel : section.getKeys(false)) {
|
||||
// block spigot is splitted into x/y/z
|
||||
String spigot = section.getString(barrel + ".spigot");
|
||||
if (spigot != null) {
|
||||
String[] splitted = spigot.split("/");
|
||||
if (splitted.length == 3) {
|
||||
|
||||
// load itemStacks from invSection
|
||||
ConfigurationSection invSection = section.getConfigurationSection(barrel + ".inv");
|
||||
Block block = world.getBlockAt(P.p.parseInt(splitted[0]), P.p.parseInt(splitted[1]), P.p.parseInt(splitted[2]));
|
||||
float time = (float) section.getDouble(barrel + ".time", 0.0);
|
||||
byte sign = (byte) section.getInt(barrel + ".sign", 0);
|
||||
|
||||
BoundingBox box = null;
|
||||
if (section.contains(barrel + ".bounds")) {
|
||||
String[] bds = section.getString(barrel + ".bounds", "").split(",");
|
||||
if (bds.length == 6) {
|
||||
box = new BoundingBox(P.p.parseInt(bds[0]), P.p.parseInt(bds[1]), P.p.parseInt(bds[2]), P.p.parseInt(bds[3]), P.p.parseInt(bds[4]), P.p.parseInt(bds[5]));
|
||||
}
|
||||
} else if (section.contains(barrel + ".st")) {
|
||||
// Convert from Stair and Wood Locations to BoundingBox
|
||||
String[] st = section.getString(barrel + ".st", "").split(",");
|
||||
String[] wo = section.getString(barrel + ".wo", "").split(",");
|
||||
int woLength = wo.length;
|
||||
if (woLength <= 1) {
|
||||
woLength = 0;
|
||||
}
|
||||
String[] points = new String[st.length + woLength];
|
||||
System.arraycopy(st, 0, points, 0, st.length);
|
||||
if (woLength > 1) {
|
||||
System.arraycopy(wo, 0, points, st.length, woLength);
|
||||
}
|
||||
int[] locs = ArrayUtils.toPrimitive(Arrays.stream(points).map(s -> P.p.parseInt(s)).toArray(Integer[]::new));
|
||||
box = BoundingBox.fromPoints(locs);
|
||||
}
|
||||
|
||||
Barrel b;
|
||||
if (invSection != null) {
|
||||
b = new Barrel(block, sign, box, invSection.getValues(true), time);
|
||||
} else {
|
||||
// Barrel has no inventory
|
||||
b = new Barrel(block, sign, box, null, time);
|
||||
}
|
||||
|
||||
// In case Barrel Block locations were missing and could not be recreated: do not add the barrel
|
||||
if (b.getBody().getBounds() != null) {
|
||||
Barrel.barrels.add(b);
|
||||
}
|
||||
|
||||
} else {
|
||||
P.p.errorLog("Incomplete Block-Data in data.yml: " + section.getCurrentPath() + "." + barrel);
|
||||
}
|
||||
} else {
|
||||
P.p.errorLog("Missing Block-Data in data.yml: " + section.getCurrentPath() + "." + barrel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loading Wakeup
|
||||
if (data.contains("Wakeup." + uuid)) {
|
||||
ConfigurationSection section = data.getConfigurationSection("Wakeup." + uuid);
|
||||
for (String wakeup : section.getKeys(false)) {
|
||||
// loc of wakeup is splitted into x/y/z/pitch/yaw
|
||||
String loc = section.getString(wakeup);
|
||||
if (loc != null) {
|
||||
String[] splitted = loc.split("/");
|
||||
if (splitted.length == 5) {
|
||||
|
||||
double x = NumberUtils.toDouble(splitted[0]);
|
||||
double y = NumberUtils.toDouble(splitted[1]);
|
||||
double z = NumberUtils.toDouble(splitted[2]);
|
||||
float pitch = NumberUtils.toFloat(splitted[3]);
|
||||
float yaw = NumberUtils.toFloat(splitted[4]);
|
||||
Location location = new Location(world, x, y, z, yaw, pitch);
|
||||
|
||||
Wakeup.wakeups.add(new Wakeup(location));
|
||||
|
||||
} else {
|
||||
P.p.errorLog("Incomplete Location-Data in data.yml: " + section.getCurrentPath() + "." + wakeup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// loading BCauldron
|
||||
if (data.contains("BCauldron." + uuid)) {
|
||||
ConfigurationSection section = data.getConfigurationSection("BCauldron." + uuid);
|
||||
for (String cauldron : section.getKeys(false)) {
|
||||
// block is splitted into x/y/z
|
||||
String block = section.getString(cauldron + ".block");
|
||||
if (block != null) {
|
||||
String[] splitted = block.split("/");
|
||||
if (splitted.length == 3) {
|
||||
|
||||
Block worldBlock = world.getBlockAt(P.p.parseInt(splitted[0]), P.p.parseInt(splitted[1]), P.p.parseInt(splitted[2]));
|
||||
BIngredients ingredients = loadCauldronIng(section, cauldron + ".ingredients");
|
||||
int state = section.getInt(cauldron + ".state", 1);
|
||||
|
||||
new BCauldron(worldBlock, ingredients, state);
|
||||
} else {
|
||||
P.p.errorLog("Incomplete Block-Data in data.yml: " + section.getCurrentPath() + "." + cauldron);
|
||||
}
|
||||
} else {
|
||||
P.p.errorLog("Missing Block-Data in data.yml: " + section.getCurrentPath() + "." + cauldron);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loading Barrel
|
||||
if (data.contains("Barrel." + uuid)) {
|
||||
ConfigurationSection section = data.getConfigurationSection("Barrel." + uuid);
|
||||
for (String barrel : section.getKeys(false)) {
|
||||
// block spigot is splitted into x/y/z
|
||||
String spigot = section.getString(barrel + ".spigot");
|
||||
if (spigot != null) {
|
||||
String[] splitted = spigot.split("/");
|
||||
if (splitted.length == 3) {
|
||||
|
||||
// load itemStacks from invSection
|
||||
ConfigurationSection invSection = section.getConfigurationSection(barrel + ".inv");
|
||||
Block block = world.getBlockAt(P.p.parseInt(splitted[0]), P.p.parseInt(splitted[1]), P.p.parseInt(splitted[2]));
|
||||
float time = (float) section.getDouble(barrel + ".time", 0.0);
|
||||
byte sign = (byte) section.getInt(barrel + ".sign", 0);
|
||||
|
||||
BoundingBox box = null;
|
||||
if (section.contains(barrel + ".bounds")) {
|
||||
String[] bds = section.getString(barrel + ".bounds", "").split(",");
|
||||
if (bds.length == 6) {
|
||||
box = new BoundingBox(P.p.parseInt(bds[0]), P.p.parseInt(bds[1]), P.p.parseInt(bds[2]), P.p.parseInt(bds[3]), P.p.parseInt(bds[4]), P.p.parseInt(bds[5]));
|
||||
}
|
||||
} else if (section.contains(barrel + ".st")) {
|
||||
// Convert from Stair and Wood Locations to BoundingBox
|
||||
String[] st = section.getString(barrel + ".st", "").split(",");
|
||||
String[] wo = section.getString(barrel + ".wo", "").split(",");
|
||||
int woLength = wo.length;
|
||||
if (woLength <= 1) {
|
||||
woLength = 0;
|
||||
}
|
||||
String[] points = new String[st.length + woLength];
|
||||
System.arraycopy(st, 0, points, 0, st.length);
|
||||
if (woLength > 1) {
|
||||
System.arraycopy(wo, 0, points, st.length, woLength);
|
||||
}
|
||||
int[] locs = ArrayUtils.toPrimitive(Arrays.stream(points).map(s -> P.p.parseInt(s)).toArray(Integer[]::new));
|
||||
box = BoundingBox.fromPoints(locs);
|
||||
}
|
||||
|
||||
Barrel b;
|
||||
if (invSection != null) {
|
||||
b = new Barrel(block, sign, box, invSection.getValues(true), time);
|
||||
} else {
|
||||
// Barrel has no inventory
|
||||
b = new Barrel(block, sign, box, null, time);
|
||||
}
|
||||
|
||||
// In case Barrel Block locations were missing and could not be recreated: do not add the barrel
|
||||
|
||||
if (b.getBody().getBounds() != null) {
|
||||
Barrel.barrels.add(b);
|
||||
}
|
||||
|
||||
} else {
|
||||
P.p.errorLog("Incomplete Block-Data in data.yml: " + section.getCurrentPath() + "." + barrel);
|
||||
}
|
||||
} else {
|
||||
P.p.errorLog("Missing Block-Data in data.yml: " + section.getCurrentPath() + "." + barrel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loading Wakeup
|
||||
if (data.contains("Wakeup." + uuid)) {
|
||||
ConfigurationSection section = data.getConfigurationSection("Wakeup." + uuid);
|
||||
for (String wakeup : section.getKeys(false)) {
|
||||
// loc of wakeup is splitted into x/y/z/pitch/yaw
|
||||
String loc = section.getString(wakeup);
|
||||
if (loc != null) {
|
||||
String[] splitted = loc.split("/");
|
||||
if (splitted.length == 5) {
|
||||
|
||||
double x = NumberUtils.toDouble(splitted[0]);
|
||||
double y = NumberUtils.toDouble(splitted[1]);
|
||||
double z = NumberUtils.toDouble(splitted[2]);
|
||||
float pitch = NumberUtils.toFloat(splitted[3]);
|
||||
float yaw = NumberUtils.toFloat(splitted[4]);
|
||||
Location location = new Location(world, x, y, z, yaw, pitch);
|
||||
|
||||
Wakeup.wakeups.add(new Wakeup(location));
|
||||
|
||||
} else {
|
||||
P.p.errorLog("Incomplete Location-Data in data.yml: " + section.getCurrentPath() + "." + wakeup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class DataSave extends BukkitRunnable {
|
||||
Brew.writePrevSeeds(configFile);
|
||||
|
||||
if (!Brew.legacyPotions.isEmpty()) {
|
||||
Brew.save(configFile.createSection("Brew"));
|
||||
Brew.saveLegacy(configFile.createSection("Brew"));
|
||||
}
|
||||
|
||||
if (!BCauldron.bcauldrons.isEmpty() || oldData.contains("BCauldron")) {
|
||||
|
@ -1,18 +1,30 @@
|
||||
package com.dre.brewery.integration;
|
||||
|
||||
import com.dre.brewery.Barrel;
|
||||
import com.dre.brewery.utility.LegacyUtil;
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.api.events.barrel.BarrelAccessEvent;
|
||||
import com.dre.brewery.api.events.barrel.BarrelDestroyEvent;
|
||||
import com.dre.brewery.api.events.barrel.BarrelRemoveEvent;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import com.dre.brewery.integration.barrel.GriefPreventionBarrel;
|
||||
import com.dre.brewery.integration.barrel.LWCBarrel;
|
||||
import com.dre.brewery.integration.barrel.LogBlockBarrel;
|
||||
import com.dre.brewery.integration.item.MMOItemsPluginItem;
|
||||
import com.dre.brewery.recipe.BCauldronRecipe;
|
||||
import com.dre.brewery.recipe.RecipeItem;
|
||||
import com.dre.brewery.utility.LegacyUtil;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.item.NBTItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class IntegrationListener implements Listener {
|
||||
@ -173,4 +185,36 @@ public class IntegrationListener implements Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void onInteract(PlayerInteractEvent event) {
|
||||
// Cancel the Interact Event early, so MMOItems does not act before us and consume the item when trying to add item to Cauldron
|
||||
if (!P.use1_9) return;
|
||||
if (BConfig.hasMMOItems == null) {
|
||||
BConfig.hasMMOItems = P.p.getServer().getPluginManager().isPluginEnabled("MMOItems");
|
||||
}
|
||||
if (!BConfig.hasMMOItems) return;
|
||||
try {
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.hasItem() && event.getHand() == EquipmentSlot.HAND) {
|
||||
if (event.getClickedBlock() != null && event.getClickedBlock().getType() == Material.CAULDRON) {
|
||||
NBTItem item = MMOItems.plugin.getNMS().getNBTItem(event.getItem());
|
||||
if (item.hasType()) {
|
||||
for (RecipeItem rItem : BCauldronRecipe.acceptedCustom) {
|
||||
if (rItem instanceof MMOItemsPluginItem) {
|
||||
MMOItemsPluginItem mmo = ((MMOItemsPluginItem) rItem);
|
||||
if (mmo.matches(event.getItem())) {
|
||||
event.setCancelled(true);
|
||||
P.p.playerListener.onPlayerInteract(event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
P.p.errorLog("Could not check MMOItems for Item");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.dre.brewery.integration;
|
||||
package com.dre.brewery.integration.barrel;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -13,7 +13,7 @@ import vg.civcraft.mc.citadel.reinforcement.Reinforcement;
|
||||
|
||||
/**
|
||||
* Basic Citadel support to prevent randos from stealing your barrel aging brews
|
||||
*
|
||||
*
|
||||
* @author ProgrammerDan
|
||||
*/
|
||||
public class CitadelBarrel {
|
||||
@ -21,11 +21,11 @@ public class CitadelBarrel {
|
||||
|
||||
public static boolean checkAccess(Player player, Block sign) {
|
||||
ReinforcementManager manager = Citadel.getReinforcementManager();
|
||||
|
||||
|
||||
Reinforcement rein = manager.getReinforcement(sign);
|
||||
|
||||
|
||||
if (rein == null) return true; // no protections in place.
|
||||
|
||||
|
||||
if (rein instanceof PlayerReinforcement) {
|
||||
PlayerReinforcement prein = (PlayerReinforcement) rein;
|
||||
if (prein.canAccessChests(player)) {
|
||||
@ -35,7 +35,7 @@ public class CitadelBarrel {
|
||||
return true;
|
||||
}
|
||||
// no support for multiblock atm, would require namelayer support.
|
||||
|
||||
|
||||
// special locked, or no access.
|
||||
brewery.msg(player, brewery.languageReader.get("Error_NoBarrelAccess"));
|
||||
return false;
|
@ -1,4 +1,4 @@
|
||||
package com.dre.brewery.integration;
|
||||
package com.dre.brewery.integration.barrel;
|
||||
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.api.events.barrel.BarrelAccessEvent;
|
@ -1,4 +1,4 @@
|
||||
package com.dre.brewery.integration;
|
||||
package com.dre.brewery.integration.barrel;
|
||||
|
||||
import com.dre.brewery.Barrel;
|
||||
import com.dre.brewery.P;
|
@ -1,4 +1,4 @@
|
||||
package com.dre.brewery.integration;
|
||||
package com.dre.brewery.integration.barrel;
|
||||
|
||||
import com.dre.brewery.utility.LegacyUtil;
|
||||
import com.dre.brewery.P;
|
@ -1,4 +1,4 @@
|
||||
package com.dre.brewery.integration;
|
||||
package com.dre.brewery.integration.barrel;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
@ -1,4 +1,4 @@
|
||||
package com.dre.brewery.integration;
|
||||
package com.dre.brewery.integration.barrel;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
@ -1,4 +1,4 @@
|
||||
package com.dre.brewery.integration;
|
||||
package com.dre.brewery.integration.barrel;
|
||||
|
||||
|
||||
import com.sk89q.worldguard.bukkit.RegionQuery;
|
@ -1,4 +1,4 @@
|
||||
package com.dre.brewery.integration;
|
||||
package com.dre.brewery.integration.barrel;
|
||||
|
||||
|
||||
import org.bukkit.block.Block;
|
30
src/com/dre/brewery/integration/item/BreweryPluginItem.java
Normal file
30
src/com/dre/brewery/integration/item/BreweryPluginItem.java
Normal file
@ -0,0 +1,30 @@
|
||||
package com.dre.brewery.integration.item;
|
||||
|
||||
import com.dre.brewery.Brew;
|
||||
import com.dre.brewery.recipe.BRecipe;
|
||||
import com.dre.brewery.recipe.PluginItem;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
/**
|
||||
* For recipes that use Brewery Items as input
|
||||
*/
|
||||
public class BreweryPluginItem extends PluginItem {
|
||||
|
||||
// When implementing this, put Brewery as softdepend in your plugin.yml!
|
||||
// We're calling this as server start:
|
||||
// PluginItem.registerForConfig("brewery", BreweryPluginItem::new);
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
Brew brew = Brew.get(item);
|
||||
if (brew != null) {
|
||||
BRecipe recipe = brew.getCurrentRecipe();
|
||||
if (recipe != null) {
|
||||
return recipe.getRecipeName().equalsIgnoreCase(getItemId()) || recipe.getName(10).equalsIgnoreCase(getItemId());
|
||||
}
|
||||
return ChatColor.stripColor(item.getItemMeta().getDisplayName()).equalsIgnoreCase(getItemId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
32
src/com/dre/brewery/integration/item/MMOItemsPluginItem.java
Normal file
32
src/com/dre/brewery/integration/item/MMOItemsPluginItem.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.dre.brewery.integration.item;
|
||||
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import com.dre.brewery.recipe.PluginItem;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.item.NBTItem;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class MMOItemsPluginItem extends PluginItem {
|
||||
|
||||
// When implementing this, put Brewery as softdepend in your plugin.yml!
|
||||
// We're calling this as server start:
|
||||
// PluginItem.registerForConfig("mmoitems", MMOItemsPluginItem::new);
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
if (BConfig.hasMMOItems == null) {
|
||||
BConfig.hasMMOItems = P.p.getServer().getPluginManager().isPluginEnabled("MMOItems");
|
||||
}
|
||||
if (!BConfig.hasMMOItems) return false;
|
||||
|
||||
try {
|
||||
NBTItem nbtItem = MMOItems.plugin.getNMS().getNBTItem(item);
|
||||
return nbtItem.hasType() && nbtItem.getString("MMOITEMS_ITEM_ID").equalsIgnoreCase(getItemId());
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
P.p.errorLog("Could not check MMOItems for Item ID");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
35
src/com/dre/brewery/integration/item/SlimefunPluginItem.java
Normal file
35
src/com/dre/brewery/integration/item/SlimefunPluginItem.java
Normal file
@ -0,0 +1,35 @@
|
||||
package com.dre.brewery.integration.item;
|
||||
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import com.dre.brewery.recipe.PluginItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class SlimefunPluginItem extends PluginItem {
|
||||
|
||||
// When implementing this, put Brewery as softdepend in your plugin.yml!
|
||||
// We're calling this as server start:
|
||||
// PluginItem.registerForConfig("slimefun", SlimefunPluginItem::new);
|
||||
// PluginItem.registerForConfig("exoticgarden", SlimefunPluginItem::new);
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
if (BConfig.hasSlimefun == null) {
|
||||
BConfig.hasSlimefun = P.p.getServer().getPluginManager().isPluginEnabled("Slimefun");
|
||||
}
|
||||
if (!BConfig.hasSlimefun) return false;
|
||||
|
||||
try {
|
||||
SlimefunItem sfItem = SlimefunItem.getByItem(item);
|
||||
if (sfItem != null) {
|
||||
return sfItem.getID().equalsIgnoreCase(getItemId());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
P.p.errorLog("Could not check Slimefun for Item ID");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package com.dre.brewery.listeners;
|
||||
import com.dre.brewery.*;
|
||||
import com.dre.brewery.api.events.brew.BrewModifyEvent;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import com.dre.brewery.recipe.BRecipe;
|
||||
import com.dre.brewery.utility.BUtil;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
|
@ -19,9 +19,9 @@ public class WorldListener implements Listener {
|
||||
World world = event.getWorld();
|
||||
|
||||
if (world.getName().startsWith("DXL_")) {
|
||||
BData.loadWorldData(BUtil.getDxlName(world.getName()), world);
|
||||
BData.loadWorldData(BUtil.getDxlName(world.getName()), world, null);
|
||||
} else {
|
||||
BData.loadWorldData(world.getUID().toString(), world);
|
||||
BData.loadWorldData(world.getUID().toString(), world, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.dre.brewery.lore;
|
||||
|
||||
import com.dre.brewery.BEffect;
|
||||
import com.dre.brewery.recipe.BEffect;
|
||||
import com.dre.brewery.BIngredients;
|
||||
import com.dre.brewery.BRecipe;
|
||||
import com.dre.brewery.recipe.BRecipe;
|
||||
import com.dre.brewery.Brew;
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
|
@ -1,11 +1,10 @@
|
||||
package com.dre.brewery;
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import com.dre.brewery.utility.CustomItem;
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.utility.PotionColor;
|
||||
import com.dre.brewery.utility.Tuple;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -17,10 +16,12 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class BCauldronRecipe {
|
||||
public static List<BCauldronRecipe> recipes = new ArrayList<>();
|
||||
public static Set<Material> acceptedMaterials = EnumSet.noneOf(Material.class);
|
||||
public static List<RecipeItem> acceptedCustom = new ArrayList<>(); // All accepted custom and other items
|
||||
public static Set<Material> acceptedSimple = EnumSet.noneOf(Material.class); // All accepted simple items
|
||||
public static Set<Material> acceptedMaterials = EnumSet.noneOf(Material.class); // Fast cache for all accepted Materials
|
||||
|
||||
private String name;
|
||||
private List<Tuple<CustomItem, Integer>> ingredients; // Item and amount
|
||||
private List<RecipeItem> ingredients;
|
||||
//private List<String> particles
|
||||
private PotionColor color;
|
||||
private List<String> lore;
|
||||
@ -72,7 +73,7 @@ public class BCauldronRecipe {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Tuple<CustomItem, Integer>> getIngredients() {
|
||||
public List<RecipeItem> getIngredients() {
|
||||
return ingredients;
|
||||
}
|
||||
|
||||
@ -92,28 +93,26 @@ public class BCauldronRecipe {
|
||||
* If all Ingredients and their amounts are equal, returns 10
|
||||
* Returns something between 0 and 10 if all ingredients present, but differing amounts, depending on how much the amount differs.
|
||||
*/
|
||||
public float getIngredientMatch(List<ItemStack> items) {
|
||||
public float getIngredientMatch(List<Ingredient> items) {
|
||||
if (items.size() < ingredients.size()) {
|
||||
return 0;
|
||||
}
|
||||
float match = 10;
|
||||
search: for (Tuple<CustomItem, Integer> ing : ingredients) {
|
||||
for (ItemStack item : items) {
|
||||
if (ing.a().matches(item)) {
|
||||
double difference = Math.abs(ing.b() - item.getAmount());
|
||||
search: for (RecipeItem recipeIng : ingredients) {
|
||||
for (Ingredient ing : items) {
|
||||
if (recipeIng.matches(ing)) {
|
||||
double difference = Math.abs(recipeIng.getAmount() - ing.getAmount());
|
||||
if (difference >= 1000) {
|
||||
return 0;
|
||||
}
|
||||
// The Item Amount is the determining part here, the higher the better.
|
||||
// But let the difference in amount to what the recipe expects have a tiny factor as well.
|
||||
// This way for the same amount, the recipe with the lower difference wins.
|
||||
double factor = item.getAmount() * (1.0 - (difference / 1000.0)) ;
|
||||
double factor = ing.getAmount() * (1.0 - (difference / 1000.0)) ;
|
||||
//double mod = 0.1 + (0.9 * Math.exp(-0.03 * difference)); // logarithmic curve from 1 to 0.1
|
||||
double mod = 1 + (0.9 * -Math.exp(-0.03 * factor)); // logarithmic curve from 0.1 to 1, small for a low factor
|
||||
|
||||
P.p.debugLog("Mod for " + ing.a() + "/" + ing.b() + ": " + mod);
|
||||
assert mod >= 0.1;
|
||||
assert mod <= 1; // TODO Test
|
||||
P.p.debugLog("Mod for " + recipeIng + ": " + mod);
|
||||
|
||||
|
||||
|
||||
@ -138,4 +137,40 @@ public class BCauldronRecipe {
|
||||
public String toString() {
|
||||
return "BCauldronRecipe{" + name + '}';
|
||||
}
|
||||
|
||||
/*public static boolean acceptItem(ItemStack item) {
|
||||
if (acceptedMaterials.contains(item.getType())) {
|
||||
// Extremely fast way to check for most items
|
||||
return true;
|
||||
}
|
||||
if (!item.hasItemMeta()) {
|
||||
return false;
|
||||
}
|
||||
// If the Item is not on the list, but customized, we have to do more checks
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
assert meta != null;
|
||||
if (meta.hasDisplayName() || meta.hasLore()) {
|
||||
for (BItem bItem : acceptedCustom) {
|
||||
if (bItem.matches(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static RecipeItem acceptItem(ItemStack item) {
|
||||
if (!acceptedMaterials.contains(item.getType()) && !item.hasItemMeta()) {
|
||||
// Extremely fast way to check for most items
|
||||
return null;
|
||||
}
|
||||
// If the Item is on the list, or customized, we have to do more checks
|
||||
for (RecipeItem rItem : acceptedItems) {
|
||||
if (rItem.matches(item)) {
|
||||
return rItem;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}*/
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.dre.brewery;
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.utility.BUtil;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
@ -1,7 +1,9 @@
|
||||
package com.dre.brewery;
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import com.dre.brewery.BIngredients;
|
||||
import com.dre.brewery.Brew;
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import com.dre.brewery.utility.CustomItem;
|
||||
import com.dre.brewery.utility.PotionColor;
|
||||
import com.dre.brewery.utility.Tuple;
|
||||
import org.bukkit.Material;
|
||||
@ -12,14 +14,13 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BRecipe {
|
||||
|
||||
public static List<BRecipe> recipes = new ArrayList<>();
|
||||
|
||||
private String[] name;
|
||||
private List<Tuple<CustomItem, Integer>> ingredients = new ArrayList<>(); // Items and amounts
|
||||
private List<RecipeItem> ingredients = new ArrayList<>(); // Items and amounts
|
||||
private int cookingTime; // time to cook in cauldron
|
||||
private byte distillruns; // runs through the brewer
|
||||
private int distillTime; // time for one distill run in seconds
|
||||
@ -96,7 +97,7 @@ public class BRecipe {
|
||||
return recipe;
|
||||
}
|
||||
|
||||
public static List<Tuple<CustomItem, Integer>> loadIngredients(ConfigurationSection cfg, String recipeId) {
|
||||
public static List<RecipeItem> loadIngredients(ConfigurationSection cfg, String recipeId) {
|
||||
List<String> ingredientsList;
|
||||
if (cfg.isString(recipeId + ".ingredients")) {
|
||||
ingredientsList = new ArrayList<>(1);
|
||||
@ -107,7 +108,7 @@ public class BRecipe {
|
||||
if (ingredientsList == null) {
|
||||
return null;
|
||||
}
|
||||
List<Tuple<CustomItem, Integer>> ingredients = new ArrayList<>(ingredientsList.size());
|
||||
List<RecipeItem> ingredients = new ArrayList<>(ingredientsList.size());
|
||||
listLoop: for (String item : ingredientsList) {
|
||||
String[] ingredParts = item.split("/");
|
||||
int amount = 1;
|
||||
@ -121,19 +122,51 @@ public class BRecipe {
|
||||
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("\\.");
|
||||
}
|
||||
|
||||
// Check if this is a Plugin Item
|
||||
String[] pluginItem = matParts[0].split(":");
|
||||
if (pluginItem.length > 1) {
|
||||
RecipeItem custom = PluginItem.fromConfig(pluginItem[0], pluginItem[1]);
|
||||
if (custom != null) {
|
||||
custom.setAmount(amount);
|
||||
custom.makeImmutable();
|
||||
ingredients.add(custom);
|
||||
BCauldronRecipe.acceptedCustom.add(custom);
|
||||
continue;
|
||||
} else {
|
||||
// TODO Maybe load later ie on first use of recipe?
|
||||
P.p.errorLog(recipeId + ": Could not Find Plugin: " + ingredParts[1]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to find this Ingredient as Custom Item
|
||||
for (CustomItem custom : BConfig.customItems) {
|
||||
if (custom.getId().equalsIgnoreCase(matParts[0])) {
|
||||
ingredients.add(new Tuple<>(custom, amount));
|
||||
BCauldronRecipe.acceptedMaterials.addAll(custom.getMaterials());
|
||||
for (RecipeItem custom : BConfig.customItems) {
|
||||
if (custom.getConfigId().equalsIgnoreCase(matParts[0])) {
|
||||
custom = custom.getMutableCopy();
|
||||
custom.setAmount(amount);
|
||||
custom.makeImmutable();
|
||||
ingredients.add(custom);
|
||||
if (custom.hasMaterials()) {
|
||||
BCauldronRecipe.acceptedMaterials.addAll(custom.getMaterials());
|
||||
}
|
||||
// Add it as acceptedCustom
|
||||
if (!BCauldronRecipe.acceptedCustom.contains(custom)) {
|
||||
BCauldronRecipe.acceptedCustom.add(custom);
|
||||
/*if (custom instanceof PluginItem || !custom.hasMaterials()) {
|
||||
BCauldronRecipe.acceptedCustom.add(custom);
|
||||
} else if (custom instanceof CustomMatchAnyItem) {
|
||||
CustomMatchAnyItem ma = (CustomMatchAnyItem) custom;
|
||||
if (ma.hasNames() || ma.hasLore()) {
|
||||
BCauldronRecipe.acceptedCustom.add(ma);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
continue listLoop;
|
||||
}
|
||||
}
|
||||
@ -163,14 +196,17 @@ public class BRecipe {
|
||||
}
|
||||
}
|
||||
if (mat != null) {
|
||||
CustomItem custom;
|
||||
RecipeItem rItem;
|
||||
if (durability > -1) {
|
||||
custom = CustomItem.asSimpleItem(mat, durability);
|
||||
rItem = new SimpleItem(mat, durability);
|
||||
} else {
|
||||
custom = CustomItem.asSimpleItem(mat);
|
||||
rItem = new SimpleItem(mat);
|
||||
}
|
||||
ingredients.add(new Tuple<>(custom, amount));
|
||||
rItem.setAmount(amount);
|
||||
rItem.makeImmutable();
|
||||
ingredients.add(rItem);
|
||||
BCauldronRecipe.acceptedMaterials.add(mat);
|
||||
BCauldronRecipe.acceptedSimple.add(mat);
|
||||
} else {
|
||||
P.p.errorLog(recipeId + ": Unknown Material: " + ingredParts[0]);
|
||||
return null;
|
||||
@ -297,14 +333,14 @@ public class BRecipe {
|
||||
}
|
||||
|
||||
// true if given list misses an ingredient
|
||||
public boolean isMissingIngredients(List<ItemStack> list) {
|
||||
public boolean isMissingIngredients(List<Ingredient> list) {
|
||||
if (list.size() < ingredients.size()) {
|
||||
return true;
|
||||
}
|
||||
for (Tuple<CustomItem, Integer> ingredient : ingredients) {
|
||||
for (RecipeItem rItem : ingredients) {
|
||||
boolean matches = false;
|
||||
for (ItemStack used : list) {
|
||||
if (ingredient.a().matches(used)) {
|
||||
for (Ingredient used : list) {
|
||||
if (rItem.matches(used)) {
|
||||
matches = true;
|
||||
break;
|
||||
}
|
||||
@ -327,13 +363,18 @@ public class BRecipe {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Brew from this Recipe with best values. Quality can be set, but will reset to 10 if put in a barrel
|
||||
* Create a Brew from this Recipe with best values. Quality can be set, but will reset to 10 if unset immutable and put in a barrel
|
||||
*
|
||||
* @param quality The Quality of the Brew
|
||||
* @return The created Brew
|
||||
*/
|
||||
public Brew createBrew(int quality) {
|
||||
List<ItemStack> list = ingredients.stream().map(ing -> ing.a().createDummy(ing.b())).collect(Collectors.toList());
|
||||
List<Ingredient> list = new ArrayList<>(ingredients.size());
|
||||
for (RecipeItem rItem : ingredients) {
|
||||
Ingredient ing = rItem.toIngredientGeneric();
|
||||
ing.setAmount(rItem.getAmount());
|
||||
list.add(ing);
|
||||
}
|
||||
|
||||
BIngredients bIngredients = new BIngredients(list, cookingTime);
|
||||
|
||||
@ -343,11 +384,21 @@ public class BRecipe {
|
||||
|
||||
// Getter
|
||||
|
||||
// how many of a specific ingredient in the recipe
|
||||
public int amountOf(Ingredient ing) {
|
||||
for (RecipeItem rItem : ingredients) {
|
||||
if (rItem.matches(ing)) {
|
||||
return rItem.getAmount();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// how many of a specific ingredient in the recipe
|
||||
public int amountOf(ItemStack item) {
|
||||
for (Tuple<CustomItem, Integer> ingredient : ingredients) {
|
||||
if (ingredient.a().matches(item)) {
|
||||
return ingredient.b();
|
||||
for (RecipeItem rItem : ingredients) {
|
||||
if (rItem.matches(item)) {
|
||||
return rItem.getAmount();
|
||||
}
|
||||
}
|
||||
return 0;
|
291
src/com/dre/brewery/recipe/CustomItem.java
Normal file
291
src/com/dre/brewery/recipe/CustomItem.java
Normal file
@ -0,0 +1,291 @@
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Minecraft Item with custon name and lore.
|
||||
* Mostly used for Custom Items of the Config, but also for general custom items
|
||||
*/
|
||||
public class CustomItem extends RecipeItem implements Ingredient {
|
||||
|
||||
private Material mat;
|
||||
private String name;
|
||||
private List<String> lore;
|
||||
|
||||
public CustomItem() {
|
||||
}
|
||||
|
||||
public CustomItem(Material mat) {
|
||||
this.mat = mat;
|
||||
}
|
||||
|
||||
public CustomItem(Material mat, String name, List<String> lore) {
|
||||
this.mat = mat;
|
||||
this.name = name;
|
||||
this.lore = lore;
|
||||
}
|
||||
|
||||
public CustomItem(ItemStack item) {
|
||||
mat = item.getType();
|
||||
if (!item.hasItemMeta()) {
|
||||
return;
|
||||
}
|
||||
ItemMeta itemMeta = item.getItemMeta();
|
||||
assert itemMeta != null;
|
||||
if (itemMeta.hasDisplayName()) {
|
||||
name = itemMeta.getDisplayName();
|
||||
}
|
||||
if (itemMeta.hasLore()) {
|
||||
lore = itemMeta.getLore();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMaterials() {
|
||||
return mat != null;
|
||||
}
|
||||
|
||||
public boolean hasName() {
|
||||
return name != null;
|
||||
}
|
||||
|
||||
public boolean hasLore() {
|
||||
return lore != null && !lore.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Material> getMaterials() {
|
||||
List<Material> l = new ArrayList<>(1);
|
||||
l.add(mat);
|
||||
return l;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Material getMaterial() {
|
||||
return mat;
|
||||
}
|
||||
|
||||
protected void setMat(Material mat) {
|
||||
this.mat = mat;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getLore() {
|
||||
return lore;
|
||||
}
|
||||
|
||||
protected void setLore(List<String> lore) {
|
||||
this.lore = lore;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ingredient toIngredient(ItemStack forItem) {
|
||||
return ((CustomItem) getMutableCopy());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ingredient toIngredientGeneric() {
|
||||
return ((CustomItem) getMutableCopy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Ingredient ingredient) {
|
||||
if (isSimilar(ingredient)) {
|
||||
return true;
|
||||
}
|
||||
if (ingredient instanceof RecipeItem) {
|
||||
RecipeItem rItem = ((RecipeItem) ingredient);
|
||||
if (rItem instanceof SimpleItem) {
|
||||
// If the recipe item is just a simple item, only match if we also only define material
|
||||
// If this is a custom item with more info, we don't want to match a simple item
|
||||
return hasMaterials() && !hasLore() && !hasName() && getMaterial() == ((SimpleItem) rItem).getMaterial();
|
||||
} else if (rItem instanceof CustomItem) {
|
||||
// If the other is a CustomItem as well and not Similar to ours, it might have more data and we still match
|
||||
CustomItem other = ((CustomItem) rItem);
|
||||
if (mat == null || mat == other.mat) {
|
||||
if (!hasName() || (other.name != null && name.equalsIgnoreCase(other.name))) {
|
||||
return !hasLore() || lore == other.lore || (other.hasLore() && matchLore(other.lore));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
if (mat != null) {
|
||||
if (item.getType() != mat) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (name == null && !hasLore()) {
|
||||
return true;
|
||||
}
|
||||
if (!item.hasItemMeta()) {
|
||||
return false;
|
||||
}
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
assert meta != null;
|
||||
if (name != null) {
|
||||
if (!meta.hasDisplayName() || !name.equalsIgnoreCase(meta.getDisplayName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLore()) {
|
||||
if (!meta.hasLore()) {
|
||||
return false;
|
||||
}
|
||||
return matchLore(meta.getLore());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this item has lore that matches the given lore.
|
||||
* It matches if our lore is contained in the given lore consecutively, ignoring color of the given lore.
|
||||
*
|
||||
* @param usedLore The given lore to match
|
||||
* @return True if the given lore contains our lore consecutively
|
||||
*/
|
||||
public boolean matchLore(List<String> usedLore) {
|
||||
if (lore == null) return true;
|
||||
int lastIndex = 0;
|
||||
boolean foundFirst = false;
|
||||
for (String line : lore) {
|
||||
do {
|
||||
if (lastIndex == usedLore.size()) {
|
||||
// There is more in lore than in usedLore, bad
|
||||
return false;
|
||||
}
|
||||
String usedLine = usedLore.get(lastIndex);
|
||||
if (line.equalsIgnoreCase(usedLine) || line.equalsIgnoreCase(ChatColor.stripColor(usedLine))) {
|
||||
// If the line is correct, we have found our first and we want all consecutive lines to also equal
|
||||
foundFirst = true;
|
||||
} else if (foundFirst) {
|
||||
// If a consecutive line is not equal, thats bad
|
||||
return false;
|
||||
}
|
||||
lastIndex++;
|
||||
// If we once found one correct line, iterate over 'lore' consecutively
|
||||
} while (!foundFirst);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// We don't compare id here
|
||||
@Override
|
||||
public boolean isSimilar(Ingredient item) {
|
||||
if (this == item) {
|
||||
return true;
|
||||
}
|
||||
if (item instanceof CustomItem) {
|
||||
CustomItem ci = ((CustomItem) item);
|
||||
return mat == ci.mat && Objects.equals(name, ci.name) && Objects.equals(lore, ci.lore);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!super.equals(obj)) return false;
|
||||
if (obj instanceof CustomItem) {
|
||||
return isSimilar(((CustomItem) obj));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), mat, name, lore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CustomItem{" +
|
||||
"id=" + getConfigId() +
|
||||
", mat=" + (mat != null ? mat.name().toLowerCase() : "null") +
|
||||
", name='" + name + '\'' +
|
||||
", loresize: " + (lore != null ? lore.size() : 0) +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveTo(DataOutputStream out) throws IOException {
|
||||
out.writeUTF("CI");
|
||||
if (mat != null) {
|
||||
out.writeBoolean(true);
|
||||
out.writeUTF(mat.name());
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
}
|
||||
if (name != null) {
|
||||
out.writeBoolean(true);
|
||||
out.writeUTF(name);
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
}
|
||||
if (lore != null) {
|
||||
short size = (short) Math.min(lore.size(), Short.MAX_VALUE);
|
||||
out.writeShort(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
out.writeUTF(lore.get(i));
|
||||
}
|
||||
} else {
|
||||
out.writeShort(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static CustomItem loadFrom(ItemLoader loader) {
|
||||
try {
|
||||
DataInputStream in = loader.getInputStream();
|
||||
CustomItem item = new CustomItem();
|
||||
if (in.readBoolean()) {
|
||||
item.mat = Material.getMaterial(in.readUTF());
|
||||
}
|
||||
if (in.readBoolean()) {
|
||||
item.name = in.readUTF();
|
||||
}
|
||||
short size = in.readShort();
|
||||
if (size > 0) {
|
||||
item.lore = new ArrayList<>(size);
|
||||
for (short i = 0; i < size; i++) {
|
||||
item.lore.add(in.readUTF());
|
||||
}
|
||||
}
|
||||
return item;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Needs to be called at Server start
|
||||
public static void registerItemLoader() {
|
||||
Ingredient.registerForItemLoader("CI", CustomItem::loadFrom);
|
||||
}
|
||||
}
|
231
src/com/dre/brewery/recipe/CustomMatchAnyItem.java
Normal file
231
src/com/dre/brewery/recipe/CustomMatchAnyItem.java
Normal file
@ -0,0 +1,231 @@
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Custom Item that matches any one of the given info.
|
||||
* Does not implement Ingredient, as it can not directly be added to an ingredient
|
||||
*/
|
||||
public class CustomMatchAnyItem extends RecipeItem {
|
||||
|
||||
private List<Material> materials;
|
||||
private List<String> names;
|
||||
private List<String> lore;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasMaterials() {
|
||||
return materials != null && !materials.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasNames() {
|
||||
return names != null && !names.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasLore() {
|
||||
return lore != null && !lore.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<Material> getMaterials() {
|
||||
return materials;
|
||||
}
|
||||
|
||||
protected void setMaterials(List<Material> materials) {
|
||||
this.materials = materials;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
protected void setNames(List<String> names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getLore() {
|
||||
return lore;
|
||||
}
|
||||
|
||||
protected void setLore(List<String> lore) {
|
||||
this.lore = lore;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ingredient toIngredient(ItemStack forItem) {
|
||||
// We only use the one part of this item that actually matched the given item to add to ingredients
|
||||
Material mat = getMaterialMatch(forItem);
|
||||
if (mat != null) {
|
||||
return new CustomItem(mat);
|
||||
}
|
||||
String name = getNameMatch(forItem);
|
||||
if (name != null) {
|
||||
return new CustomItem(null, name, null);
|
||||
}
|
||||
String l = getLoreMatch(forItem);
|
||||
if (l != null) {
|
||||
List<String> lore = new ArrayList<>(1);
|
||||
lore.add(l);
|
||||
return new CustomItem(null, null, lore);
|
||||
}
|
||||
|
||||
// Shouldnt happen
|
||||
return new SimpleItem(Material.GOLDEN_HOE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ingredient toIngredientGeneric() {
|
||||
if (hasMaterials()) {
|
||||
return new CustomItem(materials.get(0));
|
||||
}
|
||||
if (hasNames()) {
|
||||
return new CustomItem(null, names.get(0), null);
|
||||
}
|
||||
if (hasLore()) {
|
||||
List<String> l = new ArrayList<>(1);
|
||||
l.add(lore.get(0));
|
||||
return new CustomItem(null, null, l);
|
||||
}
|
||||
|
||||
// Shouldnt happen
|
||||
return new SimpleItem(Material.GOLDEN_HOE);
|
||||
}
|
||||
|
||||
public Material getMaterialMatch(ItemStack item) {
|
||||
if (!hasMaterials()) return null;
|
||||
|
||||
Material usedMat = item.getType();
|
||||
for (Material mat : materials) {
|
||||
if (usedMat == mat) {
|
||||
return mat;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getNameMatch(ItemStack item) {
|
||||
if (!item.hasItemMeta() || !hasNames()) {
|
||||
return null;
|
||||
}
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
assert meta != null;
|
||||
if (meta.hasDisplayName()) {
|
||||
return getNameMatch(meta.getDisplayName());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getNameMatch(String usedName) {
|
||||
if (!hasNames()) return null;
|
||||
|
||||
for (String name : names) {
|
||||
if (name.equalsIgnoreCase(usedName)) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getLoreMatch(ItemStack item) {
|
||||
if (!item.hasItemMeta() || !hasLore()) {
|
||||
return null;
|
||||
}
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
assert meta != null;
|
||||
if (meta.hasLore()) {
|
||||
return getLoreMatch(meta.getLore());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getLoreMatch(List<String> usedLore) {
|
||||
if (!hasLore()) return null;
|
||||
|
||||
for (String line : this.lore) {
|
||||
for (String usedLine : usedLore) {
|
||||
if (line.equalsIgnoreCase(usedLine) || line.equalsIgnoreCase(ChatColor.stripColor(usedLine))) {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
if (getMaterialMatch(item) != null) {
|
||||
return true;
|
||||
}
|
||||
if (getNameMatch(item) != null) {
|
||||
return true;
|
||||
}
|
||||
return getLoreMatch(item) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Ingredient ingredient) {
|
||||
// Ingredient can not be CustomMatchAnyItem, so we don't need to/can't check for similarity.
|
||||
if (ingredient instanceof CustomItem) {
|
||||
// If the custom item has any of our data, we match
|
||||
CustomItem ci = ((CustomItem) ingredient);
|
||||
if (hasMaterials() && ci.hasMaterials()) {
|
||||
if (materials.contains(ci.getMaterial())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (hasNames() && ci.hasName()) {
|
||||
if (getNameMatch(ci.getName()) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (hasLore() && ci.hasLore()) {
|
||||
return getLoreMatch(ci.getLore()) != null;
|
||||
}
|
||||
} else if (ingredient instanceof SimpleItem) {
|
||||
// If we contain the Material of the Simple Item, we match
|
||||
SimpleItem si = (SimpleItem) ingredient;
|
||||
return hasMaterials() && materials.contains(si.getMaterial());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
CustomMatchAnyItem that = (CustomMatchAnyItem) o;
|
||||
return Objects.equals(materials, that.materials) &&
|
||||
Objects.equals(names, that.names) &&
|
||||
Objects.equals(lore, that.lore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), materials, names, lore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CustomMatchAnyItem{" +
|
||||
"id=" + getConfigId() +
|
||||
", materials: " + (materials != null ? materials.size() : 0) +
|
||||
", names:" + (names != null ? names.size() : 0) +
|
||||
", loresize: " + (lore != null ? lore.size() : 0) +
|
||||
'}';
|
||||
}
|
||||
}
|
88
src/com/dre/brewery/recipe/Ingredient.java
Normal file
88
src/com/dre/brewery/recipe/Ingredient.java
Normal file
@ -0,0 +1,88 @@
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Item used in a BIngredients, inside BCauldron or Brew.
|
||||
* Represents the Items used as ingredients in the Brewing process
|
||||
* Can be a copy of a recipe item
|
||||
* Will be saved and loaded with a DataStream
|
||||
* Each implementing class needs to register a static function as Item Loader
|
||||
*/
|
||||
public interface Ingredient {
|
||||
|
||||
Map<String, Function<ItemLoader, Ingredient>> LOADERS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Register a Static function as function that takes an ItemLoader, containing a DataInputStream.
|
||||
* Using the Stream it constructs a corresponding Ingredient for the chosen SaveID
|
||||
*
|
||||
* @param saveID The SaveID should be a small identifier like "AB"
|
||||
* @param loadFct The Static Function that loads the Item, i.e.
|
||||
* public static AItem loadFrom(ItemLoader loader)
|
||||
*/
|
||||
static void registerForItemLoader(String saveID, Function<ItemLoader, Ingredient> loadFct) {
|
||||
LOADERS.put(saveID, loadFct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the ItemLoader
|
||||
*
|
||||
* @param saveID the chosen SaveID
|
||||
*/
|
||||
static void unRegisterItemLoader(String saveID) {
|
||||
LOADERS.remove(saveID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Saves this Ingredient to the DataOutputStream.
|
||||
* The first data HAS to be storing the SaveID like:
|
||||
* out.writeUTF("AB");
|
||||
* Amount will be saved automatically and does not have to be saved here.
|
||||
* Saving is done to Brew or for BCauldron into data.yml
|
||||
*
|
||||
* @param out The outputstream to write to
|
||||
* @throws IOException Any IOException
|
||||
*/
|
||||
void saveTo(DataOutputStream out) throws IOException;
|
||||
|
||||
int getAmount();
|
||||
|
||||
void setAmount(int amount);
|
||||
|
||||
/**
|
||||
* Does this Ingredient match the given ItemStack
|
||||
*
|
||||
* @param item The given ItemStack to match
|
||||
* @return true if all required data is contained on the item
|
||||
*/
|
||||
boolean matches(ItemStack item);
|
||||
|
||||
/*
|
||||
* Does this Item match the given RecipeItem.
|
||||
* An IngredientItem matches a RecipeItem if all required info of the RecipeItem are fulfilled on this IngredientItem
|
||||
* This does not imply that the same holds the other way round, as this item might have more info than needed
|
||||
*
|
||||
*
|
||||
* @param recipeItem The recipeItem whose requirements need to be fulfilled
|
||||
* @return True if this matches the required info of the recipeItem
|
||||
*/
|
||||
//boolean matches(RecipeItem recipeItem);
|
||||
|
||||
/**
|
||||
* The other Ingredient is Similar if it is equal except amount
|
||||
*
|
||||
* @param item The item to check similarity with
|
||||
* @return True if this is equal to item except for amount
|
||||
*/
|
||||
boolean isSimilar(Ingredient item);
|
||||
|
||||
|
||||
}
|
28
src/com/dre/brewery/recipe/ItemLoader.java
Normal file
28
src/com/dre/brewery/recipe/ItemLoader.java
Normal file
@ -0,0 +1,28 @@
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
|
||||
public class ItemLoader {
|
||||
|
||||
private final int version;
|
||||
private final DataInputStream in;
|
||||
private final String saveID;
|
||||
|
||||
public ItemLoader(int version, DataInputStream in, String saveID) {
|
||||
this.version = version;
|
||||
this.in = in;
|
||||
this.saveID = saveID;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public DataInputStream getInputStream() {
|
||||
return in;
|
||||
}
|
||||
|
||||
public String getSaveID() {
|
||||
return saveID;
|
||||
}
|
||||
}
|
213
src/com/dre/brewery/recipe/PluginItem.java
Normal file
213
src/com/dre/brewery/recipe/PluginItem.java
Normal file
@ -0,0 +1,213 @@
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* An Item of a Recipe or as Ingredient in a Brew that corresponds to an item from another plugin.
|
||||
* See /integration/item for examples on how to extend this class.
|
||||
* This class stores items as name of the plugin and item id
|
||||
*/
|
||||
public abstract class PluginItem extends RecipeItem implements Ingredient {
|
||||
|
||||
private static Map<String, Supplier<PluginItem>> constructors = new HashMap<>();
|
||||
|
||||
private String plugin;
|
||||
private String itemId;
|
||||
|
||||
/**
|
||||
* New Empty PluginItem
|
||||
*/
|
||||
public PluginItem() {
|
||||
}
|
||||
|
||||
/**
|
||||
* New PluginItem with both fields already set
|
||||
*
|
||||
* @param plugin The name of the Plugin
|
||||
* @param itemId The ItemID
|
||||
*/
|
||||
public PluginItem(String plugin, String itemId) {
|
||||
this.plugin = plugin;
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasMaterials() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Material> getMaterials() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public String getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
protected void setPlugin(String plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
protected void setItemId(String itemId) {
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after Loading this Plugin Item from Config, or (by default) from Ingredients.
|
||||
* Allows Override to define custom actions after an Item was constructed
|
||||
*/
|
||||
protected void onConstruct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this PluginItem Match the other Ingredient.
|
||||
* By default it matches exactly when they are similar, i.e. also a PluginItem with same parameters
|
||||
*
|
||||
* @param ingredient The ingredient that needs to fulfill the requirements
|
||||
* @return True if the ingredient matches the required info of this
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(Ingredient ingredient) {
|
||||
return isSimilar(ingredient);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ingredient toIngredient(ItemStack forItem) {
|
||||
return ((PluginItem) getMutableCopy());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ingredient toIngredientGeneric() {
|
||||
return ((PluginItem) getMutableCopy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSimilar(Ingredient item) {
|
||||
if (item instanceof PluginItem) {
|
||||
return Objects.equals(plugin, ((PluginItem) item).plugin) && Objects.equals(itemId, ((PluginItem) item).itemId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
PluginItem item = (PluginItem) o;
|
||||
return Objects.equals(plugin, item.plugin) &&
|
||||
Objects.equals(itemId, item.itemId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), plugin, itemId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveTo(DataOutputStream out) throws IOException {
|
||||
out.writeUTF("PI");
|
||||
out.writeUTF(plugin);
|
||||
out.writeUTF(itemId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when loading this Plugin Item from Ingredients (of a Brew)
|
||||
* The default loading is the same as loading from Config
|
||||
*
|
||||
* @param loader The ItemLoader from which to load the data, use loader.getInputStream()
|
||||
* @return The constructed PluginItem
|
||||
*/
|
||||
public static PluginItem loadFrom(ItemLoader loader) {
|
||||
try {
|
||||
DataInputStream in = loader.getInputStream();
|
||||
String plugin = in.readUTF();
|
||||
String itemId = in.readUTF();
|
||||
PluginItem item = fromConfig(plugin, itemId);
|
||||
if (item == null) {
|
||||
// Plugin not found when loading from Item, use a generic PluginItem that never matches other items
|
||||
item = new PluginItem(plugin, itemId) {
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
return item;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Needs to be called at Server start
|
||||
* Registers the chosen SaveID and the loading Method for loading from Brew or BCauldron
|
||||
*/
|
||||
public static void registerItemLoader() {
|
||||
Ingredient.registerForItemLoader("PI", PluginItem::loadFrom);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when loading trying to find a config defined Plugin Item, or by default also when loading from ingredients
|
||||
* Will call a registered constructor matching the given plugin identifier
|
||||
*
|
||||
* @param plugin The Identifier of the Plugin used in the config
|
||||
* @param itemId The Identifier of the Item belonging to this Plugin used in the config
|
||||
* @return The Plugin Item if found, or null if there is no plugin for the given String
|
||||
*/
|
||||
@Nullable
|
||||
public static PluginItem fromConfig(String plugin, String itemId) {
|
||||
plugin = plugin.toLowerCase();
|
||||
if (constructors.containsKey(plugin)) {
|
||||
PluginItem item = constructors.get(plugin).get();
|
||||
item.setPlugin(plugin);
|
||||
item.setItemId(itemId);
|
||||
item.onConstruct();
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This needs to be called at Server Start before Brewery loads its data.
|
||||
* When implementing this, put Brewery as softdepend in your plugin.yml!
|
||||
* Registers a Constructor that returns a new or cloned instance of a PluginItem
|
||||
* This Constructor will be called when loading a Plugin Item from Config or by default from ingredients
|
||||
* After the Constructor is called, the plugin and itemid will be set on the new instance
|
||||
* Finally the onConstruct is called.
|
||||
*
|
||||
* @param pluginId The ID to use in the config
|
||||
* @param constructor The constructor i.e. YourPluginItem::new
|
||||
*/
|
||||
public static void registerForConfig(String pluginId, Supplier<PluginItem> constructor) {
|
||||
constructors.put(pluginId.toLowerCase(), constructor);
|
||||
}
|
||||
|
||||
public static void unRegisterForConfig(String pluginId) {
|
||||
constructors.remove(pluginId.toLowerCase());
|
||||
}
|
||||
|
||||
}
|
314
src/com/dre/brewery/recipe/RecipeItem.java
Normal file
314
src/com/dre/brewery/recipe/RecipeItem.java
Normal file
@ -0,0 +1,314 @@
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Item that can be used in a Recipe.
|
||||
* They are not necessarily only loaded from config
|
||||
* They are immutable if used in a recipe. If one implements Ingredient,
|
||||
* it can be used as mutable copy directly in a
|
||||
* BIngredients. Otherwise it needs to be converted to an Ingredient
|
||||
*/
|
||||
public abstract class RecipeItem implements Cloneable {
|
||||
|
||||
private String cfgId;
|
||||
private int amount;
|
||||
private boolean immutable = false;
|
||||
|
||||
|
||||
/**
|
||||
* Does this RecipeItem match the given ItemStack?
|
||||
* Used to determine if the given item corresponds to this recipeitem
|
||||
*
|
||||
* @param item The ItemStack for comparison
|
||||
* @return True if the given item matches this recipeItem
|
||||
*/
|
||||
public abstract boolean matches(ItemStack item);
|
||||
|
||||
/**
|
||||
* Does this Item match the given Ingredient.
|
||||
* A RecipeItem matches an Ingredient if all required info of the RecipeItem are fulfilled on the Ingredient
|
||||
* This does not imply that the same holds the other way round, as the ingredient item might have more info than needed
|
||||
*
|
||||
*
|
||||
* @param ingredient The ingredient that needs to fulfill the requirements
|
||||
* @return True if the ingredient matches the required info of this
|
||||
*/
|
||||
public abstract boolean matches(Ingredient ingredient);
|
||||
|
||||
/**
|
||||
* Get the Corresponding Ingredient Item. For Items implementing Ingredient, just getMutableCopy()
|
||||
* This is called when this recipe item is added to a BIngredients
|
||||
*
|
||||
* @param forItem The ItemStack that has previously matched this RecipeItem. Used if the resulting Ingredient needs more info from the ItemStack
|
||||
* @return The IngredientItem corresponding to this RecipeItem
|
||||
*/
|
||||
@NotNull
|
||||
public abstract Ingredient toIngredient(ItemStack forItem);
|
||||
|
||||
/**
|
||||
* Gets a Generic Ingredient for this recipe item
|
||||
*/
|
||||
@NotNull
|
||||
public abstract Ingredient toIngredientGeneric();
|
||||
|
||||
/**
|
||||
* @return True if this recipeItem has one or more materials that could classify an item. if true, getMaterials() is NotNull
|
||||
*/
|
||||
public abstract boolean hasMaterials();
|
||||
|
||||
/**
|
||||
* @return List of one or more Materials this recipeItem uses.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract List<Material> getMaterials();
|
||||
|
||||
/**
|
||||
* @return The Id this Item uses in the config in the custom-items section
|
||||
*/
|
||||
@Nullable
|
||||
public String getConfigId() {
|
||||
return cfgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Amount of this Item in a Recipe
|
||||
*/
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Amount of this Item in a Recipe
|
||||
* The amount can not be set on an existing item in a recipe or existing custom item.
|
||||
* To change amount you need to use getMutableCopy() and change the amount on the copy
|
||||
*
|
||||
* @param amount The new amount
|
||||
*/
|
||||
public void setAmount(int amount) {
|
||||
if (immutable) throw new IllegalStateException("Setting amount only possible on mutable copy");
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes this Item immutable, for example when loaded from config. Used so if this is added to BIngredients,
|
||||
* it needs to be cloned before changing anything like amount
|
||||
*/
|
||||
public void makeImmutable() {
|
||||
immutable = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a shallow clone of this RecipeItem whose fields like amount can be changed.
|
||||
*
|
||||
* @return A mutable copy of this
|
||||
*/
|
||||
public RecipeItem getMutableCopy() {
|
||||
try {
|
||||
RecipeItem i = (RecipeItem) super.clone();
|
||||
i.immutable = false;
|
||||
return i;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find a matching RecipeItem for this item. It checks custom items and if it has found a unique custom item
|
||||
* it will return that. If there are multiple matching custom items, a new CustomItem with all item info is returned
|
||||
* If there is no matching CustomItem, it will return a SimpleItem with the items type
|
||||
*
|
||||
* @param item The Item for which to find a matching RecipeItem
|
||||
* @param acceptAll If true it will accept any item and return a SimpleItem even if not on the accepted list
|
||||
* If false it will return null if the item is not acceptable by the Cauldron
|
||||
* @return The Matched CustomItem, new CustomItem with all item info or SimpleItem
|
||||
*/
|
||||
@Nullable
|
||||
@Contract("_, true -> !null")
|
||||
public static RecipeItem getMatchingRecipeItem(ItemStack item, boolean acceptAll) {
|
||||
RecipeItem rItem = null;
|
||||
boolean multiMatch = false;
|
||||
for (RecipeItem ri : BCauldronRecipe.acceptedCustom) {
|
||||
// If we already have a multi match, only check if there is a PluginItem that matches more strictly
|
||||
if (!multiMatch || (ri instanceof PluginItem)) {
|
||||
if (ri.matches(item)) {
|
||||
// If we match a plugin item, thats a very strict match, so immediately return it
|
||||
if (ri instanceof PluginItem) {
|
||||
return ri;
|
||||
}
|
||||
if (rItem == null) {
|
||||
rItem = ri;
|
||||
} else {
|
||||
multiMatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (multiMatch) {
|
||||
// We have multiple Custom Items matching, so just store all item info
|
||||
return new CustomItem(item);
|
||||
}
|
||||
if (rItem == null && (acceptAll || BCauldronRecipe.acceptedSimple.contains(item.getType()))) {
|
||||
// No Custom item found
|
||||
if (P.use1_13) {
|
||||
return new SimpleItem(item.getType());
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
return new SimpleItem(item.getType(), item.getDurability());
|
||||
}
|
||||
}
|
||||
return rItem;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static RecipeItem fromConfigCustom(ConfigurationSection cfg, String id) {
|
||||
RecipeItem rItem;
|
||||
if (cfg.getBoolean(id + ".matchAny", false)) {
|
||||
rItem = new CustomMatchAnyItem();
|
||||
} else {
|
||||
rItem = new CustomItem();
|
||||
}
|
||||
|
||||
rItem.cfgId = id;
|
||||
rItem.immutable = true;
|
||||
|
||||
List<Material> materials;
|
||||
List<String> names;
|
||||
List<String> lore;
|
||||
|
||||
List<String> load = null;
|
||||
String path = id + ".material";
|
||||
if (cfg.isString(path)) {
|
||||
load = new ArrayList<>(1);
|
||||
load.add(cfg.getString(path));
|
||||
} else if (cfg.isList(path)) {
|
||||
load = cfg.getStringList(path);
|
||||
}
|
||||
if (load != null && !load.isEmpty()) {
|
||||
if ((materials = loadMaterials(load)) == null) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
materials = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
load = null;
|
||||
path = id + ".name";
|
||||
if (cfg.isString(path)) {
|
||||
load = new ArrayList<>(1);
|
||||
load.add(cfg.getString(path));
|
||||
} else if (cfg.isList(path)) {
|
||||
load = cfg.getStringList(path);
|
||||
}
|
||||
if (load != null && !load.isEmpty()) {
|
||||
names = load.stream().map(l -> P.p.color(l)).collect(Collectors.toList());
|
||||
if (P.use1_13) {
|
||||
// In 1.13 trailing Color white is removed from display names
|
||||
names = names.stream().map(l -> l.startsWith("§f") ? l.substring(2) : l).collect(Collectors.toList());
|
||||
}
|
||||
} else {
|
||||
names = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
load = null;
|
||||
path = id + ".lore";
|
||||
if (cfg.isString(path)) {
|
||||
load = new ArrayList<>(1);
|
||||
load.add(cfg.getString(path));
|
||||
} else if (cfg.isList(path)) {
|
||||
load = cfg.getStringList(path);
|
||||
}
|
||||
if (load != null && !load.isEmpty()) {
|
||||
lore = load.stream().map(l -> P.p.color(l)).collect(Collectors.toList());
|
||||
} else {
|
||||
lore = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
if (materials.isEmpty() && names.isEmpty() && lore.isEmpty()) {
|
||||
P.p.errorLog("No Config Entries found for Custom Item");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (rItem instanceof CustomItem) {
|
||||
CustomItem cItem = ((CustomItem) rItem);
|
||||
if (!materials.isEmpty()) {
|
||||
cItem.setMat(materials.get(0));
|
||||
}
|
||||
if (!names.isEmpty()) {
|
||||
cItem.setName(names.get(0));
|
||||
}
|
||||
cItem.setLore(lore);
|
||||
} else {
|
||||
CustomMatchAnyItem maItem = (CustomMatchAnyItem) rItem;
|
||||
maItem.setMaterials(materials);
|
||||
maItem.setNames(names);
|
||||
maItem.setLore(lore);
|
||||
}
|
||||
|
||||
return rItem;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static List<Material> loadMaterials(List<String> ingredientsList) {
|
||||
List<Material> materials = new ArrayList<>(ingredientsList.size());
|
||||
for (String item : ingredientsList) {
|
||||
String[] ingredParts = item.split("/");
|
||||
if (ingredParts.length == 2) {
|
||||
P.p.errorLog("Item Amount can not be specified for Custom Items: " + item);
|
||||
return null;
|
||||
}
|
||||
Material mat = Material.matchMaterial(ingredParts[0]);
|
||||
|
||||
if (mat == null && BConfig.hasVault) {
|
||||
try {
|
||||
net.milkbowl.vault.item.ItemInfo vaultItem = net.milkbowl.vault.item.Items.itemByString(ingredParts[0]);
|
||||
if (vaultItem != null) {
|
||||
mat = vaultItem.getType();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
P.p.errorLog("Could not check vault for Item Name");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (mat != null) {
|
||||
materials.add(mat);
|
||||
} else {
|
||||
P.p.errorLog("Unknown Material: " + ingredParts[0]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return materials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof RecipeItem)) return false;
|
||||
RecipeItem that = (RecipeItem) o;
|
||||
return amount == that.amount &&
|
||||
immutable == that.immutable &&
|
||||
Objects.equals(cfgId, that.cfgId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(cfgId, amount, immutable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecipeItem{(" + getClass().getSimpleName() + ") ID: " + getConfigId() + " Materials: " + (hasMaterials() ? getMaterials().size() : 0) + " Amount: " + getAmount();
|
||||
}
|
||||
}
|
151
src/com/dre/brewery/recipe/SimpleItem.java
Normal file
151
src/com/dre/brewery/recipe/SimpleItem.java
Normal file
@ -0,0 +1,151 @@
|
||||
package com.dre.brewery.recipe;
|
||||
|
||||
import com.dre.brewery.P;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Simple Minecraft Item with just Material
|
||||
*/
|
||||
public class SimpleItem extends RecipeItem implements Ingredient {
|
||||
|
||||
private Material mat;
|
||||
private short dur; // Old Mc
|
||||
|
||||
|
||||
public SimpleItem(Material mat) {
|
||||
this(mat, (short) 0);
|
||||
}
|
||||
|
||||
public SimpleItem(Material mat, short dur) {
|
||||
this.mat = mat;
|
||||
this.dur = dur;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMaterials() {
|
||||
return mat != null;
|
||||
}
|
||||
|
||||
public Material getMaterial() {
|
||||
return mat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Material> getMaterials() {
|
||||
List<Material> l = new ArrayList<>(1);
|
||||
l.add(mat);
|
||||
return l;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ingredient toIngredient(ItemStack forItem) {
|
||||
return ((SimpleItem) getMutableCopy());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Ingredient toIngredientGeneric() {
|
||||
return ((SimpleItem) getMutableCopy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
if (!mat.equals(item.getType())) {
|
||||
return false;
|
||||
}
|
||||
//noinspection deprecation
|
||||
return P.use1_13 || dur == item.getDurability();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Ingredient ingredient) {
|
||||
if (isSimilar(ingredient)) {
|
||||
return true;
|
||||
}
|
||||
if (ingredient instanceof RecipeItem) {
|
||||
if (!((RecipeItem) ingredient).hasMaterials()) {
|
||||
return false;
|
||||
}
|
||||
if (ingredient instanceof CustomItem) {
|
||||
// Only match if the Custom Item also only defines material
|
||||
// If the custom item has more info like name and lore, it is not supposed to match a simple item
|
||||
CustomItem ci = (CustomItem) ingredient;
|
||||
return !ci.hasLore() && !ci.hasName() && mat == ci.getMaterial();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSimilar(Ingredient item) {
|
||||
if (this == item) {
|
||||
return true;
|
||||
}
|
||||
if (item instanceof SimpleItem) {
|
||||
SimpleItem si = ((SimpleItem) item);
|
||||
return si.mat == mat && si.dur == dur;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
SimpleItem item = (SimpleItem) o;
|
||||
return dur == item.dur &&
|
||||
mat == item.mat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), mat, dur);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleItem{" +
|
||||
"mat=" + mat.name().toLowerCase() +
|
||||
" amount=" + getAmount() +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveTo(DataOutputStream out) throws IOException {
|
||||
out.writeUTF("SI");
|
||||
out.writeUTF(mat.name());
|
||||
out.writeShort(dur);
|
||||
}
|
||||
|
||||
public static SimpleItem loadFrom(ItemLoader loader) {
|
||||
try {
|
||||
DataInputStream in = loader.getInputStream();
|
||||
Material mat = Material.getMaterial(in.readUTF());
|
||||
if (mat != null) {
|
||||
SimpleItem item = new SimpleItem(mat, in.readShort());
|
||||
return item;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Needs to be called at Server start
|
||||
public static void registerItemLoader() {
|
||||
Ingredient.registerForItemLoader("SI", SimpleItem::loadFrom);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,329 +0,0 @@
|
||||
package com.dre.brewery.utility;
|
||||
|
||||
import com.dre.brewery.P;
|
||||
import com.dre.brewery.filedata.BConfig;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CustomItem {
|
||||
private String id;
|
||||
private boolean simple; // Simple Custom Item is just materials.get(0) and durability for old mc
|
||||
private boolean matchAny; // If only one of the values needs to match
|
||||
private short dur; // Old Mc
|
||||
private List<Material> materials;
|
||||
private List<String> names;
|
||||
private List<String> lore;
|
||||
|
||||
public static CustomItem asSimpleItem(Material mat) {
|
||||
return asSimpleItem(mat, (short) 0);
|
||||
}
|
||||
|
||||
public static CustomItem asSimpleItem(Material mat, short dur) {
|
||||
CustomItem it = new CustomItem();
|
||||
it.simple = true;
|
||||
it.dur = dur;
|
||||
it.materials = new ArrayList<>(1);
|
||||
it.materials.add(mat);
|
||||
return it;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CustomItem fromConfig(ConfigurationSection cfg, String id) {
|
||||
CustomItem custom = new CustomItem();
|
||||
|
||||
custom.id = id;
|
||||
custom.matchAny = cfg.getBoolean(id + ".matchAny", false);
|
||||
|
||||
List<String> load = null;
|
||||
String path = id + ".material";
|
||||
if (cfg.isString(path)) {
|
||||
load = new ArrayList<>(1);
|
||||
load.add(cfg.getString(path));
|
||||
} else if (cfg.isList(path)) {
|
||||
load = cfg.getStringList(path);
|
||||
}
|
||||
if (load != null && !load.isEmpty()) {
|
||||
custom.materials = new ArrayList<>(load.size());
|
||||
if (!custom.loadMaterials(load)) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
custom.materials = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
load = null;
|
||||
path = id + ".name";
|
||||
if (cfg.isString(path)) {
|
||||
load = new ArrayList<>(1);
|
||||
load.add(cfg.getString(path));
|
||||
} else if (cfg.isList(path)) {
|
||||
load = cfg.getStringList(path);
|
||||
}
|
||||
if (load != null && !load.isEmpty()) {
|
||||
custom.names = load.stream().map(l -> P.p.color(l)).collect(Collectors.toList());
|
||||
if (P.use1_13) {
|
||||
// In 1.13 trailing Color white is removed from display names
|
||||
custom.names = custom.names.stream().map(l -> l.startsWith("§f") ? l.substring(2) : l).collect(Collectors.toList());
|
||||
}
|
||||
} else {
|
||||
custom.names = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
load = null;
|
||||
path = id + ".lore";
|
||||
if (cfg.isString(path)) {
|
||||
load = new ArrayList<>(1);
|
||||
load.add(cfg.getString(path));
|
||||
} else if (cfg.isList(path)) {
|
||||
load = cfg.getStringList(path);
|
||||
}
|
||||
if (load != null && !load.isEmpty()) {
|
||||
custom.lore = load.stream().map(l -> P.p.color(l)).collect(Collectors.toList());
|
||||
} else {
|
||||
custom.lore = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
if (custom.materials.isEmpty() && custom.names.isEmpty() && custom.lore.isEmpty()) {
|
||||
P.p.errorLog("No Config Entries found for Custom Item");
|
||||
return null;
|
||||
}
|
||||
|
||||
return custom;
|
||||
}
|
||||
|
||||
private boolean loadMaterials(List<String> ingredientsList) {
|
||||
for (String item : ingredientsList) {
|
||||
String[] ingredParts = item.split("/");
|
||||
if (ingredParts.length == 2) {
|
||||
P.p.errorLog("Item Amount can not be specified for Custom Items: " + item);
|
||||
return false;
|
||||
}
|
||||
Material mat = Material.matchMaterial(ingredParts[0]);
|
||||
|
||||
if (mat == null && BConfig.hasVault) {
|
||||
try {
|
||||
net.milkbowl.vault.item.ItemInfo vaultItem = net.milkbowl.vault.item.Items.itemByString(ingredParts[0]);
|
||||
if (vaultItem != null) {
|
||||
mat = vaultItem.getType();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
P.p.errorLog("Could not check vault for Item Name");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (mat != null) {
|
||||
materials.add(mat);
|
||||
} else {
|
||||
P.p.errorLog("Unknown Material: " + ingredParts[0]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean isSimple() {
|
||||
return simple;
|
||||
}
|
||||
|
||||
public boolean isMatchAny() {
|
||||
return matchAny;
|
||||
}
|
||||
|
||||
public List<Material> getMaterials() {
|
||||
return materials;
|
||||
}
|
||||
|
||||
public Material getSimpleMaterial() {
|
||||
return materials.get(0);
|
||||
}
|
||||
|
||||
public List<String> getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
public List<String> getLore() {
|
||||
return lore;
|
||||
}
|
||||
|
||||
public boolean matches(ItemStack usedItem) {
|
||||
if (simple) {
|
||||
return matchSimple(usedItem);
|
||||
} else if (matchAny){
|
||||
return matchAny(usedItem);
|
||||
} else {
|
||||
return matchOne(usedItem);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchSimple(ItemStack usedItem) {
|
||||
if (!materials.get(0).equals(usedItem.getType())) {
|
||||
return false;
|
||||
}
|
||||
//noinspection deprecation
|
||||
return P.use1_13 || dur == usedItem.getDurability();
|
||||
}
|
||||
|
||||
private boolean matchAny(ItemStack usedItem) {
|
||||
Material usedMat = usedItem.getType();
|
||||
for (Material mat : materials) {
|
||||
if (usedMat == mat) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!usedItem.hasItemMeta()) {
|
||||
return false;
|
||||
}
|
||||
ItemMeta meta = usedItem.getItemMeta();
|
||||
assert meta != null;
|
||||
if (meta.hasDisplayName()) {
|
||||
String usedName = meta.getDisplayName();
|
||||
for (String name : names) {
|
||||
if (name.equalsIgnoreCase(usedName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (meta.hasLore()) {
|
||||
List<String> usedLore = meta.getLore();
|
||||
assert usedLore != null;
|
||||
for (String line : this.lore) {
|
||||
for (String usedLine : usedLore) {
|
||||
if (line.equalsIgnoreCase(usedLine) || line.equalsIgnoreCase(ChatColor.stripColor(usedLine))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchOne(ItemStack item) {
|
||||
if (!materials.isEmpty()) {
|
||||
if (item.getType() != materials.get(0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (names.isEmpty() && lore.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
if (!item.hasItemMeta()) {
|
||||
return false;
|
||||
}
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
assert meta != null;
|
||||
if (!names.isEmpty()) {
|
||||
if (!meta.hasDisplayName() || !names.get(0).equalsIgnoreCase(meta.getDisplayName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!lore.isEmpty()) {
|
||||
if (!meta.hasLore()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int lastIndex = 0;
|
||||
List<String> usedLore = meta.getLore();
|
||||
assert usedLore != null;
|
||||
boolean foundFirst = false;
|
||||
for (String line : lore) {
|
||||
do {
|
||||
if (lastIndex == usedLore.size()) {
|
||||
// There is more in lore than in usedLore, bad
|
||||
return false;
|
||||
}
|
||||
String usedLine = usedLore.get(lastIndex);
|
||||
if (line.equalsIgnoreCase(usedLine) || line.equalsIgnoreCase(ChatColor.stripColor(usedLine))) {
|
||||
// If the line is correct, we have found our first and we want all consecutive lines to also equal
|
||||
foundFirst = true;
|
||||
} else if (foundFirst) {
|
||||
// If a consecutive line is not equal, thats bad
|
||||
return false;
|
||||
}
|
||||
lastIndex++;
|
||||
// If we once found one correct line, iterate over 'lore' consecutively
|
||||
} while (!foundFirst);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ItemStack createDummy(int amount) {
|
||||
if (simple) {
|
||||
if (P.use1_13) {
|
||||
return new ItemStack(getSimpleMaterial(), amount);
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
return new ItemStack(getSimpleMaterial(), amount, dur);
|
||||
}
|
||||
} else if (matchAny) {
|
||||
if (!materials.isEmpty()) {
|
||||
return new ItemStack(materials.get(0), amount);
|
||||
} else if (!names.isEmpty()) {
|
||||
ItemStack item = new ItemStack(Material.DIAMOND_HOE, amount);
|
||||
ItemMeta meta = item.hasItemMeta() ? item.getItemMeta() : P.p.getServer().getItemFactory().getItemMeta(Material.DIAMOND_HOE);
|
||||
assert meta != null;
|
||||
meta.setDisplayName(names.get(0));
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
} else if (!lore.isEmpty()) {
|
||||
ItemStack item = new ItemStack(Material.DIAMOND_HOE, amount);
|
||||
ItemMeta meta = item.hasItemMeta() ? item.getItemMeta() : P.p.getServer().getItemFactory().getItemMeta(Material.DIAMOND_HOE);
|
||||
assert meta != null;
|
||||
List<String> l = new ArrayList<>();
|
||||
l.add(lore.get(0));
|
||||
meta.setLore(l);
|
||||
item.setItemMeta(meta);
|
||||
return item;
|
||||
}
|
||||
return new ItemStack(Material.DIAMOND_HOE, amount);
|
||||
} else {
|
||||
ItemStack item;
|
||||
ItemMeta meta;
|
||||
if (!materials.isEmpty()) {
|
||||
item = new ItemStack(materials.get(0), amount);
|
||||
meta = item.hasItemMeta() ? item.getItemMeta() : P.p.getServer().getItemFactory().getItemMeta(materials.get(0));
|
||||
} else {
|
||||
item = new ItemStack(Material.DIAMOND_HOE, amount);
|
||||
meta = item.hasItemMeta() ? item.getItemMeta() : P.p.getServer().getItemFactory().getItemMeta(Material.DIAMOND_HOE);
|
||||
}
|
||||
assert meta != null;
|
||||
if (!names.isEmpty()) {
|
||||
meta.setDisplayName(names.get(0));
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
if (!lore.isEmpty()) {
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (simple) {
|
||||
return "CustomItem{Simple: " + getSimpleMaterial().name().toLowerCase() + "}";
|
||||
}
|
||||
if (materials == null || names == null || lore == null) {
|
||||
return "CustomItem{" + id + "}";
|
||||
}
|
||||
return "CustomItem{" + id + ": " + (matchAny ? "MatchAny, " : "MatchOne, ") + materials.size() + " Materials, " + names.size() + " Names, " + lore.size() + " Lore}";
|
||||
}
|
||||
}
|
@ -1,5 +1,10 @@
|
||||
package com.dre.brewery;
|
||||
|
||||
import com.dre.brewery.recipe.BCauldronRecipe;
|
||||
import com.dre.brewery.recipe.BRecipe;
|
||||
import com.dre.brewery.recipe.Ingredient;
|
||||
import com.dre.brewery.recipe.RecipeItem;
|
||||
import com.dre.brewery.recipe.SimpleItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
@ -24,9 +29,12 @@ public class RecipeTests {
|
||||
int y = recipe.amountOf(new ItemStack(Material.NETHER_BRICK));
|
||||
|
||||
|
||||
List<ItemStack> list = new ArrayList<>();
|
||||
list.add(new ItemStack(Material.DIAMOND_HOE, 3));
|
||||
list.add(new ItemStack(Material.RED_MUSHROOM, 1));
|
||||
List<Ingredient> list = new ArrayList<>();
|
||||
Ingredient ing = new SimpleItem(Material.DIAMOND_HOE);
|
||||
ing.setAmount(3);
|
||||
list.add(ing);
|
||||
ing = new SimpleItem(Material.RED_MUSHROOM);
|
||||
list.add(ing);
|
||||
for (int i = 1; i < 20; i++) {
|
||||
list.get(0).setAmount(i + 3);
|
||||
list.get(1).setAmount(i);
|
||||
@ -46,5 +54,16 @@ public class RecipeTests {
|
||||
}
|
||||
P.p.debugLog("Found best for i:" + i + " " + best);
|
||||
}
|
||||
|
||||
item = new ItemStack(Material.BARRIER);
|
||||
itemMeta = item.getItemMeta();
|
||||
l = new ArrayList<>();
|
||||
l.add("Eine Tür");
|
||||
l.add("§6Besonders gut geschützt");
|
||||
itemMeta.setLore(l);
|
||||
itemMeta.setDisplayName("Mauer");
|
||||
item.setItemMeta(itemMeta);
|
||||
|
||||
RecipeItem.getMatchingRecipeItem(item, false);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user