Recipes can now have amounts

You can also specify the amount of the crafted output using a new item
stat
This commit is contained in:
ASangarin 2020-07-10 22:59:39 +02:00
parent 9a40e86b14
commit b9bb29b559
21 changed files with 776 additions and 528 deletions

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>net.Indyuce</groupId>
<artifactId>MMOItems</artifactId>
<version>5.5.1</version>
<version>5.5.2</version>
<name>MMOItems</name>
<description>A great item solution for your RPG server.</description>

View File

@ -10,10 +10,12 @@ import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import net.Indyuce.mmoitems.api.ConfigFile;
import net.Indyuce.mmoitems.api.SoulboundInfo;
import net.Indyuce.mmoitems.api.item.MMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.command.MMOItemsCommand;
import net.Indyuce.mmoitems.command.UpdateItemCommand;
@ -45,6 +47,7 @@ import net.Indyuce.mmoitems.comp.rpg.DefaultHook;
import net.Indyuce.mmoitems.comp.rpg.RPGHandler;
import net.Indyuce.mmoitems.gui.PluginInventory;
import net.Indyuce.mmoitems.gui.listener.GuiListener;
import net.Indyuce.mmoitems.listener.CraftingListener;
import net.Indyuce.mmoitems.listener.CustomBlockListener;
import net.Indyuce.mmoitems.listener.CustomSoundListener;
import net.Indyuce.mmoitems.listener.DisableInteractions;
@ -155,6 +158,7 @@ public class MMOItems extends JavaPlugin {
Bukkit.getPluginManager().registerEvents(new DisableInteractions(), this);
Bukkit.getPluginManager().registerEvents(new GuiListener(), this);
Bukkit.getPluginManager().registerEvents(new ElementListener(), this);
Bukkit.getPluginManager().registerEvents(new CraftingListener(), this);
if (MMOLib.plugin.getVersion().isStrictlyHigher(1, 12)) {
Bukkit.getPluginManager().registerEvents(new CustomBlockListener(), this);
Bukkit.getPluginManager().registerEvents(new Listener_v1_13(), this);
@ -401,6 +405,45 @@ public class MMOItems extends JavaPlugin {
return getConfig().getStringList("block-blacklist").contains(material.name());
}
/***
* Parses an ItemStack from a string.
* Can be used to both get a vanilla material or
* an MMOItem. Used by the recipe manager.
*/
public ItemStack parseStack(String parse) {
ItemStack stack = null;
String[] split = parse.split("\\:");
String input = split[0];
if (input.contains(".")) {
String[] typeId = input.split("\\.");
String typeFormat = typeId[0].toUpperCase().replace("-", "_").replace(" ", "_");
Validate.isTrue(getTypes().has(typeFormat), "Could not find type " + typeFormat);
MMOItem mmo = getItems().getMMOItem(MMOItems.plugin.getTypes().get(typeFormat), typeId[1]);
if(mmo != null) stack = mmo.newBuilder().build();
}
else {
Material mat = Material.AIR;
try {
mat = Material.valueOf(input.toUpperCase().replace("-", "_").replace(" ", "_"));
} catch (IllegalArgumentException e) {
getLogger().warning("Couldn't parse material from '" + parse + "'!");
}
if(mat != Material.AIR) stack = new ItemStack(mat);
}
try {
if(stack != null && split.length > 1)
stack.setAmount(Integer.parseInt(split[1]));
} catch (NumberFormatException e) {
getLogger().warning("Couldn't parse amount from '" + parse + "'!");
}
return stack;
}
public void debug(Object... message) {
if (!getConfig().getBoolean("debug"))
return;

View File

@ -1,93 +1,41 @@
package net.Indyuce.mmoitems.api.recipe;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.mmogroup.mmolib.api.item.NBTItem;
public class MMORecipeChoice {
private final Material material;
private final int data;
private final Type type;
private final String id;
public MMORecipeChoice(Material material, int data) {
this(material, data, null, null);
}
public MMORecipeChoice(Type type, String id) {
this(null, 0, type, id);
}
private final ItemStack item;
private final int amount;
private final boolean isVanilla;
public MMORecipeChoice(String input) {
if (input.contains(".")) {
String[] typeId = input.split("\\.");
String typeFormat = typeId[0].toUpperCase().replace("-", "_").replace(" ", "_");
Validate.isTrue(MMOItems.plugin.getTypes().has(typeFormat), "Could not find type " + typeFormat);
type = MMOItems.plugin.getTypes().get(typeFormat);
id = typeId[1];
data = 0;
material = null;
item = MMOItems.plugin.parseStack(input);
if(item != null) {
isVanilla = !NBTItem.get(item).hasType();
amount = item.getAmount();
}
else {
String[] split = input.split("\\:");
material = Material.valueOf(split[0].toUpperCase().replace("-", "_").replace(" ", "_"));
data = split.length > 1 ? Integer.parseInt(split[1]) : 0;
type = null;
id = null;
amount = 1;
isVanilla = true;
}
}
private MMORecipeChoice(Material material, int data, Type type, String id) {
this.type = type;
this.id = id;
this.material = material;
this.data = data;
public boolean isValid() {
return item != null;
}
public boolean isVanilla() {
return isVanilla;
}
@SuppressWarnings("deprecation")
public ItemStack generateStack() {
return material != null ? (data > 0 ? new ItemStack(material, 1, (short) data) : new ItemStack(material)) : MMOItems.plugin.getItems().getItem(type, id);
public int getAmount() {
return amount;
}
public boolean isAir() {
return material == Material.AIR;
}
public Material getMaterial() {
return material;
}
public Type getType() {
return type;
}
public String getId() {
return id;
}
public int getMeta() {
return data;
}
public static List<MMORecipeChoice> getFromShapedConfig(List<String> list) {
List<MMORecipeChoice> choices = new ArrayList<>();
for (String key : list)
for (String subkey : key.split("\\ "))
choices.add(new MMORecipeChoice(subkey));
return choices;
public ItemStack getItem() {
return item;
}
}

View File

@ -0,0 +1,56 @@
package net.Indyuce.mmoitems.api.recipe.workbench;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.inventory.ItemStack;
public class CachedRecipe {
private Map<Integer, Integer> amounts = new HashMap<>();
private ItemStack stack;
public boolean isValid(ItemStack[] matrix) {
boolean check = true;
for (int i = 0; i < matrix.length; i++) {
if (matrix[i] == null)
continue;
if (matrix[i].getAmount() < amounts.get(i))
check = false;
if (!check)
break;
}
return check;
}
public ItemStack[] generateMatrix(ItemStack[] matrix) {
ItemStack[] newMatrix = new ItemStack[9];
for (int i = 0; i < matrix.length; i++) {
ItemStack stack = matrix[i];
if (stack == null) {
newMatrix[i] = null;
continue;
}
int amountLeft = stack.getAmount() - amounts.get(i);
if (amountLeft < 1) {
newMatrix[i] = null;
continue;
}
stack.setAmount(amountLeft);
newMatrix[i] = stack;
}
return newMatrix;
}
public void add(int slot, int amount) {
amounts.put(slot, amount);
}
public void setResult(ItemStack result) {
stack = result;
}
public ItemStack getResult() {
return stack;
}
}

View File

@ -0,0 +1,81 @@
package net.Indyuce.mmoitems.api.recipe.workbench;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.recipe.workbench.ingredients.AirIngredient;
import net.Indyuce.mmoitems.api.recipe.workbench.ingredients.WorkbenchIngredient;
import net.mmogroup.mmolib.api.item.NBTItem;
public class CustomRecipe implements Comparable<CustomRecipe> {
private final boolean shapeless;
private final ItemStack output;
private final Map<Integer, WorkbenchIngredient> ingredients = new HashMap<>(9);
public CustomRecipe(NBTItem output, List<String> recipe, boolean isShapeless) {
this.shapeless = isShapeless;
this.output = output.toItem();
if (output.hasTag("MMOITEMS_CRAFTED_AMOUNT"))
this.output.setAmount(output.getInteger("MMOITEMS_CRAFTED_AMOUNT"));
if (shapeless) {
for (int i = 0; i < 9; i++) {
ItemStack stack = MMOItems.plugin.parseStack(recipe.get(i));
if (stack == null || stack.getType() == Material.AIR)
continue;
ingredients.put(i, WorkbenchIngredient.getAutomatically(stack));
}
}
else {
for (int i = 0; i < 9; i++) {
List<String> line = Arrays.asList(recipe.get(i / 3).split("\\ "));
while (line.size() < 3)
line.add("AIR");
ItemStack stack = MMOItems.plugin.parseStack(line.get(i % 3));
if (stack == null || stack.getType() == Material.AIR)
ingredients.put(i, new AirIngredient());
else ingredients.put(i, WorkbenchIngredient.getAutomatically(stack));
}
}
}
public Set<Entry<Integer, WorkbenchIngredient>> getIngredients() {
return ingredients.entrySet();
}
public boolean fitsPlayerCrafting() {
boolean check = true;
for (int value : ingredients.keySet())
if (value > 3) {
check = false;
break;
}
return check;
}
public boolean isEmpty() {
return ingredients.isEmpty();
}
public boolean isShapeless() {
return shapeless;
}
public ItemStack getResult() {
return output;
}
@Override
public int compareTo(CustomRecipe o) {
return Boolean.compare(shapeless, o.shapeless);
}
}

View File

@ -0,0 +1,16 @@
package net.Indyuce.mmoitems.api.recipe.workbench.ingredients;
import org.bukkit.inventory.ItemStack;
public class AirIngredient extends WorkbenchIngredient {
@Override
public boolean matches(ItemStack stack) {
if(stack == null) return true;
else return false;
}
@Override
public boolean matchStack(ItemStack stack) {
return true;
}
}

View File

@ -0,0 +1,26 @@
package net.Indyuce.mmoitems.api.recipe.workbench.ingredients;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.api.Type;
import net.mmogroup.mmolib.api.item.NBTItem;
public class MMOIngredient extends WorkbenchIngredient {
private final Type type;
private final String id;
public MMOIngredient(Type type, String id) {
this.type = type;
this.id = id;
}
@Override
public boolean matchStack(ItemStack stack) {
NBTItem nbt = NBTItem.get(stack);
if (!nbt.hasType())
return false;
return nbt.getType().equals(type) &&
nbt.getString("MMOITEMS_ITEM_ID").equalsIgnoreCase(id);
}
}

View File

@ -0,0 +1,20 @@
package net.Indyuce.mmoitems.api.recipe.workbench.ingredients;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import net.mmogroup.mmolib.api.item.NBTItem;
public class VanillaIngredient extends WorkbenchIngredient {
private final Material mat;
public VanillaIngredient(Material mat) {
this.mat = mat;
}
@Override
public boolean matchStack(ItemStack stack) {
if(NBTItem.get(stack).hasType()) return false;
return stack.getType() == mat;
}
}

View File

@ -0,0 +1,34 @@
package net.Indyuce.mmoitems.api.recipe.workbench.ingredients;
import org.bukkit.inventory.ItemStack;
import net.mmogroup.mmolib.api.item.NBTItem;
public abstract class WorkbenchIngredient {
private int amount;
public void setAmount(int value) {
amount = value;
}
public int getAmount() {
return amount;
}
public static WorkbenchIngredient getAutomatically(ItemStack stack) {
WorkbenchIngredient ingredient;
NBTItem nbt = NBTItem.get(stack);
if(nbt.hasType()) ingredient = new MMOIngredient(nbt.getType(), nbt.getString("MMOITEMS_ITEM_ID"));
else ingredient = new VanillaIngredient(stack.getType());
ingredient.setAmount(stack.getAmount());
return ingredient;
}
public boolean matches(ItemStack stack) {
if(stack == null) return false;
if(stack.getAmount() < amount) return false;
else return matchStack(stack);
}
public abstract boolean matchStack(ItemStack stack);
}

View File

@ -522,12 +522,10 @@ public class MMOItemsCommand implements CommandExecutor {
* discoverRecipes must be called on the main thread.
*/
Bukkit.getScheduler().runTask(MMOItems.plugin, () -> {
if (MMOLib.plugin.getVersion().isStrictlyHigher(1, 12) && MMOItems.plugin.getConfig().getBoolean("auto-recipe-book"))
Bukkit.getOnlinePlayers().forEach(online -> online.discoverRecipes(MMOItems.plugin.getRecipes().getNamespacedKeys()));
sender.sendMessage(MMOItems.plugin.getPrefix() + "Successfully reloaded recipes.");
sender.sendMessage(MMOItems.plugin.getPrefix() + "- " + ChatColor.RED
+ MMOItems.plugin.getRecipes().getLoadedRecipes().size() + ChatColor.GRAY + " Recipes");
+ (MMOItems.plugin.getRecipes().getLoadedRecipes().size()
+ MMOItems.plugin.getRecipes().getCustomRecipes().size()) + ChatColor.GRAY + " Recipes");
});
});
}

View File

@ -6,6 +6,7 @@ import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
@ -13,10 +14,10 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.ConfigFile;
import net.Indyuce.mmoitems.api.edition.StatEdition;
import net.Indyuce.mmoitems.api.item.MMOItem;
import net.Indyuce.mmoitems.api.recipe.MMORecipeChoice;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.mmogroup.mmolib.api.util.AltChar;
@ -56,8 +57,11 @@ public class RecipeEdition extends EditionInventory {
while (line.size() < 3)
line.add("AIR");
ItemStack element = new MMORecipeChoice(fixAir(line.get(j % 3))).generateStack();
ItemStack element = MMOItems.plugin.parseStack(line.get(j % 3));
if(element == null) element = new ItemStack(Material.BARRIER);
if(element.getType() == Material.AIR) element.setType(Material.BARRIER);
ItemMeta elementMeta = element.getItemMeta();
if(element.getType() == Material.BARRIER) elementMeta.setDisplayName(ChatColor.RED + "Empty");
List<String> elementLore = new ArrayList<>();
elementLore.add("");
elementLore.add(ChatColor.YELLOW + AltChar.listDash + " Click to change this ingredient.");
@ -76,34 +80,35 @@ public class RecipeEdition extends EditionInventory {
Inventory inv = Bukkit.createInventory(this, 54, ChatColor.UNDERLINE + "Recipe Editor: " + mmoitem.getId());
ConfigFile config = mmoitem.getType().getConfigFile();
if (!config.getConfig().contains(mmoitem.getId() + ".crafting.shapeless.1")) {
for (int i = 1; i < 10; i++)
config.getConfig().set(mmoitem.getId() + ".crafting.shapeless.1.item" + i, "AIR");
config.getConfig().set(mmoitem.getId() + ".crafting.shapeless.1",
Arrays.asList("AIR", "AIR", "AIR", "AIR", "AIR", "AIR", "AIR", "AIR", "AIR"));
registerItemEdition(config);
}
for (int j = 0; j < 9; j++) {
int slot = intToSlot(j);
List<String> ingredients = config.getConfig().getStringList(mmoitem.getId() + ".crafting.shapeless.1");
if(ingredients.size() == 9)
for (int j = 0; j < 9; j++) {
int slot = intToSlot(j);
ItemStack element = new MMORecipeChoice(fixAir(config.getConfig().getString(mmoitem.getId() + ".crafting.shapeless.1.item" + (j + 1))))
.generateStack();
ItemMeta elementMeta = element.getItemMeta();
List<String> elementLore = new ArrayList<>();
elementLore.add("");
elementLore.add(ChatColor.YELLOW + AltChar.listDash + " Click to change this ingredient.");
elementLore.add(ChatColor.YELLOW + AltChar.listDash + " Right click to remove this ingredient.");
elementMeta.setLore(elementLore);
element.setItemMeta(elementMeta);
ItemStack element = MMOItems.plugin.parseStack(ingredients.get(j));
if(element == null) element = new ItemStack(Material.BARRIER);
if(element.getType() == Material.AIR) element.setType(Material.BARRIER);
ItemMeta elementMeta = element.getItemMeta();
if(element.getType() == Material.BARRIER) elementMeta.setDisplayName(ChatColor.RED + "Empty");
List<String> elementLore = new ArrayList<>();
elementLore.add("");
elementLore.add(ChatColor.YELLOW + AltChar.listDash + " Click to change this ingredient.");
elementLore.add(ChatColor.YELLOW + AltChar.listDash + " Right click to remove this ingredient.");
elementMeta.setLore(elementLore);
element.setItemMeta(elementMeta);
inv.setItem(slot, element);
}
inv.setItem(slot, element);
}
else MMOItems.plugin.getLogger().warning("Couldn't load shapeless recipe for '" + mmoitem.getId() + "'!");
addEditionInventoryItems(inv, true);
return inv;
}
private String fixAir(String string) {
return string.equals("AIR") ? "BARRIER" : string;
}
private int intToSlot(int i) {
return i >= 0 && i <= 2 ? 21 + i : (i >= 3 && i <= 5 ? 27 + i : (i >= 6 && i <= 8 ? 33 + i : 0));
}
@ -122,7 +127,7 @@ public class RecipeEdition extends EditionInventory {
if (event.getAction() == InventoryAction.PICKUP_ALL) {
if (slotToInt(event.getRawSlot()) >= 0)
new StatEdition(this, ItemStat.CRAFTING, "recipe", (shapeless ? "shapeless" : "shaped"), slotToInt(event.getRawSlot()))
.enable("Write in the chat the item you want.", "Format: '[MATERIAL]' or '[MATERIAL]:[DURABILITY]' or '[TYPE].[ID]'");
.enable("Write in the chat the item you want.", "Format: '[MATERIAL]' or '[TYPE].[ID]'");
} else if (event.getAction() == InventoryAction.PICKUP_HALF) {
if (shapeless)
@ -146,8 +151,12 @@ public class RecipeEdition extends EditionInventory {
private void deleteShapeless(int slot) {
ConfigFile config = mmoitem.getType().getConfigFile();
config.getConfig().set(mmoitem.getId() + ".crafting.shapeless.1.item" + (slot + 1), "AIR");
registerItemEdition(config);
open();
if(config.getConfig().contains(mmoitem.getId() + ".crafting.shapeless.1")) {
List<String> newList = config.getConfig().getStringList(mmoitem.getId() + ".crafting.shapeless.1");
newList.set(slot, "AIR");
config.getConfig().set(mmoitem.getId() + ".crafting.shapeless.1", newList);
registerItemEdition(config);
open();
}
}
}

View File

@ -0,0 +1,140 @@
package net.Indyuce.mmoitems.listener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.event.inventory.PrepareItemCraftEvent;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.recipe.workbench.CachedRecipe;
import net.Indyuce.mmoitems.api.recipe.workbench.CustomRecipe;
import net.Indyuce.mmoitems.api.recipe.workbench.ingredients.WorkbenchIngredient;
public class CraftingListener implements Listener {
Map<UUID, CachedRecipe> cachedRecipe = new HashMap<>();
@EventHandler
public void calculateCrafting(PrepareItemCraftEvent e) {
if (!(e.getView().getPlayer() instanceof Player))
return;
handleCustomCrafting(e.getInventory(), (Player) e.getView().getPlayer());
}
@EventHandler
public void getResult(InventoryClickEvent e) {
if (!(e.getView().getPlayer() instanceof Player)) return;
if (!(e.getInventory() instanceof CraftingInventory)) return;
if (e.getSlotType() == SlotType.CRAFTING && e.getAction() == InventoryAction.PLACE_ONE)
Bukkit.getScheduler().runTaskLater(MMOItems.plugin, new Runnable() {
@Override
public void run() {
handleCustomCrafting((CraftingInventory) e.getInventory(), (Player) e.getView().getPlayer());
}
}, 1);
else if (e.getSlotType() == SlotType.RESULT) {
CraftingInventory inv = (CraftingInventory) e.getInventory();
if (e.getCurrentItem() == null || !cachedRecipe.containsKey(e.getWhoClicked().getUniqueId()))
return;
if (e.getClick() != ClickType.LEFT) {
e.setCancelled(true);
return;
}
CachedRecipe cached = cachedRecipe.get(e.getWhoClicked().getUniqueId());
cachedRecipe.remove(e.getWhoClicked().getUniqueId());
if (!cached.isValid(inv.getMatrix())) {
e.setCancelled(true);
return;
}
ItemStack[] newMatrix = cached.generateMatrix(inv.getMatrix());
inv.setMatrix(new ItemStack[] { null, null, null, null, null, null, null, null, null });
Bukkit.getScheduler().runTaskLater(MMOItems.plugin, new Runnable() {
@Override
public void run() {
boolean check = true;
for (ItemStack stack : newMatrix)
if (stack != null)
check = false;
if (check) {
inv.setMatrix(new ItemStack[] { null, null, null, null, null, null, null, null, null });
((Player) e.getView().getPlayer()).updateInventory();
} else
inv.setMatrix(newMatrix);
}
}, 1);
e.setCurrentItem(cached.getResult());
}
}
public void handleCustomCrafting(CraftingInventory inv, Player player) {
player.updateInventory();
cachedRecipe.remove(player.getUniqueId());
for (CustomRecipe recipe : MMOItems.plugin.getRecipes().getCustomRecipes()) {
if (!recipe.fitsPlayerCrafting() && inv.getMatrix().length == 4)
continue;
CachedRecipe cached = new CachedRecipe();
boolean matches = true;
List<Integer> slotsChecked = new ArrayList<>();
for (Entry<Integer, WorkbenchIngredient> ingredients : recipe.getIngredients()) {
if (recipe.isShapeless()) {
boolean check = false;
int nonnullcount = 0;
for (int i = 0; i < inv.getMatrix().length; i++) {
if (slotsChecked.contains(i))
continue;
ItemStack item = inv.getMatrix()[i];
if (item == null) {
slotsChecked.add(i);
continue;
}
nonnullcount += 1;
if (ingredients.getValue().matches(item)) {
cached.add(i, ingredients.getValue().getAmount());
slotsChecked.add(i);
check = true;
}
if (nonnullcount > recipe.getIngredients().size()) {
check = false;
break;
}
}
if (!check)
matches = false;
} else {
if (!ingredients.getValue().matches(inv.getMatrix()[ingredients.getKey()]))
matches = false;
else cached.add(ingredients.getKey(), ingredients.getValue().getAmount());
}
if (!matches) break;
}
if (matches) {
cached.setResult(recipe.getResult());
cachedRecipe.put(player.getUniqueId(), cached);
inv.setResult(recipe.getResult());
Bukkit.getScheduler().runTaskLater(MMOItems.plugin, new Runnable() {
@Override
public void run() {
inv.setItem(0, recipe.getResult());
}
}, 1);
break;
}
}
}
}

View File

@ -4,10 +4,8 @@ import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.entity.Trident;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
@ -18,8 +16,6 @@ import net.mmogroup.mmolib.MMOLib;
import net.mmogroup.mmolib.api.item.NBTItem;
public class Listener_v1_13 implements Listener {
private final boolean autoRecipeBook = MMOItems.plugin.getConfig().getBoolean("auto-recipe-book");
@EventHandler
public void a(ProjectileLaunchEvent event) {
if (!(event.getEntity() instanceof Trident) || !(event.getEntity().getShooter() instanceof Player))
@ -41,10 +37,4 @@ public class Listener_v1_13 implements Listener {
MMOItems.plugin.getEntities().registerCustomProjectile(nbtItem, playerData.getStats().newTemporary(), (Trident) event.getEntity(), type != null);
}
@EventHandler(priority = EventPriority.LOW)
public void b(PlayerJoinEvent event) {
if (autoRecipeBook)
event.getPlayer().discoverRecipes(MMOItems.plugin.getRecipes().getNamespacedKeys());
}
}

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmoitems.manager.recipe;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@ -10,58 +11,55 @@ import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.recipe.MMORecipeChoice;
import net.Indyuce.mmoitems.api.recipe.workbench.CustomRecipe;
public abstract class RecipeManager {
/**
* TODO When Bukkit changes their 'RecipeChoice.ExactChoice' API we can
* remove the suppressed warnings, but right now it works despite being
* marked as deprecated. It is just a
*/
private final Set<CustomRecipe> craftingRecipes = new HashSet<>();
private final Set<LoadedRecipe> loadedRecipes = new HashSet<>();
public abstract void reload();
public abstract void registerFurnaceRecipe(Type type, String id, BurningRecipeInformation info, String number);
public abstract void registerShapelessRecipe(Type type, String id, ConfigurationSection config, String number);
public abstract void shapedIngredient(ShapedRecipe recipe, char slot, MMORecipeChoice choice);
public abstract void registerShapedRecipe(Type type, String id, List<String> list, String number);
public abstract void shapelessIngredient(ShapelessRecipe recipe, MMORecipeChoice choice);
/**
* This method is purely for easily converting the AWB recipes.
*
* @deprecated Some day I want to get proper rid of the AWB but right now we
* don't want to force players to update their recipes right off
* the bat.
*/
@Deprecated
public abstract void setIngredientOrAir(ShapedRecipe recipe, char character, ConfigurationSection c);
public abstract void registerShapedRecipe(Type type, String id, List<String> list);
public abstract void registerShapelessRecipe(Type type, String id, List<String> ingredients);
public void registerRecipe(NamespacedKey key, Recipe recipe) {
loadedRecipes.add(new LoadedRecipe(key, recipe));
}
public void registerRecipe(CustomRecipe recipe) {
if(!recipe.isEmpty())
craftingRecipes.add(recipe);
}
public Set<LoadedRecipe> getLoadedRecipes() {
return loadedRecipes;
}
public Set<CustomRecipe> getCustomRecipes() {
return craftingRecipes;
}
public Set<NamespacedKey> getNamespacedKeys() {
return loadedRecipes.stream().map(recipe -> recipe.getKey()).collect(Collectors.toSet());
}
public void sortRecipes() {
List<CustomRecipe> temporary = new ArrayList<>();
temporary.addAll(craftingRecipes);
craftingRecipes.clear();
craftingRecipes.addAll(temporary.stream().sorted().collect(Collectors.toList()));
}
public void clearCustomRecipes() {
craftingRecipes.clear();
}
public NamespacedKey getRecipeKey(Type type, String id, String recipeType, String number) {
return new NamespacedKey(MMOItems.plugin, recipeType + "_" + type.getId() + "_" + id + "_" + number);
}
@ -81,28 +79,6 @@ public abstract class RecipeManager {
});
}
/**
* @deprecated Some day I want to get proper rid of the AWB but right now we
* don't want to force players to update their recipes right off
* the bat.
*/
public void registerAdvancedWorkbenchRecipe(Type type, String id, FileConfiguration config) {
MMOItems.plugin.getLogger().warning("Found deprecated adv. recipe for " + id + ". Converting it to the new system...");
MMOItems.plugin.getLogger().warning("It is recommended to update your recipes!");
NamespacedKey key = getRecipeKey(type, id, "advanced", "deprecated");
ShapedRecipe recipe = new ShapedRecipe(key, MMOItems.plugin.getItems().getItem(type, id));
recipe.shape("012", "345", "678");
for (int j = 0; j < 9; j++) {
ConfigurationSection section = config.getConfigurationSection(id + ".advanced-craft." + j);
if (section != null)
setIngredientOrAir(recipe, ("" + j).charAt(0), section);
}
registerRecipe(key, recipe);
}
/*
* used because spigot API does not let us access namespaced key of a Recipe
* instance.
@ -120,7 +96,7 @@ public abstract class RecipeManager {
return key;
}
public Recipe toBukkit() {
public Recipe getRecipe() {
return recipe;
}
}

View File

@ -3,53 +3,44 @@ package net.Indyuce.mmoitems.manager.recipe;
import java.util.List;
import java.util.logging.Level;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.BlastingRecipe;
import org.bukkit.inventory.CampfireRecipe;
import org.bukkit.inventory.FurnaceRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.RecipeChoice;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.inventory.SmokingRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.recipe.MMORecipeChoice;
import net.asangarin.hexcolors.ColorParse;
import net.Indyuce.mmoitems.api.recipe.workbench.CustomRecipe;
public class RecipeManagerDefault extends RecipeManager {
public RecipeManagerDefault() {
reload();
}
@Override
@SuppressWarnings("deprecation")
public void reload() {
clearCustomRecipes();
for (Type type : MMOItems.plugin.getTypes().getAll()) {
FileConfiguration config = type.getConfigFile().getConfig();
for (String id : config.getKeys(false))
try {
if (config.getConfigurationSection(id).contains("advanced-craft"))
registerAdvancedWorkbenchRecipe(type, id, config);
if (config.getConfigurationSection(id).contains("crafting")) {
ConfigurationSection section = config.getConfigurationSection(id + ".crafting");
if (section.contains("shaped"))
section.getConfigurationSection("shaped").getKeys(false)
.forEach(recipe -> registerShapedRecipe(type, id, section.getStringList("shaped." + recipe), recipe));
.forEach(recipe -> registerShapedRecipe(type, id, section.getStringList("shaped." + recipe)));
if (section.contains("shapeless"))
section.getConfigurationSection("shapeless").getKeys(false).forEach(
recipe -> registerShapelessRecipe(type, id, section.getConfigurationSection("shapeless." + recipe), recipe));
recipe -> registerShapelessRecipe(type, id, section.getStringList("shapeless." + recipe)));
if (section.contains("furnace"))
section.getConfigurationSection("furnace").getKeys(false).forEach(recipe -> registerFurnaceRecipe(type, id,
new BurningRecipeInformation(section.getConfigurationSection("furnace." + recipe)), recipe));
@ -68,16 +59,17 @@ public class RecipeManagerDefault extends RecipeManager {
}
}
// registerCampfireRecipe(MMOItems.plugin.getItems().getItem(Type.SWORD,
// "SILVER_SWORD"), new
// RecipeChoice.ExactChoice(MMOItems.plugin.getItems().getItem(Type.get("MATERIAL"),
// "SILVER_INGOT")));
Bukkit.getScheduler().runTask(MMOItems.plugin, () -> getLoadedRecipes().forEach(recipe -> Bukkit.addRecipe(recipe.toBukkit())));
sortRecipes();
Bukkit.getScheduler().runTask(MMOItems.plugin,
() -> getLoadedRecipes().forEach(recipe -> Bukkit.addRecipe(recipe.getRecipe())));
}
@Override
public void registerFurnaceRecipe(Type type, String id, BurningRecipeInformation info, String number) {
if(!info.getChoice().isValid()) {
MMOItems.plugin.getLogger().warning("Couldn't load furnace recipe for '" + type.getId() + "." + id + "'");
return;
}
NamespacedKey key = getRecipeKey(type, id, "furnace", number);
FurnaceRecipe recipe = new FurnaceRecipe(key, MMOItems.plugin.getItems().getItem(type, id), toBukkit(info.getChoice()), info.getExp(),
info.getBurnTime());
@ -85,6 +77,10 @@ public class RecipeManagerDefault extends RecipeManager {
}
public void registerBlastRecipe(Type type, String id, BurningRecipeInformation info, String number) {
if(!info.getChoice().isValid()) {
MMOItems.plugin.getLogger().warning("Couldn't load blast furnace recipe for '" + type.getId() + "." + id + "'");
return;
}
NamespacedKey key = getRecipeKey(type, id, "blast", number);
BlastingRecipe recipe = new BlastingRecipe(key, MMOItems.plugin.getItems().getItem(type, id), toBukkit(info.getChoice()), info.getExp(),
info.getBurnTime());
@ -92,6 +88,10 @@ public class RecipeManagerDefault extends RecipeManager {
}
public void registerSmokerRecipe(Type type, String id, BurningRecipeInformation info, String number) {
if(!info.getChoice().isValid()) {
MMOItems.plugin.getLogger().warning("Couldn't load smoker recipe for '" + type.getId() + "." + id + "'");
return;
}
NamespacedKey key = getRecipeKey(type, id, "smoker", number);
SmokingRecipe recipe = new SmokingRecipe(key, MMOItems.plugin.getItems().getItem(type, id), toBukkit(info.getChoice()), info.getExp(),
info.getBurnTime());
@ -99,6 +99,10 @@ public class RecipeManagerDefault extends RecipeManager {
}
public void registerCampfireRecipe(Type type, String id, BurningRecipeInformation info, String number) {
if(!info.getChoice().isValid()) {
MMOItems.plugin.getLogger().warning("Couldn't load campfire recipe for '" + type.getId() + "." + id + "'");
return;
}
NamespacedKey key = getRecipeKey(type, id, "campfire", number);
CampfireRecipe recipe = new CampfireRecipe(key, MMOItems.plugin.getItems().getItem(type, id), toBukkit(info.getChoice()), info.getExp(),
info.getBurnTime());
@ -106,94 +110,23 @@ public class RecipeManagerDefault extends RecipeManager {
}
@Override
public void registerShapedRecipe(Type type, String id, List<String> list, String number) {
NamespacedKey key = getRecipeKey(type, id, "shaped", number);
ShapedRecipe recipe = new ShapedRecipe(key, MMOItems.plugin.getItems().getItem(type, id));
List<MMORecipeChoice> choices = MMORecipeChoice.getFromShapedConfig(list);
if (choices.isEmpty())
return;
recipe.shape("ABC", "DEF", "GHI");
shapedIngredient(recipe, 'A', choices.get(0));
shapedIngredient(recipe, 'B', choices.get(1));
shapedIngredient(recipe, 'C', choices.get(2));
shapedIngredient(recipe, 'D', choices.get(3));
shapedIngredient(recipe, 'E', choices.get(4));
shapedIngredient(recipe, 'F', choices.get(5));
shapedIngredient(recipe, 'G', choices.get(6));
shapedIngredient(recipe, 'H', choices.get(7));
shapedIngredient(recipe, 'I', choices.get(8));
registerRecipe(key, recipe);
public void registerShapedRecipe(Type type, String id, List<String> list) {
registerRecipe(new CustomRecipe(MMOItems.plugin.getItems().getMMOItem(type, id).newBuilder().buildNBT(), list, false));
}
@Override
public void shapedIngredient(ShapedRecipe recipe, char slot, MMORecipeChoice choice) {
if (choice.isAir())
recipe.setIngredient(slot, Material.AIR);
else
recipe.setIngredient(slot, toBukkit(choice));
}
@Override
public void registerShapelessRecipe(Type type, String id, ConfigurationSection config, String number) {
NamespacedKey key = getRecipeKey(type, id, "shapeless", number);
ShapelessRecipe recipe = new ShapelessRecipe(key, MMOItems.plugin.getItems().getItem(type, id));
for (int i = 1; i < 10; i++)
if (config.contains("item" + i))
shapelessIngredient(recipe, new MMORecipeChoice(config.getString("item" + i)));
if (!recipe.getIngredientList().isEmpty())
registerRecipe(key, recipe);
}
@Override
public void shapelessIngredient(ShapelessRecipe recipe, MMORecipeChoice choice) {
if (!choice.isAir())
recipe.addIngredient(toBukkit(choice));
}
@Override
@SuppressWarnings("deprecation")
public void setIngredientOrAir(ShapedRecipe recipe, char character, ConfigurationSection config) {
if (config.contains("type")) {
String typeFormat = config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_");
Validate.notNull(MMOItems.plugin.getTypes().has(typeFormat), "Could not find item type");
String id = config.getString("id");
Validate.notNull(id, "Could not find item ID");
ItemStack item = MMOItems.plugin.getItems().getItem(MMOItems.plugin.getTypes().get(typeFormat), id);
Validate.isTrue(item != null, "Could not load item with ID: " + id);
item.setAmount(config.getInt("amount", 1));
recipe.setIngredient(character, item.getType());
} else if (config.contains("material")) {
Material material = Material.valueOf(config.getString("material").toUpperCase().replace("-", "_").replace(" ", "_"));
int amount = config.getInt("amount", 1);
String name = config.getString("name", "");
if (amount == 1)
recipe.setIngredient(character, material);
else {
ItemStack item = new ItemStack(material);
item.setAmount(amount);
if (!name.isEmpty()) {
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(new ColorParse('&', name).toChatColor());
item.setItemMeta(meta);
}
recipe.setIngredient(character, new RecipeChoice.ExactChoice(item));
}
}
public void registerShapelessRecipe(Type type, String id, List<String> list) {
registerRecipe(new CustomRecipe(MMOItems.plugin.getItems().getMMOItem(type, id).newBuilder().buildNBT(), list, true));
}
/*
* TODO When Bukkit changes their 'RecipeChoice.ExactChoice' API we can
* remove the suppressed warnings, but right now it works despite being
* marked as deprecated. It is just draft API and probably subject to change.
*/
@SuppressWarnings("deprecation")
public RecipeChoice toBukkit(MMORecipeChoice choice) {
return choice.getMaterial() != null ? new RecipeChoice.MaterialChoice(choice.getMaterial())
: new RecipeChoice.ExactChoice(MMOItems.plugin.getItems().getItem(choice.getType(), choice.getId()));
return choice.isVanilla() ? new RecipeChoice.MaterialChoice(choice.getItem().getType())
: new RecipeChoice.ExactChoice(choice.getItem());
}
}

View File

@ -3,144 +3,75 @@ package net.Indyuce.mmoitems.manager.recipe;
import java.util.List;
import java.util.logging.Level;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.FurnaceRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.recipe.MMORecipeChoice;
import net.Indyuce.mmoitems.api.recipe.workbench.CustomRecipe;
/** One day I'll get rid of 1.12 for real >:) */
/** One day we'll get rid of 1.12 for real >:) */
public class RecipeManagerLegacy extends RecipeManager {
public RecipeManagerLegacy() {
reload();
}
@Override
@SuppressWarnings("deprecation")
public void reload() {
clearCustomRecipes();
for (Type type : MMOItems.plugin.getTypes().getAll()) {
FileConfiguration config = type.getConfigFile().getConfig();
for (String id : config.getKeys(false))
try {
if (config.getConfigurationSection(id).contains("advanced-craft"))
registerAdvancedWorkbenchRecipe(type, id, config);
if (config.getConfigurationSection(id).contains("crafting")) {
ConfigurationSection section = config.getConfigurationSection(id + ".crafting");
if (section.contains("shaped"))
section.getConfigurationSection("shaped").getKeys(false)
.forEach(recipe -> registerShapedRecipe(type, id, section.getStringList("shaped." + recipe), recipe));
.forEach(recipe -> registerShapedRecipe(type, id, section.getStringList("shaped." + recipe)));
if (section.contains("shapeless"))
section.getConfigurationSection("shapeless").getKeys(false).forEach(
recipe -> registerShapelessRecipe(type, id, section.getConfigurationSection("shapeless." + recipe), recipe));
section.getConfigurationSection("shapeless").getKeys(false)
.forEach(recipe -> registerShapelessRecipe(type, id, section.getStringList("shapeless." + recipe)));
if (section.contains("furnace"))
section.getConfigurationSection("furnace").getKeys(false).forEach(recipe -> registerFurnaceRecipe(type, id,
new BurningRecipeInformation(section.getConfigurationSection("furnace." + recipe)), recipe));
section.getConfigurationSection("furnace").getKeys(false)
.forEach(recipe -> registerFurnaceRecipe(type, id,
new BurningRecipeInformation(section.getConfigurationSection("furnace." + recipe)), recipe));
}
} catch (IllegalArgumentException exception) {
MMOItems.plugin.getLogger().log(Level.WARNING, "Could not load recipe of " + id + ": " + exception.getMessage());
MMOItems.plugin.getLogger().log(Level.WARNING,
"Could not load recipe of " + id + ": " + exception.getMessage());
}
}
// registerCampfireRecipe(MMOItems.plugin.getItems().getItem(Type.SWORD,
// "SILVER_SWORD"), new
// RecipeChoice.ExactChoice(MMOItems.plugin.getItems().getItem(Type.get("MATERIAL"),
// "SILVER_INGOT")));
Bukkit.getScheduler().runTask(MMOItems.plugin, () ->
getLoadedRecipes().forEach(recipe -> Bukkit.addRecipe(recipe.toBukkit())));
sortRecipes();
Bukkit.getScheduler().runTask(MMOItems.plugin,
() -> getLoadedRecipes().forEach(recipe -> Bukkit.addRecipe(recipe.getRecipe())));
}
@Override
public void registerFurnaceRecipe(Type type, String id, BurningRecipeInformation info, String number) {
NamespacedKey key = getRecipeKey(type, id, "furnace", number);
FurnaceRecipe recipe = new FurnaceRecipe(key, MMOItems.plugin.getItems().getItem(type, id), info.getChoice().getMaterial(), info.getExp(),
info.getBurnTime());
registerRecipe(key, recipe);
}
@Override
public void registerShapedRecipe(Type type, String id, List<String> list, String number) {
NamespacedKey key = getRecipeKey(type, id, "shaped", number);
ShapedRecipe recipe = new ShapedRecipe(key, MMOItems.plugin.getItems().getItem(type, id));
List<MMORecipeChoice> rcList = MMORecipeChoice.getFromShapedConfig(list);
if (rcList == null)
if (!info.getChoice().isValid()) {
MMOItems.plugin.getLogger().warning("Couldn't load furnace recipe for '" + type.getId() + "." + id + "'");
return;
recipe.shape("ABC", "DEF", "GHI");
shapedIngredient(recipe, 'A', rcList.get(0));
shapedIngredient(recipe, 'B', rcList.get(1));
shapedIngredient(recipe, 'C', rcList.get(2));
shapedIngredient(recipe, 'D', rcList.get(3));
shapedIngredient(recipe, 'E', rcList.get(4));
shapedIngredient(recipe, 'F', rcList.get(5));
shapedIngredient(recipe, 'G', rcList.get(6));
shapedIngredient(recipe, 'H', rcList.get(7));
shapedIngredient(recipe, 'I', rcList.get(8));
}
NamespacedKey key = getRecipeKey(type, id, "furnace", number);
FurnaceRecipe recipe = new FurnaceRecipe(key, MMOItems.plugin.getItems().getItem(type, id),
info.getChoice().getItem().getType(), info.getExp(), info.getBurnTime());
registerRecipe(key, recipe);
}
@Override
public void shapedIngredient(ShapedRecipe recipe, char c, MMORecipeChoice rc) {
if (rc.isAir())
recipe.setIngredient(c, Material.AIR);
else
recipe.setIngredient(c, rc.generateStack().getType());
public void registerShapedRecipe(Type type, String id, List<String> list) {
registerRecipe(new CustomRecipe(MMOItems.plugin.getItems().getMMOItem(type, id).newBuilder().buildNBT(), list, false));
}
@Override
public void registerShapelessRecipe(Type type, String id, ConfigurationSection config, String number) {
NamespacedKey key = getRecipeKey(type, id, "shapeless", number);
ShapelessRecipe recipe = new ShapelessRecipe(key, MMOItems.plugin.getItems().getItem(type, id));
for (int i = 1; i < 10; i++)
if (config.contains("item" + i))
shapelessIngredient(recipe, new MMORecipeChoice(config.getString("item" + i)));
if (!recipe.getIngredientList().isEmpty())
registerRecipe(key, recipe);
}
@Override
public void shapelessIngredient(ShapelessRecipe recipe, MMORecipeChoice rc) {
if (!rc.isAir())
recipe.addIngredient(rc.getMaterial());
}
@Override
public void setIngredientOrAir(ShapedRecipe recipe, char character, ConfigurationSection config) {
if (config.contains("type")) {
String typeFormat = config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_");
Validate.notNull(MMOItems.plugin.getTypes().has(typeFormat), "Could not find item type");
String id = config.getString("id");
Validate.notNull(id, "Could not find item ID");
ItemStack item = MMOItems.plugin.getItems().getItem(MMOItems.plugin.getTypes().get(typeFormat), id);
Validate.isTrue(item != null, "Could not load item with ID: " + id);
item.setAmount(config.getInt("amount", 1));
recipe.setIngredient(character, item.getType());
} else if (config.contains("material")) {
Material material = Material.valueOf(config.getString("material").toUpperCase().replace("-", "_").replace(" ", "_"));
recipe.setIngredient(character, material);
}
public void registerShapelessRecipe(Type type, String id, List<String> list) {
registerRecipe(new CustomRecipe(MMOItems.plugin.getItems().getMMOItem(type, id).newBuilder().buildNBT(), list, true));
}
}

View File

@ -71,7 +71,9 @@ public class Crafting extends ItemStat {
config.getConfig().set(inv.getEdited().getId() + ".crafting.shaped.1", newList);
inv.registerItemEdition(config);
} else {
config.getConfig().set(inv.getEdited().getId() + ".crafting.shapeless.1.item" + (slot + 1), message);
List<String> newList = config.getConfig().getStringList(inv.getEdited().getId() + ".crafting.shapeless.1");
newList.set(slot, message);
config.getConfig().set(inv.getEdited().getId() + ".crafting.shapeless.1", newList);
inv.registerItemEdition(config);
}
}
@ -128,6 +130,23 @@ public class Crafting extends ItemStat {
}
private boolean validate(Player player, String input) {
if (input.contains(":")) {
String[] count = input.split("\\:");
if (count.length != 2) {
player.sendMessage(MMOItems.plugin.getPrefix() + "Invalid format.");
return false;
}
try {
Integer.parseInt(count[1]);
} catch (NumberFormatException exception) {
player.sendMessage(MMOItems.plugin.getPrefix() + "'" + count[1] + "' isn't a valid number.");
return false;
}
input = count[0];
}
if (input.contains(".")) {
String[] typeid = input.split("\\.");
if (typeid.length != 2) {
@ -149,27 +168,6 @@ public class Crafting extends ItemStat {
return true;
}
if (input.contains(":")) {
String[] matmeta = input.split("\\:");
if (matmeta.length != 2) {
player.sendMessage(MMOItems.plugin.getPrefix() + "Invalid format.");
return false;
}
try {
Material.valueOf(matmeta[0].toUpperCase().replace("-", "_"));
} catch (IllegalArgumentException exception) {
player.sendMessage(MMOItems.plugin.getPrefix() + "'" + matmeta[0].toUpperCase().replace("-", "_") + "' isn't a valid material.");
return false;
}
try {
Integer.parseInt(matmeta[1]);
} catch (NumberFormatException exception) {
player.sendMessage(MMOItems.plugin.getPrefix() + "'" + matmeta[1] + "' isn't a valid number.");
return false;
}
return true;
}
try {
Material.valueOf(input.toUpperCase().replace("-", "_"));
} catch (Exception e) {

View File

@ -77,177 +77,227 @@ import net.mmogroup.mmolib.version.VersionMaterial;
public abstract class ItemStat {
public static final ItemStat MATERIAL = new MaterialStat(),
DURABILITY = MMOLib.plugin.getVersion().isBelowOrEqual(1, 12) ? new LegacyDurability() : new DefaultDurability(),
CUSTOM_MODEL_DATA = new CustomModelData(), MAX_DURABILITY = new MaximumDurability(), WILL_BREAK = new LostWhenBroken();
DURABILITY = MMOLib.plugin.getVersion().isBelowOrEqual(1, 12) ? new LegacyDurability()
: new DefaultDurability(),
CUSTOM_MODEL_DATA = new CustomModelData(), MAX_DURABILITY = new MaximumDurability(),
WILL_BREAK = new LostWhenBroken();
public static final ItemStat NAME = new DisplayName(), LORE = new Lore(), NBT_TAGS = new NBTTags();
public static final ItemStat DISPLAYED_TYPE = new StringStat("DISPLAYED_TYPE", VersionMaterial.OAK_SIGN.toItem(), "Displayed Type",
new String[] { "This option will only affect the", "type displayed on the item lore." }, new String[] { "all" });
public static final ItemStat ENCHANTS = new Enchants(), HIDE_ENCHANTS = new HideEnchants(), PERMISSION = new Permission(),
ITEM_PARTICLES = new ItemParticles(), ARROW_PARTICLES = new ArrowParticles();
public static final ItemStat DISABLE_INTERACTION = new DisableStat("INTERACTION", VersionMaterial.GRASS_BLOCK.toMaterial(), "Disable Interaction",
"Disable any unwanted interaction:", "block placement, item use...");
public static final ItemStat DISABLE_CRAFTING = new DisableStat("CRAFTING", VersionMaterial.CRAFTING_TABLE.toMaterial(), "Disable Crafting",
public static final ItemStat DISPLAYED_TYPE = new StringStat("DISPLAYED_TYPE", VersionMaterial.OAK_SIGN.toItem(),
"Displayed Type", new String[] { "This option will only affect the", "type displayed on the item lore." },
new String[] { "all" });
public static final ItemStat ENCHANTS = new Enchants(), HIDE_ENCHANTS = new HideEnchants(),
PERMISSION = new Permission(), ITEM_PARTICLES = new ItemParticles(), ARROW_PARTICLES = new ArrowParticles();
public static final ItemStat DISABLE_INTERACTION = new DisableStat("INTERACTION",
VersionMaterial.GRASS_BLOCK.toMaterial(), "Disable Interaction", "Disable any unwanted interaction:",
"block placement, item use...");
public static final ItemStat DISABLE_CRAFTING = new DisableStat("CRAFTING",
VersionMaterial.CRAFTING_TABLE.toMaterial(), "Disable Crafting",
"Players can't use this item while crafting.");
public static final ItemStat DISABLE_SMELTING = new DisableStat("SMELTING", Material.FURNACE, "Disable Smelting",
"Players can't use this item in furnaces.");
public static final ItemStat DISABLE_SMITHING = new DisableStat("SMITHING", Material.DAMAGED_ANVIL, "Disable Smithing",
"Players can't smith this item in smithing tables.");
public static final ItemStat DISABLE_ENCHANTING = new DisableStat("ENCHANTING", VersionMaterial.ENCHANTING_TABLE.toMaterial(),
"Disable Enchanting", "Players can't enchant this item."), DISABLE_ADVANCED_ENCHANTS = new DisableAdvancedEnchantments();
public static final ItemStat DISABLE_SMELTING = new DisableStat("SMELTING", Material.FURNACE, "Disable Smelting",
"Players can't use this item in furnaces.");
public static final ItemStat DISABLE_SMITHING = new DisableStat("SMITHING", Material.DAMAGED_ANVIL,
"Disable Smithing", "Players can't smith this item in smithing tables.");
public static final ItemStat DISABLE_ENCHANTING = new DisableStat("ENCHANTING",
VersionMaterial.ENCHANTING_TABLE.toMaterial(), "Disable Enchanting", "Players can't enchant this item."),
DISABLE_ADVANCED_ENCHANTS = new DisableAdvancedEnchantments();
public static final ItemStat DISABLE_REPAIRING = new DisableStat("REPAIRING", Material.ANVIL, "Disable Repairing",
"Players can't use this item in anvils.");
public static final ItemStat DISABLE_ARROW_SHOOTING = new DisableStat("ARROW_SHOOTING", Material.ARROW, "Disable Arrow Shooting",
new Material[] { Material.ARROW }, "Players can't shoot this", "item using a bow.");
public static final ItemStat DISABLE_ATTACK_PASSIVE = new DisableStat("ATTACK_PASSIVE", Material.BARRIER, "Disable Attack Passive",
new String[] { "piercing", "slashing", "blunt" }, "Disables the blunt/slashing/piercing", "passive effects on attacks.");
public static final ItemStat DISABLE_RIGHT_CLICK_CONSUME = new DisableStat("RIGHT_CLICK_CONSUME", Material.BARRIER, "Disable Right Click Consume",
new String[] { "consumable" }, "This item will not be consumed", "when eaten by players.");
public static final ItemStat DISABLE_ARROW_SHOOTING = new DisableStat("ARROW_SHOOTING", Material.ARROW,
"Disable Arrow Shooting", new Material[] { Material.ARROW }, "Players can't shoot this",
"item using a bow.");
public static final ItemStat DISABLE_ATTACK_PASSIVE = new DisableStat("ATTACK_PASSIVE", Material.BARRIER,
"Disable Attack Passive", new String[] { "piercing", "slashing", "blunt" },
"Disables the blunt/slashing/piercing", "passive effects on attacks.");
public static final ItemStat DISABLE_RIGHT_CLICK_CONSUME = new DisableStat("RIGHT_CLICK_CONSUME", Material.BARRIER,
"Disable Right Click Consume", new String[] { "consumable" }, "This item will not be consumed",
"when eaten by players.");
public static final ItemStat REQUIRED_LEVEL = new RequiredLevel(), REQUIRED_CLASS = new RequiredClass(), ATTACK_DAMAGE = new AttackDamage(),
ATTACK_SPEED = new AttackSpeed();
public static final ItemStat CRITICAL_STRIKE_CHANCE = new DoubleStat("CRITICAL_STRIKE_CHANCE", new ItemStack(Material.NETHER_STAR),
"Critical Strike Chance", new String[] { "Critical Strikes deal more damage.", "In % chance." },
public static final ItemStat REQUIRED_LEVEL = new RequiredLevel(), REQUIRED_CLASS = new RequiredClass(),
ATTACK_DAMAGE = new AttackDamage(), ATTACK_SPEED = new AttackSpeed();
public static final ItemStat CRITICAL_STRIKE_CHANCE = new DoubleStat("CRITICAL_STRIKE_CHANCE",
new ItemStack(Material.NETHER_STAR), "Critical Strike Chance",
new String[] { "Critical Strikes deal more damage.", "In % chance." },
new String[] { "!miscellaneous", "all" });
public static final ItemStat CRITICAL_STRIKE_POWER = new DoubleStat("CRITICAL_STRIKE_POWER", new ItemStack(Material.NETHER_STAR),
"Critical Strike Power", new String[] { "The extra damage weapon crits deals.", "(Stacks with default value)", "In %." },
public static final ItemStat CRITICAL_STRIKE_POWER = new DoubleStat("CRITICAL_STRIKE_POWER",
new ItemStack(Material.NETHER_STAR), "Critical Strike Power",
new String[] { "The extra damage weapon crits deals.", "(Stacks with default value)", "In %." },
new String[] { "!miscellaneous", "all" });
public static final ItemStat BLOCK_POWER = new DoubleStat("BLOCK_POWER", new ItemStack(Material.IRON_HELMET), "Block Power",
new String[] { "The % of the damage your", "armor/shield can block.", "Default: 25%" }, new String[] { "!miscellaneous", "all" });
public static final ItemStat BLOCK_RATING = new DoubleStat("BLOCK_RATING", new ItemStack(Material.IRON_HELMET), "Block Rating",
new String[] { "The chance your piece of armor", "has to block any entity attack." }, new String[] { "!miscellaneous", "all" });
public static final ItemStat BLOCK_COOLDOWN_REDUCTION = new DoubleStat("BLOCK_COOLDOWN_REDUCTION", new ItemStack(Material.IRON_HELMET),
"Block Cooldown Reduction", new String[] { "Reduces the blocking cooldown (%)." }, new String[] { "!miscellaneous", "all" });
public static final ItemStat DODGE_RATING = new DoubleStat("DODGE_RATING", new ItemStack(Material.FEATHER), "Dodge Rating",
public static final ItemStat BLOCK_POWER = new DoubleStat("BLOCK_POWER", new ItemStack(Material.IRON_HELMET),
"Block Power", new String[] { "The % of the damage your", "armor/shield can block.", "Default: 25%" },
new String[] { "!miscellaneous", "all" });
public static final ItemStat BLOCK_RATING = new DoubleStat("BLOCK_RATING", new ItemStack(Material.IRON_HELMET),
"Block Rating", new String[] { "The chance your piece of armor", "has to block any entity attack." },
new String[] { "!miscellaneous", "all" });
public static final ItemStat BLOCK_COOLDOWN_REDUCTION = new DoubleStat("BLOCK_COOLDOWN_REDUCTION",
new ItemStack(Material.IRON_HELMET), "Block Cooldown Reduction",
new String[] { "Reduces the blocking cooldown (%)." }, new String[] { "!miscellaneous", "all" });
public static final ItemStat DODGE_RATING = new DoubleStat("DODGE_RATING", new ItemStack(Material.FEATHER),
"Dodge Rating",
new String[] { "The chance to dodge an attack.", "Dodging completely negates", "the attack damage." },
new String[] { "!miscellaneous", "all" });
public static final ItemStat DODGE_COOLDOWN_REDUCTION = new DoubleStat("DODGE_COOLDOWN_REDUCTION", new ItemStack(Material.FEATHER),
"Dodge Cooldown Reduction", new String[] { "Reduces the dodging cooldown (%)." }, new String[] { "!miscellaneous", "all" });
public static final ItemStat PARRY_RATING = new DoubleStat("PARRY_RATING", new ItemStack(Material.BUCKET), "Parry Rating",
new String[] { "The chance to parry an attack.", "Parrying negates the damage", "and knocks the attacker back." },
public static final ItemStat DODGE_COOLDOWN_REDUCTION = new DoubleStat("DODGE_COOLDOWN_REDUCTION",
new ItemStack(Material.FEATHER), "Dodge Cooldown Reduction",
new String[] { "Reduces the dodging cooldown (%)." }, new String[] { "!miscellaneous", "all" });
public static final ItemStat PARRY_RATING = new DoubleStat(
"PARRY_RATING", new ItemStack(Material.BUCKET), "Parry Rating", new String[] {
"The chance to parry an attack.", "Parrying negates the damage", "and knocks the attacker back." },
new String[] { "!miscellaneous", "all" });
public static final ItemStat PARRY_COOLDOWN_REDUCTION = new DoubleStat("PARRY_COOLDOWN_REDUCTION", new ItemStack(Material.BUCKET),
"Parry Cooldown Reduction", new String[] { "Reduces the parrying cooldown (%)." }, new String[] { "!miscellaneous", "all" });
public static final ItemStat COOLDOWN_REDUCTION = new DoubleStat("COOLDOWN_REDUCTION", new ItemStack(Material.BOOK), "Cooldown Reduction",
new String[] { "Reduces cooldowns of item skills (%)." });
public static final ItemStat PARRY_COOLDOWN_REDUCTION = new DoubleStat("PARRY_COOLDOWN_REDUCTION",
new ItemStack(Material.BUCKET), "Parry Cooldown Reduction",
new String[] { "Reduces the parrying cooldown (%)." }, new String[] { "!miscellaneous", "all" });
public static final ItemStat COOLDOWN_REDUCTION = new DoubleStat("COOLDOWN_REDUCTION", new ItemStack(Material.BOOK),
"Cooldown Reduction", new String[] { "Reduces cooldowns of item skills (%)." });
public static final ItemStat RANGE = new DoubleStat("RANGE", new ItemStack(Material.STICK), "Range",
new String[] { "The range of your item attacks." }, new String[] { "staff", "whip", "wand", "musket" });
public static final ItemStat MANA_COST = new DoubleStat("MANA_COST", VersionMaterial.LAPIS_LAZULI.toItem(), "Mana Cost",
new String[] { "Mana spent by your weapon to be used." }, new String[] { "piercing", "slashing", "blunt", "range" });
public static final ItemStat STAMINA_COST = new DoubleStat("STAMINA_COST", VersionMaterial.LIGHT_GRAY_DYE.toItem(), "Stamina Cost",
new String[] { "Stamina spent by your weapon to be used." }, new String[] { "piercing", "slashing", "blunt", "range" });
public static final ItemStat ARROW_VELOCITY = new DoubleStat("ARROW_VELOCITY", new ItemStack(Material.ARROW), "Arrow Velocity",
new String[] { "Determins how far your", "crossbow can shoot.", "Default: 1.0" }, new String[] { "bow", "crossbow" });
public static final ItemStat PVE_DAMAGE = new DoubleStat("PVE_DAMAGE", VersionMaterial.PORKCHOP.toItem(), "PvE Damage",
new String[] { "Additional damage against", "non human entities in %." },
new String[] { "piercing", "slashing", "blunt", "offhand", "range", "tool", "armor", "gem_stone", "accessory" });
public static final ItemStat PVP_DAMAGE = new DoubleStat("PVP_DAMAGE", VersionMaterial.SKELETON_SKULL.toItem(), "PvP Damage",
new String[] { "Additional damage", "against players in %." },
new String[] { "piercing", "slashing", "blunt", "offhand", "range", "tool", "armor", "gem_stone", "accessory" });
public static final ItemStat BLUNT_POWER = new DoubleStat("BLUNT_POWER", new ItemStack(Material.IRON_AXE), "Blunt Power",
new String[] { "The radius of the AoE attack.", "If set to 2.0, enemies within 2 blocks", "around your target will take damage." },
public static final ItemStat MANA_COST = new DoubleStat("MANA_COST", VersionMaterial.LAPIS_LAZULI.toItem(),
"Mana Cost", new String[] { "Mana spent by your weapon to be used." },
new String[] { "piercing", "slashing", "blunt", "range" });
public static final ItemStat STAMINA_COST = new DoubleStat("STAMINA_COST", VersionMaterial.LIGHT_GRAY_DYE.toItem(),
"Stamina Cost", new String[] { "Stamina spent by your weapon to be used." },
new String[] { "piercing", "slashing", "blunt", "range" });
public static final ItemStat ARROW_VELOCITY = new DoubleStat("ARROW_VELOCITY", new ItemStack(Material.ARROW),
"Arrow Velocity", new String[] { "Determins how far your", "crossbow can shoot.", "Default: 1.0" },
new String[] { "bow", "crossbow" });
public static final ItemStat PVE_DAMAGE = new DoubleStat("PVE_DAMAGE", VersionMaterial.PORKCHOP.toItem(),
"PvE Damage", new String[] { "Additional damage against", "non human entities in %." }, new String[] {
"piercing", "slashing", "blunt", "offhand", "range", "tool", "armor", "gem_stone", "accessory" });
public static final ItemStat PVP_DAMAGE = new DoubleStat("PVP_DAMAGE", VersionMaterial.SKELETON_SKULL.toItem(),
"PvP Damage", new String[] { "Additional damage", "against players in %." }, new String[] { "piercing",
"slashing", "blunt", "offhand", "range", "tool", "armor", "gem_stone", "accessory" });
public static final ItemStat BLUNT_POWER = new DoubleStat("BLUNT_POWER", new ItemStack(Material.IRON_AXE),
"Blunt Power", new String[] { "The radius of the AoE attack.", "If set to 2.0, enemies within 2 blocks",
"around your target will take damage." },
new String[] { "blunt", "gem_stone" });
public static final ItemStat BLUNT_RATING = new DoubleStat("BLUNT_RATING", new ItemStack(Material.BRICK), "Blunt Rating",
new String[] { "The force of the blunt attack.", "If set to 50%, enemies hit by the attack", "will take 50% of the initial damage." },
public static final ItemStat BLUNT_RATING = new DoubleStat("BLUNT_RATING", new ItemStack(Material.BRICK),
"Blunt Rating", new String[] { "The force of the blunt attack.", "If set to 50%, enemies hit by the attack",
"will take 50% of the initial damage." },
new String[] { "blunt", "gem_stone" });
public static final ItemStat WEAPON_DAMAGE = new DoubleStat("WEAPON_DAMAGE", new ItemStack(Material.IRON_SWORD), "Weapon Damage",
new String[] { "Additional on-hit weapon damage in %." });
public static final ItemStat SKILL_DAMAGE = new DoubleStat("SKILL_DAMAGE", new ItemStack(Material.BOOK), "Skill Damage",
new String[] { "Additional ability damage in %." });
public static final ItemStat PROJECTILE_DAMAGE = new DoubleStat("PROJECTILE_DAMAGE", new ItemStack(Material.ARROW), "Projectile Damage",
new String[] { "Additional skill/weapon projectile damage." });
public static final ItemStat MAGIC_DAMAGE = new DoubleStat("MAGIC_DAMAGE", new ItemStack(Material.MAGMA_CREAM), "Magic Damage",
new String[] { "Additional magic skill damage in %." });
public static final ItemStat PHYSICAL_DAMAGE = new DoubleStat("PHYSICAL_DAMAGE", new ItemStack(Material.IRON_AXE), "Physical Damage",
new String[] { "Additional skill/weapon physical damage." });
public static final ItemStat DAMAGE_REDUCTION = new DoubleStat("DAMAGE_REDUCTION", new ItemStack(Material.IRON_CHESTPLATE), "Damage Reduction",
public static final ItemStat WEAPON_DAMAGE = new DoubleStat("WEAPON_DAMAGE", new ItemStack(Material.IRON_SWORD),
"Weapon Damage", new String[] { "Additional on-hit weapon damage in %." });
public static final ItemStat SKILL_DAMAGE = new DoubleStat("SKILL_DAMAGE", new ItemStack(Material.BOOK),
"Skill Damage", new String[] { "Additional ability damage in %." });
public static final ItemStat PROJECTILE_DAMAGE = new DoubleStat("PROJECTILE_DAMAGE", new ItemStack(Material.ARROW),
"Projectile Damage", new String[] { "Additional skill/weapon projectile damage." });
public static final ItemStat MAGIC_DAMAGE = new DoubleStat("MAGIC_DAMAGE", new ItemStack(Material.MAGMA_CREAM),
"Magic Damage", new String[] { "Additional magic skill damage in %." });
public static final ItemStat PHYSICAL_DAMAGE = new DoubleStat("PHYSICAL_DAMAGE", new ItemStack(Material.IRON_AXE),
"Physical Damage", new String[] { "Additional skill/weapon physical damage." });
public static final ItemStat DAMAGE_REDUCTION = new DoubleStat("DAMAGE_REDUCTION",
new ItemStack(Material.IRON_CHESTPLATE), "Damage Reduction",
new String[] { "Reduces damage from any source.", "In %." });
public static final ItemStat FALL_DAMAGE_REDUCTION = new DoubleStat("FALL_DAMAGE_REDUCTION", new ItemStack(Material.FEATHER),
"Fall Damage Reduction", new String[] { "Reduces fall damage.", "In %." });
public static final ItemStat PROJECTILE_DAMAGE_REDUCTION = new DoubleStat("PROJECTILE_DAMAGE_REDUCTION", VersionMaterial.SNOWBALL.toItem(),
"Projectile Damage Reduction", new String[] { "Reduces projectile damage.", "In %." });
public static final ItemStat PHYSICAL_DAMAGE_REDUCTION = new DoubleStat("PHYSICAL_DAMAGE_REDUCTION", new ItemStack(Material.LEATHER_CHESTPLATE),
"Physical Damage Reduction", new String[] { "Reduces physical damage.", "In %." });
public static final ItemStat FIRE_DAMAGE_REDUCTION = new DoubleStat("FIRE_DAMAGE_REDUCTION", new ItemStack(Material.BLAZE_POWDER),
"Fire Damage Reduction", new String[] { "Reduces fire damage.", "In %." });
public static final ItemStat MAGIC_DAMAGE_REDUCTION = new DoubleStat("MAGIC_DAMAGE_REDUCTION", new ItemStack(Material.POTION),
"Magic Damage Reduction", new String[] { "Reduce magic damage dealt by potions.", "In %." });
public static final ItemStat PVE_DAMAGE_REDUCTION = new DoubleStat("PVE_DAMAGE_REDUCTION", VersionMaterial.PORKCHOP.toItem(),
"PvE Damage Reduction", new String[] { "Reduces damage dealt by mobs.", "In %." });
public static final ItemStat PVP_DAMAGE_REDUCTION = new DoubleStat("PVP_DAMAGE_REDUCTION", VersionMaterial.SKELETON_SKULL.toItem(),
"PvP Damage Reduction", new String[] { "Reduces damage dealt by players", "In %." });
public static final ItemStat UNDEAD_DAMAGE = new DoubleStat("UNDEAD_DAMAGE", VersionMaterial.SKELETON_SKULL.toItem(), "Undead Damage",
public static final ItemStat FALL_DAMAGE_REDUCTION = new DoubleStat("FALL_DAMAGE_REDUCTION",
new ItemStack(Material.FEATHER), "Fall Damage Reduction", new String[] { "Reduces fall damage.", "In %." });
public static final ItemStat PROJECTILE_DAMAGE_REDUCTION = new DoubleStat("PROJECTILE_DAMAGE_REDUCTION",
VersionMaterial.SNOWBALL.toItem(), "Projectile Damage Reduction",
new String[] { "Reduces projectile damage.", "In %." });
public static final ItemStat PHYSICAL_DAMAGE_REDUCTION = new DoubleStat("PHYSICAL_DAMAGE_REDUCTION",
new ItemStack(Material.LEATHER_CHESTPLATE), "Physical Damage Reduction",
new String[] { "Reduces physical damage.", "In %." });
public static final ItemStat FIRE_DAMAGE_REDUCTION = new DoubleStat("FIRE_DAMAGE_REDUCTION",
new ItemStack(Material.BLAZE_POWDER), "Fire Damage Reduction",
new String[] { "Reduces fire damage.", "In %." });
public static final ItemStat MAGIC_DAMAGE_REDUCTION = new DoubleStat("MAGIC_DAMAGE_REDUCTION",
new ItemStack(Material.POTION), "Magic Damage Reduction",
new String[] { "Reduce magic damage dealt by potions.", "In %." });
public static final ItemStat PVE_DAMAGE_REDUCTION = new DoubleStat("PVE_DAMAGE_REDUCTION",
VersionMaterial.PORKCHOP.toItem(), "PvE Damage Reduction",
new String[] { "Reduces damage dealt by mobs.", "In %." });
public static final ItemStat PVP_DAMAGE_REDUCTION = new DoubleStat("PVP_DAMAGE_REDUCTION",
VersionMaterial.SKELETON_SKULL.toItem(), "PvP Damage Reduction",
new String[] { "Reduces damage dealt by players", "In %." });
public static final ItemStat UNDEAD_DAMAGE = new DoubleStat("UNDEAD_DAMAGE",
VersionMaterial.SKELETON_SKULL.toItem(), "Undead Damage",
new String[] { "Deals additional damage to undead.", "In %." });
public static final ItemStat UNBREAKABLE = new Unbreakable(), TIER = new ItemTierStat(), SET = new ItemSetStat(), ARMOR = new Armor(),
ARMOR_TOUGHNESS = new ArmorToughness(), MAX_HEALTH = new MaxHealth();
public static final ItemStat MAX_MANA = new DoubleStat("MAX_MANA", VersionMaterial.LAPIS_LAZULI.toItem(), "Max Mana",
new String[] { "Adds mana to your max mana bar." });
public static final ItemStat UNBREAKABLE = new Unbreakable(), TIER = new ItemTierStat(), SET = new ItemSetStat(),
ARMOR = new Armor(), ARMOR_TOUGHNESS = new ArmorToughness(), MAX_HEALTH = new MaxHealth();
public static final ItemStat MAX_MANA = new DoubleStat("MAX_MANA", VersionMaterial.LAPIS_LAZULI.toItem(),
"Max Mana", new String[] { "Adds mana to your max mana bar." });
public static final ItemStat KNOCKBACK_RESISTANCE = new KnockbackResistance(), MOVEMENT_SPEED = new MovementSpeed();
public static final ItemStat TWO_HANDED = new BooleanStat("TWO_HANDED", new ItemStack(Material.IRON_INGOT), "Two Handed",
new String[] { "If set to true, a player will be", "significantly slower if holding two", "items, one being Two Handed." },
public static final ItemStat TWO_HANDED = new BooleanStat("TWO_HANDED", new ItemStack(Material.IRON_INGOT),
"Two Handed",
new String[] { "If set to true, a player will be", "significantly slower if holding two",
"items, one being Two Handed." },
new String[] { "piercing", "slashing", "blunt", "offhand", "range", "tool" });
public static final ItemStat RESTORE = new Restore();
public static final ItemStat RESTORE_MANA = new DoubleStat("RESTORE_MANA", VersionMaterial.LAPIS_LAZULI.toItem(), "Restore Mana",
new String[] { "The amount of mana", "your consumable restores." }, new String[] { "consumable" });
public static final ItemStat RESTORE_STAMINA = new DoubleStat("RESTORE_STAMINA", VersionMaterial.LIGHT_GRAY_DYE.toItem(), "Restore Stamina",
public static final ItemStat RESTORE_MANA = new DoubleStat("RESTORE_MANA", VersionMaterial.LAPIS_LAZULI.toItem(),
"Restore Mana", new String[] { "The amount of mana", "your consumable restores." },
new String[] { "consumable" });
public static final ItemStat RESTORE_STAMINA = new DoubleStat("RESTORE_STAMINA",
VersionMaterial.LIGHT_GRAY_DYE.toItem(), "Restore Stamina",
new String[] { "The amount of stamina/power", "your consumable restores." }, new String[] { "consumable" });
public static final ItemStat CAN_IDENTIFY = new BooleanStat("CAN_IDENTIFY", new ItemStack(Material.PAPER), "Can Identify?",
new String[] { "Players can identify & make their", "item usable using this consumable." }, new String[] { "consumable" });
public static final ItemStat CAN_DECONSTRUCT = new BooleanStat("CAN_DECONSTRUCT", new ItemStack(Material.PAPER), "Can Deconstruct?",
new String[] { "Players can deconstruct their item", "using this consumable, creating", "another random item." },
public static final ItemStat CAN_IDENTIFY = new BooleanStat("CAN_IDENTIFY", new ItemStack(Material.PAPER),
"Can Identify?", new String[] { "Players can identify & make their", "item usable using this consumable." },
new String[] { "consumable" });
public static final ItemStat CAN_DECONSTRUCT = new BooleanStat(
"CAN_DECONSTRUCT", new ItemStack(Material.PAPER), "Can Deconstruct?", new String[] {
"Players can deconstruct their item", "using this consumable, creating", "another random item." },
new String[] { "consumable" });
public static final ItemStat EFFECTS = new Effects(), PERM_EFFECTS = new PermanentEffects();
public static final ItemStat SOULBINDING_CHANCE = new DoubleStat("SOULBINDING_CHANCE", VersionMaterial.ENDER_EYE.toItem(), "Soulbinding Chance",
new String[] { "Defines the chance your item has to", "link another item to your soul,", "preventing other players from using it." },
public static final ItemStat SOULBINDING_CHANCE = new DoubleStat("SOULBINDING_CHANCE",
VersionMaterial.ENDER_EYE.toItem(), "Soulbinding Chance",
new String[] { "Defines the chance your item has to", "link another item to your soul,",
"preventing other players from using it." },
new String[] { "consumable" });
public static final ItemStat SOULBOUND_BREAK_CHANCE = new DoubleStat(
"SOULBOUND_BREAK_CHANCE", VersionMaterial.ENDER_EYE.toItem(), "Soulbound Break Chance", new String[] { "The chance of breaking an item's",
"soulbound when drag & drop'd on it.", "This chance is lowered depending", "on the soulbound's level." },
public static final ItemStat SOULBOUND_BREAK_CHANCE = new DoubleStat("SOULBOUND_BREAK_CHANCE",
VersionMaterial.ENDER_EYE.toItem(), "Soulbound Break Chance",
new String[] { "The chance of breaking an item's", "soulbound when drag & drop'd on it.",
"This chance is lowered depending", "on the soulbound's level." },
new String[] { "consumable" });
public static final ItemStat SOULBOUND_LEVEL = new SoulboundLevel();
public static final ItemStat ITEM_COOLDOWN = new DoubleStat("ITEM_COOLDOWN", new ItemStack(Material.COOKED_CHICKEN), "Item Cooldown",
new String[] { "This cooldown applies for consumables", "as well as for item commands." },
public static final ItemStat ITEM_COOLDOWN = new DoubleStat("ITEM_COOLDOWN", new ItemStack(Material.COOKED_CHICKEN),
"Item Cooldown", new String[] { "This cooldown applies for consumables", "as well as for item commands." },
new String[] { "!armor", "!gem_stone", "all" });
public static final ItemStat VANILLA_EATING_ANIMATION = new VanillaEatingAnimation(), INEDIBLE = new Inedible(), GEM_COLOR = new GemColor(),
ITEM_TYPE_RESTRICTION = new ItemTypeRestriction();
public static final ItemStat MAX_CONSUME = new DoubleStat("MAX_CONSUME", new ItemStack(Material.BLAZE_POWDER), "Max Consume",
new String[] { "Max amount of usage before", "item disappears." }, new String[] { "consumable" });
public static final ItemStat VANILLA_EATING_ANIMATION = new VanillaEatingAnimation(), INEDIBLE = new Inedible(),
GEM_COLOR = new GemColor(), ITEM_TYPE_RESTRICTION = new ItemTypeRestriction();
public static final ItemStat MAX_CONSUME = new DoubleStat("MAX_CONSUME", new ItemStack(Material.BLAZE_POWDER),
"Max Consume", new String[] { "Max amount of usage before", "item disappears." },
new String[] { "consumable" });
public static final ItemStat SUCCESS_RATE = new SuccessRate();
public static final ItemStat COMPATIBLE_TYPES = new CompatibleTypes();
public static final ItemStat CRAFTING = new Crafting(), CRAFT_PERMISSION = new CraftingPermission();
public static final ItemStat CRAFTING = new Crafting(), CRAFT_PERMISSION = new CraftingPermission(),
CRAFT_AMOUNT = new DoubleStat("CRAFTED_AMOUNT", new ItemStack(Material.WOODEN_AXE), "Crafted Amount",
new String[] { "The stack count for", "this item when crafted." }, new String[] { "all" });
public static final ItemStat AUTOSMELT = new BooleanStat("AUTOSMELT", new ItemStack(Material.COAL), "Autosmelt",
new String[] { "If set to true, your tool will", "automaticaly smelt mined ores." }, new String[] { "tool" });
public static final ItemStat BOUNCING_CRACK = new BooleanStat("BOUNCING_CRACK", VersionMaterial.COBBLESTONE_WALL.toItem(), "Bouncing Crack",
new String[] { "If set to true, your tool will", "automaticaly smelt mined ores." },
new String[] { "tool" });
public static final ItemStat BOUNCING_CRACK = new BooleanStat("BOUNCING_CRACK",
VersionMaterial.COBBLESTONE_WALL.toItem(), "Bouncing Crack",
new String[] { "If set to true, your tool will", "also break nearby blocks." }, new String[] { "tool" });
public static final ItemStat PICKAXE_POWER = new PickaxePower();
public static final ItemStat CUSTOM_SOUNDS = new CustomSounds();
public static final ItemStat ELEMENTS = new Elements();
public static final ItemStat COMMANDS = new Commands(), STAFF_SPIRIT = new StaffSpiritStat(), LUTE_ATTACK_SOUND = new LuteAttackSoundStat(),
LUTE_ATTACK_EFFECT = new LuteAttackEffectStat();
public static final ItemStat NOTE_WEIGHT = new DoubleStat("NOTE_WEIGHT", VersionMaterial.MUSIC_DISC_MALL.toItem(), "Note Weight",
new String[] { "Defines how the projectile cast", "by your lute tilts downwards." }, new String[] { "lute" });
public static final ItemStat REMOVE_ON_CRAFT = new BooleanStat("REMOVE_ON_CRAFT", new ItemStack(Material.GLASS_BOTTLE), "Remove on Craft",
new String[] { "If the item should be completely", "removed when used in a recipe,", "or if it should become an",
"empty bottle or bucket." },
new String[] { "all" }, Material.POTION, Material.SPLASH_POTION, Material.LINGERING_POTION, Material.MILK_BUCKET, Material.LAVA_BUCKET,
Material.WATER_BUCKET);
public static final ItemStat COMMANDS = new Commands(), STAFF_SPIRIT = new StaffSpiritStat(),
LUTE_ATTACK_SOUND = new LuteAttackSoundStat(), LUTE_ATTACK_EFFECT = new LuteAttackEffectStat();
public static final ItemStat NOTE_WEIGHT = new DoubleStat("NOTE_WEIGHT", VersionMaterial.MUSIC_DISC_MALL.toItem(),
"Note Weight", new String[] { "Defines how the projectile cast", "by your lute tilts downwards." },
new String[] { "lute" });
public static final ItemStat REMOVE_ON_CRAFT = new BooleanStat("REMOVE_ON_CRAFT",
new ItemStack(Material.GLASS_BOTTLE), "Remove on Craft",
new String[] { "If the item should be completely", "removed when used in a recipe,",
"or if it should become an", "empty bottle or bucket." },
new String[] { "all" }, Material.POTION, Material.SPLASH_POTION, Material.LINGERING_POTION,
Material.MILK_BUCKET, Material.LAVA_BUCKET, Material.WATER_BUCKET);
public static final ItemStat GEM_SOCKETS = new GemSockets();
public static final ItemStat REPAIR = new DoubleStat("REPAIR", new ItemStack(Material.ANVIL), "Repair",
new String[] { "The amount of durability your item", "can repair when set an item." }, new String[] { "consumable" });
new String[] { "The amount of durability your item", "can repair when set an item." },
new String[] { "consumable" });
// public static final ItemStat REPAIR_MATERIAL = new RepairMaterial();
public static final ItemStat KNOCKBACK = new DoubleStat("KNOCKBACK", VersionMaterial.IRON_HORSE_ARMOR.toItem(), "Knockback",
new String[] { "Using this musket will knock", "the user back if positive." }, new String[] { "musket" });
public static final ItemStat KNOCKBACK = new DoubleStat("KNOCKBACK", VersionMaterial.IRON_HORSE_ARMOR.toItem(),
"Knockback", new String[] { "Using this musket will knock", "the user back if positive." },
new String[] { "musket" });
public static final ItemStat RECOIL = new DoubleStat("RECOIL", VersionMaterial.IRON_HORSE_ARMOR.toItem(), "Recoil",
new String[] { "Corresponds to the shooting innacuracy." }, new String[] { "musket" });
public static final ItemStat ABILITIES = new Abilities(), UPGRADE = new UpgradeStat();
public static final ItemStat SKULL_TEXTURE = new SkullTextureStat(), DYE_COLOR = new DyeColor(), POTION_EFFECTS = new PotionEffects(),
POTION_COLOR = new PotionColor(), SHIELD_PATTERN = new ShieldPatternStat(), HIDE_POTION_EFFECTS = new HidePotionEffects();
public static final ItemStat SKULL_TEXTURE = new SkullTextureStat(), DYE_COLOR = new DyeColor(),
POTION_EFFECTS = new PotionEffects(), POTION_COLOR = new PotionColor(),
SHIELD_PATTERN = new ShieldPatternStat(), HIDE_POTION_EFFECTS = new HidePotionEffects();
/*
* internal stats
@ -262,8 +312,8 @@ public abstract class ItemStat {
private final List<Material> compatibleMaterials;
/*
* the stat can be enabled or not, depending on the server version to
* prevent from displaying useless editable stats in the edition menu.
* the stat can be enabled or not, depending on the server version to prevent
* from displaying useless editable stats in the edition menu.
*/
private boolean enabled = true;
@ -277,15 +327,14 @@ public abstract class ItemStat {
}
/*
* reads stat data from a configuration section and applies it to the item
* stack after having generated the corresponding stat data class instance
* reads stat data from a configuration section and applies it to the item stack
* after having generated the corresponding stat data class instance
*/
public abstract StatData whenInitialized(Object object);
/*
* any item stat which can be used in the item generator. this method reads
* from a config file stat data which is cached to later generate a random
* item
* any item stat which can be used in the item generator. this method reads from
* a config file stat data which is cached to later generate a random item
*/
public abstract RandomStatData whenInitializedGeneration(Object object);
@ -300,8 +349,7 @@ public abstract class ItemStat {
public abstract boolean whenClicked(EditionInventory inv, InventoryClickEvent event);
/*
* when entering input using the chat edition feature from the item edition
* menu
* when entering input using the chat edition feature from the item edition menu
*/
public abstract boolean whenInput(EditionInventory inv, ConfigFile config, String message, Object... info);

View File

@ -130,10 +130,6 @@ cooldown-progress-bar-char: █
# When toggled off, players can't damage each other using item abilities.
ability-player-damage: true
# When enabled, all custom recipes will be in the recipe book on join.
# If toggled off they will have to use to recipe once to add it to their book.
auto-recipe-book: true
# Displays a message on the action bar instead of on the chat.
# Can be used to reduce chat spam.
# Might interfere with other action bar plugins.

View File

@ -299,15 +299,15 @@ EGGNOG:
crafting:
shapeless:
'1':
item1: EGG
item2: SUGAR
item3: AIR
item4: AIR
item5: AIR
item6: AIR
item7: AIR
item8: AIR
item9: AIR
- EGG
- SUGAR
- AIR
- AIR
- AIR
- AIR
- AIR
- AIR
- AIR
MANGO:
material: PLAYER_HEAD
name: '&fMango'

View File

@ -13,6 +13,8 @@ commands:
updateitem:
description: Update the item you are holding.
aliases: [upitem,itemup]
recipes:
description: Opens the recipe book for viewing all custom recipes.
permissions:
mmoitems.admin:
description: Access to admin commands.
@ -41,3 +43,6 @@ permissions:
mmoitems.soulbound:
description: Allows to use /soulbound.
default: op
mmoitems.recipes:
description: Allows to use /recipes.
default: true