mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2024-12-23 04:47:34 +01:00
!Rewrote crafting station player ingredients
This commit is contained in:
parent
2ecaf4572c
commit
2f73a572ea
@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.api.crafting;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.util.PostLoadObject;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CheckedRecipe;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CraftingRecipe;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.Recipe;
|
||||
|
@ -1,19 +1,14 @@
|
||||
package net.Indyuce.mmoitems.api.crafting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.crafting.CraftingStatus.CraftingQueue.CraftingInfo;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CraftingRecipe;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.Recipe;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class CraftingStatus {
|
||||
|
||||
@ -170,103 +165,4 @@ public class CraftingStatus {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* instant craft: the progress bar is displayed on the subtitle and players
|
||||
* must stay around their initial position or the craft will be cancelled
|
||||
*/
|
||||
// private InstantCraftingInfo instant;
|
||||
//
|
||||
// public InstantCraftingInfo getInstant() {
|
||||
// return instant;
|
||||
// }
|
||||
//
|
||||
// public
|
||||
// public class InstantCraftingInfo extends CraftingInfo {
|
||||
// private final PlayerDataManager data;
|
||||
// private boolean timedOut;
|
||||
//
|
||||
// public InstantCraftingInfo(PlayerDataManager data, Recipe recipe) {
|
||||
// super(recipe);
|
||||
// this.data = data;
|
||||
// }
|
||||
//
|
||||
// public void start() {
|
||||
// data.getPlayer().closeInventory();
|
||||
//
|
||||
// new BukkitRunnable() {
|
||||
// int t = 0;
|
||||
// final String format =
|
||||
// Message.CRAFTING_SUBTITLE.formatRaw(ChatColor.GREEN);
|
||||
// final Location loc = data.getPlayer().getLocation().clone();
|
||||
//
|
||||
// public void run() {
|
||||
// t++;
|
||||
//
|
||||
// if (data.getPlayer() == null || !data.getPlayer().isOnline() ||
|
||||
// data.getPlayer().isDead() ||
|
||||
// !data.getPlayer().getWorld().equals(loc.getWorld()) ||
|
||||
// loc.distanceSquared(data.getPlayer().getLocation()) > 15) {
|
||||
// timedOut = true;
|
||||
// cancel();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if ((double) t / 10 > recipe.getRecipe().getCraftingTime()) {
|
||||
// timedOut = true;
|
||||
//
|
||||
// recipe = recipe.getRecipe().getRecipeInfo(data, new
|
||||
// IngredientInventory(data.getPlayer()));
|
||||
// if (!recipe.areConditionsMet()) {
|
||||
// Message.CONDITIONS_NOT_MET.format(ChatColor.RED).send(data.getPlayer());
|
||||
// data.getPlayer().playSound(data.getPlayer().getLocation(),
|
||||
// Sound.ENTITY_VILLAGER_NO, 1, 1);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (!recipe.allIngredientsHad()) {
|
||||
// Message.NOT_ENOUGH_MATERIALS.format(ChatColor.RED).send(data.getPlayer());
|
||||
// data.getPlayer().playSound(data.getPlayer().getLocation(),
|
||||
// Sound.ENTITY_VILLAGER_NO, 1, 1);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// craft();
|
||||
//
|
||||
// cancel();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// double left = recipe.getRecipe().getCraftingTime() - (double) t / 10;
|
||||
// double r = (double) t / 10 / recipe.getRecipe().getCraftingTime();
|
||||
// data.getPlayer().sendTitle("", format.replace("#left#",
|
||||
// formatDelay(left)).replace("#bar#", MMOUtils.getProgressBar(r, 10,
|
||||
// AltChar.square)), 0, 20, 10);
|
||||
// }
|
||||
// }.runTaskTimer(MMOItems.plugin, 0, 2);
|
||||
// }
|
||||
//
|
||||
// public void craft() {
|
||||
// timedOut = true;
|
||||
//
|
||||
// for (CheckedIngredient ingredient : recipe.getIngredients())
|
||||
// ingredient.getPlayerIngredient().reduceItem(ingredient.getIngredient().getAmount(),
|
||||
// ingredient.getIngredient());
|
||||
//
|
||||
// data.getPlayer().playSound(data.getPlayer().getLocation(),
|
||||
// Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1);
|
||||
// for (ItemStack drop :
|
||||
// data.getPlayer().getInventory().addItem(recipe.getRecipe().getOutput().generate()).values())
|
||||
// data.getPlayer().getWorld().dropItem(data.getPlayer().getLocation(),
|
||||
// drop);
|
||||
//
|
||||
// updateData();
|
||||
// open();
|
||||
// }
|
||||
//
|
||||
// public boolean isTimedOut() {
|
||||
// return timedOut || (System.currentTimeMillis() - started >
|
||||
// recipe.getRecipe().getCraftingTime());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@ -1,193 +0,0 @@
|
||||
package net.Indyuce.mmoitems.api.crafting;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.api.util.ui.QuickNumberRange;
|
||||
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.manager.CraftingManager.IngredientType;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class IngredientInventory {
|
||||
|
||||
/*
|
||||
* ingredients in the map are not stored using class instances as keys but
|
||||
* using a unique string which is an unique ingredient identifier. allows
|
||||
* for faster map check ups and fixes the >64 amount and ingredient
|
||||
* splitting glitches
|
||||
*/
|
||||
private final Map<String, PlayerIngredient> ingredients = new HashMap<>();
|
||||
|
||||
public IngredientInventory(Player player) { this(player.getInventory()); }
|
||||
|
||||
public IngredientInventory(Inventory inv) {
|
||||
loop: for (ItemStack item : inv.getContents())
|
||||
if (item != null && item.getType() != Material.AIR) {
|
||||
NBTItem nbt = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item);
|
||||
for (IngredientType ingredient : MMOItems.plugin.getCrafting().getIngredients()) {
|
||||
if (ingredient.check(nbt)) {
|
||||
addIngredient(nbt, ingredient);
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addIngredient(NBTItem item, IngredientType ingredient) {
|
||||
String key = ingredient.getId() + ":" + ingredient.readKey(item);
|
||||
|
||||
if (ingredients.containsKey(key))
|
||||
|
||||
/*
|
||||
* add to current ingredient a specific amount.
|
||||
*/
|
||||
ingredients.get(key).add(item.getItem());
|
||||
else
|
||||
|
||||
/*
|
||||
* load an item stack and turn it into an ingredient which makes
|
||||
* checking ingredients later much faster.
|
||||
*/
|
||||
ingredients.put(key, new PlayerIngredient(item.getItem()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PlayerIngredient getIngredient(@NotNull Ingredient ingredient, @NotNull IngredientLookupMode lookupMode) {
|
||||
String key = ingredient.getKey();
|
||||
|
||||
// Find level
|
||||
QuickNumberRange lvl = null;
|
||||
int dsh = key.indexOf('-');
|
||||
if (dsh > 0) {
|
||||
|
||||
// Get lvl
|
||||
String itemCrop = key.substring(dsh + 1);
|
||||
String itemLevel = itemCrop.substring(0, itemCrop.indexOf('_'));
|
||||
lvl = QuickNumberRange.getFromString(itemLevel);
|
||||
key = key.substring(0, dsh) + key.substring(dsh + 1 + itemLevel.length()); }
|
||||
|
||||
// Remove lvl
|
||||
//ING//MMOItems.log("\u00a7a>\u00a78>\u00a77 Reading ingredient\u00a7a " + key + "\u00a77 (of level \u00a7a" + lvl + "\u00a77)");
|
||||
|
||||
for (String invKey : ingredients.keySet()) {
|
||||
|
||||
int dash = invKey.indexOf('-');
|
||||
Integer itemLvl = null;
|
||||
String ingredientKey = invKey;
|
||||
if (dash > 0) {
|
||||
|
||||
// Get lvl
|
||||
String itemCrop = invKey.substring(dash + 1);
|
||||
String itemLevel = itemCrop.substring(0, itemCrop.indexOf('_'));
|
||||
itemLvl = SilentNumbers.IntegerParse(itemLevel);
|
||||
ingredientKey = invKey.substring(0, dash) + invKey.substring(dash + 1 + itemLevel.length()); }
|
||||
|
||||
|
||||
// Compare removing level
|
||||
//ING//MMOItems.log(" \u00a7a>\u00a77 Comparing to \u00a7b" + invKey + "\u00a77 (\u00a73" + ingredientKey + "\u00a77)");
|
||||
|
||||
if (ingredientKey.equals(key)) {
|
||||
|
||||
// Get level
|
||||
boolean levelMet = true;
|
||||
if (lookupMode != IngredientLookupMode.IGNORE_ITEM_LEVEL && lvl != null) {
|
||||
|
||||
// Parse
|
||||
if (itemLvl == null) { itemLvl = 0; }
|
||||
levelMet = lvl.inRange(itemLvl);
|
||||
//ING//MMOItems.log(" \u00a7a>\u00a77 Was level \u00a7e" + invKey + "\u00a77 (\u00a76" + levelMet + "\u00a77)");
|
||||
}
|
||||
|
||||
if (levelMet) { return ingredients.get(invKey); }
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean hasIngredient(Ingredient ingredient) {
|
||||
PlayerIngredient found = getIngredient(ingredient, IngredientLookupMode.IGNORE_ITEM_LEVEL);
|
||||
return found != null && found.getAmount() >= ingredient.getAmount();
|
||||
}
|
||||
|
||||
public static class PlayerIngredient {
|
||||
|
||||
/*
|
||||
* stores items which correspond to a specific ingredient. when the
|
||||
* ingredient is taken off the player inventory, the itemstack amounts
|
||||
* get lowered. these POINT towards the player inventory itemStacks.
|
||||
*/
|
||||
private final List<ItemStack> items = new ArrayList<>();
|
||||
|
||||
public PlayerIngredient(ItemStack item) {
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
int t = 0;
|
||||
for (ItemStack item : items)
|
||||
t += item.getAmount();
|
||||
return t;
|
||||
}
|
||||
|
||||
public void add(ItemStack item) {
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
// used for upgrading recipes
|
||||
public ItemStack getFirstItem() {
|
||||
return items.get(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* algorythm which takes away a certain amount of items. used to consume
|
||||
* ingredients when using recipes
|
||||
*/
|
||||
public void reduceItem(int amount) {
|
||||
|
||||
Iterator<ItemStack> iterator = items.iterator();
|
||||
while (iterator.hasNext() && amount > 0) {
|
||||
ItemStack item = iterator.next();
|
||||
|
||||
// remove itemStack from list if amount <= 0
|
||||
if (item.getAmount() < 1) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
// amount of items it can take from this particular ItemStack
|
||||
int take = Math.min(item.getAmount(), amount);
|
||||
|
||||
amount -= take;
|
||||
item.setAmount(item.getAmount() - take);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* could use a boolean because there are only two states possible, but makes
|
||||
* things clearer.
|
||||
*/
|
||||
public enum IngredientLookupMode {
|
||||
|
||||
/*
|
||||
* item level must be ignored when the player is using an upgrading
|
||||
* recipe, otherwise recipe cannot identify right item
|
||||
*/
|
||||
IGNORE_ITEM_LEVEL,
|
||||
|
||||
/*
|
||||
* scans ingredient inventory considering item levels
|
||||
*/
|
||||
BASIC
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package net.Indyuce.mmoitems.api.crafting;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Used to handle both ingredients and conditions because they share the same
|
||||
* properties:
|
||||
* - a way to display them in the recipe item lore.
|
||||
* - some string identifier
|
||||
* - a function which takes as input a line config and returns a loaded ingredient/condition
|
||||
*
|
||||
* @param <C> Either Condition or Ingredient
|
||||
*/
|
||||
public class LoadedCraftingObject<C> {
|
||||
private final String id;
|
||||
private final Function<MMOLineConfig, C> function;
|
||||
|
||||
private ConditionalDisplay display;
|
||||
|
||||
public LoadedCraftingObject(String id, Function<MMOLineConfig, C> function, ConditionalDisplay display) {
|
||||
this.id = id;
|
||||
this.function = function;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setDisplay(ConditionalDisplay display) {
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public boolean hasDisplay() {
|
||||
return display != null;
|
||||
}
|
||||
|
||||
public ConditionalDisplay getDisplay() {
|
||||
return display;
|
||||
}
|
||||
|
||||
public C load(MMOLineConfig config) {
|
||||
return function.apply(config);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.condition;
|
||||
|
||||
public class CheckedCondition {
|
||||
private final Condition condition;
|
||||
private final boolean met;
|
||||
|
||||
/**
|
||||
* Instanciated everytime a condition needs to be evaluated for a player
|
||||
* when evaluating a CheckedRecipe (when a player is opening a crafting
|
||||
* station)
|
||||
*
|
||||
* @param condition Condition being evaluated
|
||||
* @param met If the condition is met or not
|
||||
*/
|
||||
public CheckedCondition(Condition condition, boolean met) {
|
||||
this.condition = condition;
|
||||
this.met = met;
|
||||
}
|
||||
|
||||
public boolean isMet() {
|
||||
return met;
|
||||
}
|
||||
|
||||
public Condition getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public String format() {
|
||||
return condition.formatDisplay(isMet() ? condition.getDisplay().getPositive() : condition.getDisplay().getNegative());
|
||||
}
|
||||
}
|
@ -56,34 +56,4 @@ public abstract class Condition {
|
||||
public CheckedCondition evaluateCondition(PlayerData data) {
|
||||
return new CheckedCondition(this, isMet(data));
|
||||
}
|
||||
|
||||
public static class CheckedCondition {
|
||||
private final Condition condition;
|
||||
private final boolean met;
|
||||
|
||||
/**
|
||||
* Instanciated everytime a condition needs to be evaluated for a player
|
||||
* when evaluating a CheckedRecipe (when a player is opening a crafting
|
||||
* station)
|
||||
*
|
||||
* @param condition Condition being evaluated
|
||||
* @param met If the condition is met or not
|
||||
*/
|
||||
public CheckedCondition(Condition condition, boolean met) {
|
||||
this.condition = condition;
|
||||
this.met = met;
|
||||
}
|
||||
|
||||
public boolean isMet() {
|
||||
return met;
|
||||
}
|
||||
|
||||
public Condition getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public String format() {
|
||||
return condition.formatDisplay(isMet() ? condition.getDisplay().getPositive() : condition.getDisplay().getNegative());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,95 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.ingredient;
|
||||
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.PlayerIngredient;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class CheckedIngredient {
|
||||
@NotNull
|
||||
private final Ingredient ingredient;
|
||||
@Nullable
|
||||
private final Set<PlayerIngredient> found;
|
||||
private final boolean isHad;
|
||||
|
||||
/**
|
||||
* Instantiated everytime an ingredient is evaluated for a player when a
|
||||
* CheckedRecipe is being created (when a player is opening a crafting
|
||||
* station). This helps greatly reducing ingredient checkups by caching
|
||||
* the items the plugin will need to take off the player's ingredient
|
||||
*
|
||||
* @param ingredient The ingredient being evaluated
|
||||
* @param found The corresponding ingredient found in the player's
|
||||
* ingredient
|
||||
*/
|
||||
public CheckedIngredient(@NotNull Ingredient ingredient, @Nullable Set<PlayerIngredient> found) {
|
||||
this.ingredient = ingredient;
|
||||
this.found = found;
|
||||
this.isHad = getTotalAmount() >= ingredient.getAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the player has enough of the specific item or not
|
||||
*/
|
||||
public boolean isHad() {
|
||||
return isHad;
|
||||
}
|
||||
|
||||
public int getTotalAmount() {
|
||||
int total = 0;
|
||||
for (PlayerIngredient ing : this.found)
|
||||
total += ing.getAmount();
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes off the required amount of ingredients from a player's inventory.
|
||||
*/
|
||||
public void takeAway() {
|
||||
reduceItem(ingredient.getAmount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes off a specific amount of ingredients from a player's inventory.
|
||||
*
|
||||
* @param amount Amount to take off the player's inventory.
|
||||
* It most likely matches ingredient.getAmount()
|
||||
*/
|
||||
public void reduceItem(int amount) {
|
||||
|
||||
Iterator<PlayerIngredient> iterator = found.iterator();
|
||||
while (iterator.hasNext() && amount > 0) {
|
||||
ItemStack item = iterator.next().getItem();
|
||||
|
||||
// Remove itemStack from list if amount <= 0
|
||||
if (item.getAmount() <= 0) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Amount of items it can take from this particular ItemStack
|
||||
int take = Math.min(item.getAmount(), amount);
|
||||
|
||||
amount -= take;
|
||||
item.setAmount(item.getAmount() - take);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Ingredient getIngredient() {
|
||||
return ingredient;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<PlayerIngredient> getFound() {
|
||||
return found;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String format() {
|
||||
return ingredient.formatDisplay(isHad() ? ingredient.getDisplay().getPositive() : ingredient.getDisplay().getNegative());
|
||||
}
|
||||
}
|
@ -3,15 +3,18 @@ package net.Indyuce.mmoitems.api.crafting.ingredient;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay;
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory.IngredientLookupMode;
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory.PlayerIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.PlayerIngredient;
|
||||
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class Ingredient {
|
||||
/**
|
||||
* An ingredient from a crafting station recipe.
|
||||
* <p>
|
||||
* See {@link PlayerIngredient} for more information.
|
||||
*/
|
||||
public abstract class Ingredient<C extends PlayerIngredient> {
|
||||
private final String id;
|
||||
private final int amount;
|
||||
|
||||
@ -24,6 +27,10 @@ public abstract class Ingredient {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The ingredient type id i.e the string placed
|
||||
* at the beginning of the line config
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
@ -43,7 +50,9 @@ public abstract class Ingredient {
|
||||
/**
|
||||
* @return The ingredient key which is used internally by MMOItems to check
|
||||
* if two ingredients are of the same nature.
|
||||
* @deprecated Apart from ingredient type keys, keys are not used anymore.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract String getKey();
|
||||
|
||||
/**
|
||||
@ -54,49 +63,20 @@ public abstract class Ingredient {
|
||||
*/
|
||||
public abstract String formatDisplay(String s);
|
||||
|
||||
public abstract boolean matches(C playerIngredient);
|
||||
|
||||
/**
|
||||
* When the player right-clicks one of the items in a station, they can
|
||||
* preview the stats if itself and the components it is made of. This
|
||||
* is called to displace those preview elements.
|
||||
*
|
||||
* @param player Player looking at the recipe
|
||||
*
|
||||
* @return The ItemStack to display to the player
|
||||
*/
|
||||
@NotNull public abstract ItemStack generateItemStack(@NotNull RPGPlayer player);
|
||||
@NotNull
|
||||
public abstract ItemStack generateItemStack(@NotNull RPGPlayer player);
|
||||
|
||||
public CheckedIngredient evaluateIngredient(@NotNull IngredientInventory inv) {
|
||||
return new CheckedIngredient(this, inv.getIngredient(this, IngredientLookupMode.BASIC));
|
||||
}
|
||||
|
||||
public static class CheckedIngredient {
|
||||
@NotNull private final Ingredient ingredient;
|
||||
@Nullable private final PlayerIngredient found;
|
||||
|
||||
/**
|
||||
* Instantiated everytime an ingredient is evaluated for a player when a
|
||||
* CheckedRecipe is being created (when a player is opening a crafting
|
||||
* station). This helps greatly reducing ingredient checkups by caching
|
||||
* the items the plugin will need to take off the player's ingredient
|
||||
*
|
||||
* @param ingredient The ingredient being evaluated
|
||||
* @param found The corresponding ingredient found in the player's
|
||||
* ingredient
|
||||
*/
|
||||
private CheckedIngredient(@NotNull Ingredient ingredient, @Nullable PlayerIngredient found) {
|
||||
this.ingredient = ingredient;
|
||||
this.found = found;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the player has enough of the specific item or not
|
||||
*/
|
||||
public boolean isHad() { return found != null && found.getAmount() >= ingredient.getAmount(); }
|
||||
|
||||
@NotNull public Ingredient getIngredient() { return ingredient; }
|
||||
|
||||
@Nullable public PlayerIngredient getPlayerIngredient() { return found; }
|
||||
|
||||
@NotNull public String format() { return ingredient.formatDisplay(isHad() ? ingredient.getDisplay().getPositive() : ingredient.getDisplay().getNegative()); }
|
||||
return inv.findMatching(this);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.ingredient;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay;
|
||||
import net.Indyuce.mmoitems.api.crafting.LoadedCraftingObject;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.PlayerIngredient;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A type of ingredient, like a vanilla ingredient or a MMOItems ingredient.
|
||||
* <p>
|
||||
* See {@link PlayerIngredient} for more information.
|
||||
*/
|
||||
public class IngredientType extends LoadedCraftingObject<Ingredient> {
|
||||
private final Predicate<NBTItem> check;
|
||||
private final Function<NBTItem, PlayerIngredient> readIngredient;
|
||||
|
||||
public IngredientType(String id, Function<MMOLineConfig, Ingredient> function, ConditionalDisplay display, Predicate<NBTItem> check, Function<NBTItem, PlayerIngredient> readIngredient) {
|
||||
super(id, function, display);
|
||||
|
||||
this.check = check;
|
||||
this.readIngredient = readIngredient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the checked item can be handled by this ingredient
|
||||
*/
|
||||
public boolean check(NBTItem item) {
|
||||
return check.test(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the ingredient from an NBTItem, called after checking
|
||||
* that this ingredient type can handle this NBTItem
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public PlayerIngredient readPlayerIngredient(NBTItem item) {
|
||||
return readIngredient.apply(item);
|
||||
}
|
||||
}
|
@ -1,28 +1,29 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.ingredient;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import io.lumine.mythic.lib.api.util.ui.QuickNumberRange;
|
||||
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
||||
import net.Indyuce.mmoitems.ItemStats;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
|
||||
import net.Indyuce.mmoitems.stat.DisplayName;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.crafting.ConfigMMOItem;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.MMOItemPlayerIngredient;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
|
||||
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
|
||||
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||
import net.Indyuce.mmoitems.stat.DisplayName;
|
||||
import net.Indyuce.mmoitems.stat.data.MaterialData;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class MMOItemIngredient extends Ingredient {
|
||||
public class MMOItemIngredient extends Ingredient<MMOItemPlayerIngredient> {
|
||||
private final MMOItemTemplate template;
|
||||
|
||||
@NotNull private final QuickNumberRange level;
|
||||
@NotNull
|
||||
private final QuickNumberRange level;
|
||||
private final String display;
|
||||
|
||||
public MMOItemIngredient(MMOLineConfig config) {
|
||||
@ -64,7 +65,28 @@ public class MMOItemIngredient extends Ingredient {
|
||||
return s.replace("#item#", display).replace("#level#", (level.hasMax() || level.hasMax()) ? "lvl." + level.toString() + " " : "").replace("#amount#", String.valueOf(getAmount()));
|
||||
}
|
||||
|
||||
@NotNull @Override public ItemStack generateItemStack(@NotNull RPGPlayer player) {
|
||||
@Override
|
||||
public boolean matches(MMOItemPlayerIngredient playerIngredient) {
|
||||
|
||||
// Check for item type
|
||||
if (!playerIngredient.getType().equals(template.getType().getId()))
|
||||
return false;
|
||||
|
||||
// Check for item id
|
||||
if (!playerIngredient.getId().equals(template.getId()))
|
||||
return false;
|
||||
|
||||
// Checks for level range
|
||||
if (SilentNumbers.floor(level.getAsDouble(0)) != 0 && !level.inRange(playerIngredient.getUpgradeLevel()))
|
||||
return false;
|
||||
|
||||
// Yuss
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack generateItemStack(@NotNull RPGPlayer player) {
|
||||
|
||||
// Generate fresh from the template
|
||||
MMOItem mmo = template.newBuilder(player).build();
|
||||
@ -93,17 +115,22 @@ public class MMOItemIngredient extends Ingredient {
|
||||
}
|
||||
|
||||
private String findName() {
|
||||
String name = null;
|
||||
String name;
|
||||
|
||||
// By default, take item display name
|
||||
if (template.getBaseItemData().containsKey(ItemStats.NAME))
|
||||
name = template.getBaseItemData().get(ItemStats.NAME).toString().replace("<tier-color>", "").replace("<tier-name>", "").replace("<tier-color-cleaned>", "");
|
||||
|
||||
if (template.getBaseItemData().containsKey(ItemStats.MATERIAL) && name == null)
|
||||
// Try and take the material name
|
||||
else if (template.getBaseItemData().containsKey(ItemStats.MATERIAL))
|
||||
name = MMOUtils.caseOnWords(((MaterialData) template.getBaseItemData().get(ItemStats.MATERIAL)).getMaterial().name().toLowerCase().replace("_", " "));
|
||||
|
||||
if (name == null) { name = "Unrecognized Item"; }
|
||||
// Ultra rare case to avoid a NPE
|
||||
else name = "Unrecognized Item";
|
||||
|
||||
// Append upgrade level
|
||||
if (SilentNumbers.floor(level.getAsDouble(0)) != 0) { return DisplayName.appendUpgradeLevel(name, SilentNumbers.floor(level.getAsDouble(0))); }
|
||||
if (SilentNumbers.floor(level.getAsDouble(0)) != 0)
|
||||
return DisplayName.appendUpgradeLevel(name, SilentNumbers.floor(level.getAsDouble(0)));
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.ingredient;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.api.util.LegacyComponent;
|
||||
import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.VanillaPlayerIngredient;
|
||||
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class VanillaIngredient extends Ingredient {
|
||||
public class VanillaIngredient extends Ingredient<VanillaPlayerIngredient> {
|
||||
private final Material material;
|
||||
|
||||
/**
|
||||
@ -40,6 +40,17 @@ public class VanillaIngredient extends Ingredient {
|
||||
return s.replace("#item#", display).replace("#amount#", "" + getAmount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(VanillaPlayerIngredient ing) {
|
||||
|
||||
// Check for material
|
||||
if (ing.getType() != material)
|
||||
return false;
|
||||
|
||||
// Check for display name
|
||||
return ing.getDisplayName() != null ? ing.getDisplayName().equals(displayName) : displayName == null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack generateItemStack(@NotNull RPGPlayer player) {
|
||||
|
@ -0,0 +1,111 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.ingredient.inventory;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.CheckedIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.IngredientType;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class IngredientInventory {
|
||||
private final Map<String, Set<PlayerIngredient>> ingredients = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Loads all the possible crafting station ingredients from a player's inventory
|
||||
*/
|
||||
public IngredientInventory(Player player) {
|
||||
this(player.getInventory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all the possible crafting station ingredients from an inventory
|
||||
*/
|
||||
public IngredientInventory(Inventory inv) {
|
||||
loop:
|
||||
for (ItemStack item : inv.getContents())
|
||||
if (item != null && item.getType() != Material.AIR && item.getAmount() > 0) {
|
||||
NBTItem nbt = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item);
|
||||
for (IngredientType ingredient : MMOItems.plugin.getCrafting().getIngredients()) {
|
||||
if (ingredient.check(nbt)) {
|
||||
addIngredient(nbt, ingredient);
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an ingredient.
|
||||
*
|
||||
* @param item The actual item in the inventory
|
||||
* @param ingredient The type of the ingredient added
|
||||
*/
|
||||
public void addIngredient(NBTItem item, IngredientType ingredient) {
|
||||
String key = ingredient.getId();
|
||||
|
||||
// Add to existing set
|
||||
if (ingredients.containsKey(key))
|
||||
ingredients.get(key).add(ingredient.readPlayerIngredient(item));
|
||||
|
||||
// Initialize
|
||||
else {
|
||||
Set<PlayerIngredient> ingredients = new HashSet<>();
|
||||
ingredients.add(ingredient.readPlayerIngredient(item));
|
||||
this.ingredients.put(key, ingredients);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CheckedIngredient findMatching(@NotNull Ingredient ingredient) {
|
||||
Set<PlayerIngredient> found = new HashSet<>();
|
||||
if (!ingredients.containsKey(ingredient.getId()))
|
||||
return new CheckedIngredient(ingredient, found);
|
||||
|
||||
for (PlayerIngredient checked : ingredients.get(ingredient.getId()))
|
||||
if (ingredient.matches(checked))
|
||||
found.add(checked);
|
||||
|
||||
return new CheckedIngredient(ingredient, found);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated First use {@link #findMatching(Ingredient)} and cache its
|
||||
* result to use the isHad() method of returned class instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean hasIngredient(Ingredient ingredient) {
|
||||
return findMatching(ingredient).isHad();
|
||||
}
|
||||
|
||||
/**
|
||||
* Could use a boolean because there are only two
|
||||
* states possible, but makes things clearer.
|
||||
*
|
||||
* @deprecated Since 6.6 where ingredients were recoded.
|
||||
*/
|
||||
@Deprecated
|
||||
public enum IngredientLookupMode {
|
||||
|
||||
/**
|
||||
* Item level must be ignored when the player is using an upgrading
|
||||
* recipe, otherwise recipe cannot identify right item
|
||||
*/
|
||||
IGNORE_ITEM_LEVEL,
|
||||
|
||||
/**
|
||||
* Scans ingredient inventory considering item levels
|
||||
*/
|
||||
BASIC
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.ingredient.inventory;
|
||||
|
||||
import com.google.gson.JsonParser;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
|
||||
public class MMOItemPlayerIngredient extends PlayerIngredient {
|
||||
|
||||
/*
|
||||
* No need to save as MMOItemTemplate or Type instances. Just need the string,
|
||||
* because if they don't exist the recipe ingredients won't load anyways.
|
||||
* And it's better for performance yes
|
||||
*/
|
||||
private final String type, id;
|
||||
|
||||
/**
|
||||
* Used to check if the level of the player's item matches
|
||||
* the level range given by the recipe ingredient.
|
||||
*/
|
||||
private final int upgradeLevel;
|
||||
|
||||
// TODO also add support for item level range? Quite easy to implement with the new PlayerIngredient interface.
|
||||
|
||||
public MMOItemPlayerIngredient(NBTItem item) {
|
||||
super(item);
|
||||
|
||||
this.type = item.getString("MMOITEMS_ITEM_TYPE");
|
||||
this.id = item.getString("MMOITEMS_ITEM_ID");
|
||||
|
||||
String upgradeString = item.getString("MMOITEMS_UPGRADE");
|
||||
this.upgradeLevel = !upgradeString.isEmpty() ? new JsonParser().parse(upgradeString).getAsJsonObject().get("Level").getAsInt() : 0;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getUpgradeLevel() {
|
||||
return upgradeLevel;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.ingredient.inventory;
|
||||
|
||||
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.CheckedIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.IngredientType;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CheckedRecipe;
|
||||
import net.Indyuce.mmoitems.manager.CraftingManager;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Code architecture for all the classes concerning Ingredients.
|
||||
* <p>
|
||||
* MMOItems based ingredients / vanilla based ingredients are called IngredientTypes.
|
||||
* One {@link IngredientType} is loaded for every type of ingredient there exists.
|
||||
* External plugins can register other types of ingredients using
|
||||
* {@link CraftingManager#registerIngredient(String, Function, ConditionalDisplay, Predicate, Function)}.
|
||||
* <p>
|
||||
* Once all the ingredient types are loaded, stations are loaded from the config files.
|
||||
* That means loading the ingredients from the recipes which is what {@link Ingredient} is used for.
|
||||
* <p>
|
||||
* When a player opens a crafting station, MMOItems must first calculate all the ingredients
|
||||
* they have in their inventory. A {@link IngredientInventory} is created, calculating all
|
||||
* the ingredients the player has using the {@link PlayerIngredient} interface.
|
||||
* <p>
|
||||
* The second step when opening a crafting station is comparing the ingredients required for one
|
||||
* crafting recipe to the current player's ingredients, which is done using {@link CheckedIngredient}
|
||||
* when creating {@link CheckedRecipe}.
|
||||
*
|
||||
* @author indyuce
|
||||
*/
|
||||
public abstract class PlayerIngredient {
|
||||
|
||||
/**
|
||||
* Redirects to the player's item in his inventory. This can be
|
||||
* used later by MMOItems to reduce the amount of items in his inventory
|
||||
* to take off ingredients from him.
|
||||
*/
|
||||
private final ItemStack item;
|
||||
|
||||
public PlayerIngredient(NBTItem item) {
|
||||
|
||||
// Throw NBTItem to garbage collector because no longer needed
|
||||
this.item = item.getItem();
|
||||
}
|
||||
|
||||
public ItemStack getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return item.getAmount();
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.ingredient.inventory;
|
||||
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class VanillaPlayerIngredient extends PlayerIngredient {
|
||||
private final Material material;
|
||||
@Nullable
|
||||
private final String displayName;
|
||||
|
||||
public VanillaPlayerIngredient(NBTItem item) {
|
||||
super(item);
|
||||
|
||||
this.material = item.getItem().getType();
|
||||
|
||||
ItemMeta meta = item.getItem().getItemMeta();
|
||||
this.displayName = meta.hasDisplayName() ? meta.getDisplayName() : null;
|
||||
}
|
||||
|
||||
public Material getType() {
|
||||
return material;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
}
|
@ -1,18 +1,17 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.recipe;
|
||||
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.CheckedCondition;
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.Condition;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.CheckedIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.Condition;
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.Condition.CheckedCondition;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient.CheckedIngredient;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
|
||||
public class CheckedRecipe {
|
||||
private final Recipe recipe;
|
||||
|
||||
@ -54,6 +53,10 @@ public class CheckedRecipe {
|
||||
return recipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if both conditions are met and ingredients are gathered
|
||||
* @deprecated Not used internally anymore
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isUnlocked() {
|
||||
return ingredientsHad && conditionsMet;
|
||||
|
@ -4,7 +4,7 @@ import io.lumine.mythic.lib.api.util.SmartGive;
|
||||
import net.Indyuce.mmoitems.api.crafting.ConfigMMOItem;
|
||||
import net.Indyuce.mmoitems.api.crafting.CraftingStation;
|
||||
import net.Indyuce.mmoitems.api.crafting.CraftingStatus.CraftingQueue;
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.event.PlayerUseCraftingStationEvent;
|
||||
import net.Indyuce.mmoitems.api.item.util.ConfigItems;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
@ -19,7 +19,7 @@ public class CraftingRecipe extends Recipe {
|
||||
private final ConfigMMOItem output;
|
||||
|
||||
/*
|
||||
* there can't be any crafting time for upgrading recipes since there is no
|
||||
* There can't be any crafting time for upgrading recipes since there is no
|
||||
* way to save an MMOItem in the config file TODO save as ItemStack
|
||||
*/
|
||||
private final double craftingTime;
|
||||
@ -96,4 +96,9 @@ public class CraftingRecipe extends Recipe {
|
||||
public ItemStack display(CheckedRecipe recipe) {
|
||||
return ConfigItems.CRAFTING_RECIPE_DISPLAY.newBuilder(recipe).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CheckedRecipe evaluateRecipe(PlayerData data, IngredientInventory inv) {
|
||||
return new CheckedRecipe(this, data, inv);
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ package net.Indyuce.mmoitems.api.crafting.recipe;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.crafting.CraftingStation;
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.Condition;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.trigger.Trigger;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import org.apache.commons.lang.Validate;
|
||||
@ -51,7 +51,6 @@ public abstract class Recipe {
|
||||
for (String format : config.getStringList("ingredients"))
|
||||
try {
|
||||
Ingredient ingredient = MMOItems.plugin.getCrafting().getIngredient(new MMOLineConfig(format));
|
||||
Validate.notNull(ingredient, "Could not match ingredient");
|
||||
ingredients.add(ingredient);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new IllegalArgumentException("Could not load ingredient '" + format + "': " + exception.getMessage());
|
||||
@ -63,7 +62,6 @@ public abstract class Recipe {
|
||||
for (String format : config.getStringList("conditions"))
|
||||
try {
|
||||
Condition condition = MMOItems.plugin.getCrafting().getCondition(new MMOLineConfig(format));
|
||||
Validate.notNull(condition, "Could not match condition");
|
||||
conditions.add(condition);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new IllegalArgumentException("Could not load condition '" + format + "': " + exception.getMessage());
|
||||
@ -131,14 +129,16 @@ public abstract class Recipe {
|
||||
options.put(option, value);
|
||||
}
|
||||
|
||||
public CheckedRecipe evaluateRecipe(PlayerData data, IngredientInventory inv) {
|
||||
return new CheckedRecipe(this, data, inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Recipe && ((Recipe) obj).id.equals(id);
|
||||
}
|
||||
/**
|
||||
* THE method that checks if a player can use a recipe or not. This checks for
|
||||
* conditions and ingredients and saves all the info needed to display everything
|
||||
* in the item lore.
|
||||
*
|
||||
* @param data Player trying to use the recipe
|
||||
* @param inv The ingredients of the player
|
||||
* @return Class that knows if the player can use the recipe
|
||||
*/
|
||||
public abstract CheckedRecipe evaluateRecipe(PlayerData data, IngredientInventory inv);
|
||||
|
||||
/**
|
||||
* Called when all the recipe conditions are to true and when the player
|
||||
@ -167,7 +167,12 @@ public abstract class Recipe {
|
||||
|
||||
public abstract ItemStack display(CheckedRecipe recipe);
|
||||
|
||||
public enum RecipeOption {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Recipe && ((Recipe) obj).id.equals(id);
|
||||
}
|
||||
|
||||
public static enum RecipeOption {
|
||||
|
||||
/**
|
||||
* Hide the crafting recipe when one of the condition is not met
|
||||
|
@ -1,27 +1,25 @@
|
||||
package net.Indyuce.mmoitems.api.crafting.recipe;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import net.Indyuce.mmoitems.ItemStats;
|
||||
import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.crafting.ConfigMMOItem;
|
||||
import net.Indyuce.mmoitems.api.crafting.CraftingStation;
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory.IngredientLookupMode;
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory.PlayerIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.CheckedIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.MMOItemIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
|
||||
import net.Indyuce.mmoitems.api.item.util.ConfigItems;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import net.Indyuce.mmoitems.api.util.message.Message;
|
||||
import net.Indyuce.mmoitems.stat.data.UpgradeData;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class UpgradingRecipe extends Recipe {
|
||||
private final ConfigMMOItem item;
|
||||
@ -32,9 +30,7 @@ public class UpgradingRecipe extends Recipe {
|
||||
public UpgradingRecipe(ConfigurationSection config) {
|
||||
super(config);
|
||||
|
||||
/*
|
||||
* load item being upgraded.
|
||||
*/
|
||||
// load item being upgraded.
|
||||
item = new ConfigMMOItem(config.getConfigurationSection("item"));
|
||||
ingredient = new MMOItemIngredient(item);
|
||||
}
|
||||
@ -44,12 +40,12 @@ public class UpgradingRecipe extends Recipe {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe uncastRecipe, CraftingStation station) {
|
||||
UpgradingRecipeInfo recipe = (UpgradingRecipeInfo) uncastRecipe;
|
||||
public void whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe castRecipe, CraftingStation station) {
|
||||
CheckedUpgradingRecipe recipe = (CheckedUpgradingRecipe) castRecipe;
|
||||
recipe.getUpgradeData().upgrade(recipe.getMMOItem());
|
||||
recipe.getUpgraded().setItemMeta(recipe.getMMOItem().newBuilder().build().getItemMeta());
|
||||
|
||||
uncastRecipe.getRecipe().getTriggers().forEach(trigger -> trigger.whenCrafting(data));
|
||||
castRecipe.getRecipe().getTriggers().forEach(trigger -> trigger.whenCrafting(data));
|
||||
if (!data.isOnline())
|
||||
return;
|
||||
|
||||
@ -60,14 +56,9 @@ public class UpgradingRecipe extends Recipe {
|
||||
@Override
|
||||
public boolean canUse(PlayerData data, IngredientInventory inv, CheckedRecipe uncastRecipe, CraftingStation station) {
|
||||
|
||||
/*
|
||||
* try to find the item which is meant to be updated. null check is
|
||||
* ugly, BUT it does halve calculations done because it does not calls
|
||||
* two map lookups. it is not needed to check for the amount because
|
||||
* only one item is upgraded.
|
||||
*/
|
||||
PlayerIngredient upgraded = inv.getIngredient(ingredient, IngredientLookupMode.IGNORE_ITEM_LEVEL);
|
||||
if (upgraded == null) {
|
||||
// Find the item which should be upgraded
|
||||
CheckedIngredient upgraded = inv.findMatching(ingredient);
|
||||
if (!upgraded.isHad()) {
|
||||
if (!data.isOnline())
|
||||
return false;
|
||||
|
||||
@ -76,11 +67,15 @@ public class UpgradingRecipe extends Recipe {
|
||||
return false;
|
||||
}
|
||||
|
||||
UpgradingRecipeInfo recipe = (UpgradingRecipeInfo) uncastRecipe;
|
||||
if (!(recipe.mmoitem = new LiveMMOItem(MythicLib.plugin.getVersion().getWrapper().getNBTItem(upgraded.getFirstItem())))
|
||||
.hasData(ItemStats.UPGRADE))
|
||||
// Finds the item that will be upgraded
|
||||
NBTItem firstItem = NBTItem.get(upgraded.getFound().stream().findFirst().get().getItem());
|
||||
|
||||
// Checks if upgraded item DOES has an upgrade template
|
||||
CheckedUpgradingRecipe recipe = (CheckedUpgradingRecipe) uncastRecipe;
|
||||
if (!(recipe.mmoitem = new LiveMMOItem(firstItem)).hasData(ItemStats.UPGRADE))
|
||||
return false;
|
||||
|
||||
// Checks for max upgrade level
|
||||
if (!(recipe.upgradeData = (UpgradeData) recipe.getMMOItem().getData(ItemStats.UPGRADE)).canLevelUp()) {
|
||||
if (!data.isOnline())
|
||||
return false;
|
||||
@ -90,11 +85,16 @@ public class UpgradingRecipe extends Recipe {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks for failure
|
||||
if (random.nextDouble() > recipe.getUpgradeData().getSuccess()) {
|
||||
|
||||
// Should the item be destroyed when failing to upgrade
|
||||
if (recipe.getUpgradeData().destroysOnFail())
|
||||
recipe.getUpgraded().setAmount(recipe.getUpgraded().getAmount() - 1);
|
||||
|
||||
recipe.getIngredients().forEach(ingredient -> ingredient.getPlayerIngredient().reduceItem(ingredient.getIngredient().getAmount()));
|
||||
// Take away ingredients
|
||||
recipe.getIngredients().forEach(ingredient -> ingredient.takeAway());
|
||||
|
||||
if (!data.isOnline())
|
||||
return false;
|
||||
|
||||
@ -113,14 +113,18 @@ public class UpgradingRecipe extends Recipe {
|
||||
|
||||
@Override
|
||||
public CheckedRecipe evaluateRecipe(PlayerData data, IngredientInventory inv) {
|
||||
return new UpgradingRecipeInfo(this, data, inv);
|
||||
return new CheckedUpgradingRecipe(this, data, inv);
|
||||
}
|
||||
|
||||
public static class UpgradingRecipeInfo extends CheckedRecipe {
|
||||
/**
|
||||
* Used to cache the LiveMMOItem instance and UpgradeData
|
||||
* which take a little performance to calculate.
|
||||
*/
|
||||
public class CheckedUpgradingRecipe extends CheckedRecipe {
|
||||
private LiveMMOItem mmoitem;
|
||||
private UpgradeData upgradeData;
|
||||
|
||||
public UpgradingRecipeInfo(Recipe recipe, PlayerData data, IngredientInventory inv) {
|
||||
public CheckedUpgradingRecipe(Recipe recipe, PlayerData data, IngredientInventory inv) {
|
||||
super(recipe, data, inv);
|
||||
}
|
||||
|
||||
|
@ -3,25 +3,19 @@ package net.Indyuce.mmoitems.api.item.template;
|
||||
import io.lumine.mythic.lib.api.util.PostLoadObject;
|
||||
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackCategory;
|
||||
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
|
||||
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
||||
import net.Indyuce.mmoitems.ItemStats;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.ItemTier;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.item.ItemReference;
|
||||
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
|
||||
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
|
||||
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
||||
import net.Indyuce.mmoitems.stat.type.ItemStat;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
@ -149,7 +143,6 @@ public class MMOItemTemplate extends PostLoadObject implements ItemReference {
|
||||
return options.contains(option);
|
||||
}
|
||||
|
||||
|
||||
public MMOItemBuilder newBuilder(@Nullable Player player) {
|
||||
if (player != null) { return newBuilder(PlayerData.get(player).getRPG()); }
|
||||
return newBuilder((RPGPlayer) null);
|
||||
|
@ -7,7 +7,7 @@ import io.lumine.mythic.lib.api.util.LegacyComponent;
|
||||
import io.lumine.mythic.utils.adventure.text.Component;
|
||||
import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay;
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.Condition.CheckedCondition;
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.CheckedCondition;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CheckedRecipe;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CraftingRecipe;
|
||||
import net.Indyuce.mmoitems.api.item.util.ConfigItem;
|
||||
|
@ -1,13 +1,12 @@
|
||||
package net.Indyuce.mmoitems.api.item.util.crafting;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.item.ItemTag;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.api.util.LegacyComponent;
|
||||
import io.lumine.mythic.utils.adventure.text.Component;
|
||||
import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay;
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.Condition.CheckedCondition;
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.CheckedCondition;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CheckedRecipe;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.UpgradingRecipe;
|
||||
import net.Indyuce.mmoitems.api.item.util.ConfigItem;
|
||||
@ -16,11 +15,7 @@ import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class UpgradingRecipeDisplay extends ConfigItem {
|
||||
public UpgradingRecipeDisplay() {
|
||||
|
@ -1,19 +1,25 @@
|
||||
package net.Indyuce.mmoitems.comp.mythicmobs.crafting;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import io.lumine.xikage.mythicmobs.MythicMobs;
|
||||
import io.lumine.xikage.mythicmobs.adapters.bukkit.BukkitAdapter;
|
||||
import io.lumine.xikage.mythicmobs.items.MythicItem;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class MythicItemIngredient extends Ingredient {
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* No way of checking if an item was generated using MythicMobs? There does
|
||||
* not seem to be any NBTTag for that using the latest dev build
|
||||
*
|
||||
* @deprecated Not implemented yet
|
||||
*/
|
||||
@Deprecated
|
||||
public class MythicItemIngredient extends Ingredient<MythicItemPlayerIngredient> {
|
||||
private final MythicItem mythicitem;
|
||||
|
||||
private final String display;
|
||||
@ -39,6 +45,11 @@ public class MythicItemIngredient extends Ingredient {
|
||||
return s.replace("#item#", display).replace("#amount#", "" + getAmount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(MythicItemPlayerIngredient playerIngredient) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack generateItemStack(@NotNull RPGPlayer player) {
|
||||
|
@ -0,0 +1,29 @@
|
||||
package net.Indyuce.mmoitems.comp.mythicmobs.crafting;
|
||||
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.PlayerIngredient;
|
||||
|
||||
/**
|
||||
* @deprecated Not implemented yet
|
||||
*/
|
||||
@Deprecated
|
||||
public class MythicItemPlayerIngredient extends PlayerIngredient {
|
||||
private final String type, id;
|
||||
|
||||
public MythicItemPlayerIngredient(NBTItem item) {
|
||||
super(item);
|
||||
|
||||
type = item.getString("MYTHIC_TYPE").toLowerCase();
|
||||
|
||||
// No idea what to use here
|
||||
id = null;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import io.lumine.mythic.lib.api.util.LegacyComponent;
|
||||
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
||||
import io.lumine.mythic.utils.adventure.text.Component;
|
||||
import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient.CheckedIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.CheckedIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CheckedRecipe;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CraftingRecipe;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.UpgradingRecipe;
|
||||
|
@ -8,9 +8,9 @@ import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.crafting.CraftingStation;
|
||||
import net.Indyuce.mmoitems.api.crafting.CraftingStatus.CraftingQueue;
|
||||
import net.Indyuce.mmoitems.api.crafting.CraftingStatus.CraftingQueue.CraftingInfo;
|
||||
import net.Indyuce.mmoitems.api.crafting.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.Layout;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CheckedRecipe;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.CraftingRecipe;
|
||||
import net.Indyuce.mmoitems.api.crafting.recipe.Recipe;
|
||||
@ -34,6 +34,7 @@ import java.util.UUID;
|
||||
public class CraftingStationView extends PluginInventory {
|
||||
private final CraftingStation station;
|
||||
private final Layout layout;
|
||||
|
||||
private List<CheckedRecipe> recipes;
|
||||
private IngredientInventory ingredients;
|
||||
|
||||
@ -128,6 +129,7 @@ public class CraftingStationView extends PluginInventory {
|
||||
public void whenClicked(InventoryClickEvent event) {
|
||||
if (!playerData.isOnline())
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
if (!MMOUtils.isMetaItem(event.getCurrentItem(), false))
|
||||
return;
|
||||
@ -159,18 +161,17 @@ public class CraftingStationView extends PluginInventory {
|
||||
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCurrentItem());
|
||||
String tag = item.getString("recipeId");
|
||||
if (!tag.equals("")) {
|
||||
if (!tag.isEmpty()) {
|
||||
CheckedRecipe recipe = getRecipe(tag);
|
||||
if (event.isRightClick()) {
|
||||
if (event.isRightClick())
|
||||
new CraftingStationPreview(this, recipe).open();
|
||||
return;
|
||||
}
|
||||
|
||||
else {
|
||||
processRecipe(recipe);
|
||||
open();
|
||||
}
|
||||
}
|
||||
|
||||
if (!(tag = item.getString("queueId")).equals("")) {
|
||||
if (!(tag = item.getString("queueId")).isEmpty()) {
|
||||
UUID uuid = UUID.fromString(tag);
|
||||
CraftingInfo recipeInfo = playerData.getCrafting().getQueue(station).getCraft(uuid);
|
||||
CraftingRecipe recipe = recipeInfo.getRecipe();
|
||||
@ -247,7 +248,7 @@ public class CraftingStationView extends PluginInventory {
|
||||
return;
|
||||
|
||||
recipe.getRecipe().whenUsed(playerData, ingredients, recipe, station);
|
||||
recipe.getIngredients().forEach(ingredient -> ingredient.getPlayerIngredient().reduceItem(ingredient.getIngredient().getAmount()));
|
||||
recipe.getIngredients().forEach(ingredient -> ingredient.takeAway());
|
||||
recipe.getConditions().forEach(condition -> condition.getCondition().whenCrafting(playerData));
|
||||
|
||||
updateData();
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.Indyuce.mmoitems.manager;
|
||||
|
||||
import com.google.gson.JsonParser;
|
||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.api.util.AltChar;
|
||||
@ -8,16 +7,22 @@ import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.ConfigFile;
|
||||
import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay;
|
||||
import net.Indyuce.mmoitems.api.crafting.CraftingStation;
|
||||
import net.Indyuce.mmoitems.api.crafting.LoadedCraftingObject;
|
||||
import net.Indyuce.mmoitems.api.crafting.condition.*;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.IngredientType;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.MMOItemIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.VanillaIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.MMOItemPlayerIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.PlayerIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.VanillaPlayerIngredient;
|
||||
import net.Indyuce.mmoitems.api.crafting.trigger.*;
|
||||
import net.Indyuce.mmoitems.comp.mythicmobs.crafting.MythicItemIngredient;
|
||||
import net.Indyuce.mmoitems.comp.mythicmobs.crafting.MythicMobsSkillTrigger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
@ -26,18 +31,19 @@ import java.util.logging.Level;
|
||||
|
||||
public class CraftingManager implements Reloadable {
|
||||
|
||||
/*
|
||||
* order matters when trying to recognize an ingredient type: if none
|
||||
/**
|
||||
* Order matters when trying to recognize an ingredient type: if none
|
||||
* ingredient matches, the item is considered as a vanilla item.
|
||||
*/
|
||||
private final List<IngredientType> ingredients = new ArrayList<>();
|
||||
private final Set<LoadedObject<Condition>> conditions = new HashSet<>();
|
||||
private final Set<LoadedObject<Trigger>> triggers = new HashSet<>();
|
||||
private final Set<LoadedCraftingObject<Condition>> conditions = new HashSet<>();
|
||||
private final Set<LoadedCraftingObject<Trigger>> triggers = new HashSet<>();
|
||||
|
||||
private final Map<String, CraftingStation> stations = new HashMap<>();
|
||||
|
||||
public CraftingManager() {
|
||||
// conditions
|
||||
|
||||
// Conditions
|
||||
registerCondition("level", LevelCondition::new, new ConditionalDisplay("&a" + AltChar.check + " Requires Level #level#", "&c" + AltChar.cross + " Requires Level #level#"));
|
||||
registerCondition("permission", PermissionCondition::new, null);
|
||||
registerCondition("placeholder", PlaceholderCondition::new, null);
|
||||
@ -46,26 +52,22 @@ public class CraftingManager implements Reloadable {
|
||||
registerCondition("food", FoodCondition::new, new ConditionalDisplay("&a" + AltChar.check + " Requires #food# Food", "&c" + AltChar.cross + " Requires #food# Food"));
|
||||
registerCondition("class", ClassCondition::new, new ConditionalDisplay("&a" + AltChar.check + " Required Class: #class#", "&c" + AltChar.cross + " Required Class: #class#"));
|
||||
|
||||
// triggers
|
||||
// Triggers
|
||||
registerTrigger("command", CommandTrigger::new);
|
||||
registerTrigger("message", MessageTrigger::new);
|
||||
registerTrigger("sound", SoundTrigger::new);
|
||||
registerTrigger("vanilla", VanillaTrigger::new);
|
||||
registerTrigger("mmoitem", MMOItemTrigger::new);
|
||||
|
||||
// ingredients
|
||||
registerIngredient("vanilla", VanillaIngredient::new, new ConditionalDisplay("&8" + AltChar.check + " &7#amount# #item#", "&c" + AltChar.cross + " &7#amount# #item#"), nbt -> true, item -> item.getItem().getType().name().toLowerCase() + "_" + (item.getItem().hasItemMeta() ? item.getItem().getItemMeta().getDisplayName() : null));
|
||||
registerIngredient("mmoitem", MMOItemIngredient::new, new ConditionalDisplay("&8" + AltChar.check + " &7#amount# #level##item#", "&c" + AltChar.cross + " &7#amount# #level##item#"), NBTItem::hasType, item -> {
|
||||
String upgradeString = item.getString("MMOITEMS_UPGRADE");
|
||||
int level = !upgradeString.isEmpty() ? new JsonParser().parse(upgradeString).getAsJsonObject().get("Level").getAsInt() : 0;
|
||||
return item.getString("MMOITEMS_ITEM_TYPE").toLowerCase() + (level != 0 ? "-" + level : "") + "_" + item.getString("MMOITEMS_ITEM_ID").toLowerCase();
|
||||
});
|
||||
// Ingredients
|
||||
registerIngredient("vanilla", VanillaIngredient::new, new ConditionalDisplay("&8" + AltChar.check + " &7#amount# #item#", "&c" + AltChar.cross + " &7#amount# #item#"), nbt -> true, VanillaPlayerIngredient::new);
|
||||
registerIngredient("mmoitem", MMOItemIngredient::new, new ConditionalDisplay("&8" + AltChar.check + " &7#amount# #level##item#", "&c" + AltChar.cross + " &7#amount# #level##item#"), NBTItem::hasType, MMOItemPlayerIngredient::new);
|
||||
|
||||
// mm comp
|
||||
// MythicMobs native compatibility
|
||||
if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) {
|
||||
registerIngredient("mythicitem", MythicItemIngredient::new,
|
||||
/*registerIngredient("mythicitem", MythicItemIngredient::new,
|
||||
new ConditionalDisplay("&8" + AltChar.check + " &7#amount# #item#", "&c" + AltChar.cross + " &7#amount# #item#"),
|
||||
nbt -> nbt.hasTag("MYTHIC_TYPE"), nbt -> nbt.getString("MYTHIC_TYPE").toLowerCase());
|
||||
nbt -> nbt.hasTag("MYTHIC_TYPE"), MythicItemPlayerIngredient::new);*/
|
||||
registerTrigger("mmskill", MythicMobsSkillTrigger::new);
|
||||
}
|
||||
}
|
||||
@ -75,7 +77,7 @@ public class CraftingManager implements Reloadable {
|
||||
|
||||
ConfigFile language = new ConfigFile("/language", "crafting-stations");
|
||||
|
||||
for (LoadedObject<Condition> condition : getConditions())
|
||||
for (LoadedCraftingObject<Condition> condition : getConditions())
|
||||
if (condition.hasDisplay()) {
|
||||
String path = "condition." + condition.getId();
|
||||
if (!language.getConfig().contains(path)) {
|
||||
@ -134,6 +136,11 @@ public class CraftingManager implements Reloadable {
|
||||
return stations.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the corresponding ingredient type, and from there
|
||||
* load the corresponding ingredient from the line config
|
||||
*/
|
||||
@NotNull
|
||||
public Ingredient getIngredient(MMOLineConfig config) {
|
||||
String key = config.getKey();
|
||||
|
||||
@ -141,113 +148,91 @@ public class CraftingManager implements Reloadable {
|
||||
if (ingredient.getId().equals(key))
|
||||
return ingredient.load(config);
|
||||
|
||||
return null;
|
||||
throw new IllegalArgumentException("Could not match ingredient");
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the corresponding condition type, and from there
|
||||
* load the corresponding condition from the line config
|
||||
*/
|
||||
@NotNull
|
||||
public Condition getCondition(MMOLineConfig config) {
|
||||
String key = config.getKey();
|
||||
|
||||
for (LoadedObject<Condition> condition : conditions)
|
||||
for (LoadedCraftingObject<Condition> condition : conditions)
|
||||
if (condition.getId().equalsIgnoreCase(key))
|
||||
return condition.load(config);
|
||||
|
||||
return null;
|
||||
throw new IllegalArgumentException("Could not match condition");
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the corresponding trigger type, and from there
|
||||
* load the corresponding trigger from the line config
|
||||
*/
|
||||
@NotNull
|
||||
public Trigger getTrigger(MMOLineConfig config) {
|
||||
String key = config.getKey();
|
||||
|
||||
for (LoadedObject<Trigger> trigger : triggers)
|
||||
for (LoadedCraftingObject<Trigger> trigger : triggers)
|
||||
if (trigger.getId().equalsIgnoreCase(key))
|
||||
return trigger.load(config);
|
||||
|
||||
return null;
|
||||
throw new IllegalArgumentException("Could not match trigger");
|
||||
}
|
||||
|
||||
public List<IngredientType> getIngredients() {
|
||||
return ingredients;
|
||||
}
|
||||
|
||||
public Set<LoadedObject<Condition>> getConditions() {
|
||||
public Set<LoadedCraftingObject<Condition>> getConditions() {
|
||||
return conditions;
|
||||
}
|
||||
|
||||
public Set<LoadedObject<Trigger>> getTriggers() {
|
||||
public Set<LoadedCraftingObject<Trigger>> getTriggers() {
|
||||
return triggers;
|
||||
}
|
||||
|
||||
public void registerIngredient(String id, Function<MMOLineConfig, Ingredient> function, ConditionalDisplay display, Predicate<NBTItem> check, Function<NBTItem, String> read) {
|
||||
ingredients.add(0, new IngredientType(id, function, display, check, read));
|
||||
/**
|
||||
* Registers a type of ingredient in MMOItems crafting stations
|
||||
* <p>
|
||||
* See {@link IngredientType} for more information.
|
||||
*
|
||||
* @param id The ingredient id
|
||||
* @param function Function that loads an ingredient from a line config
|
||||
* @param display How it displays in the item lore
|
||||
* @param check Should return true if an item can be handled by this ingredient type
|
||||
* @param readIngredient After checking if this ingredient type can handle an item,
|
||||
* method called to provide the corresponding PlayerIngredient
|
||||
*/
|
||||
public void registerIngredient(String id, Function<MMOLineConfig, Ingredient> function, ConditionalDisplay display, Predicate<NBTItem> check, Function<NBTItem, PlayerIngredient> readIngredient) {
|
||||
ingredients.add(0, new IngredientType(id, function, display, check, readIngredient));
|
||||
}
|
||||
|
||||
public void registerCondition(String id, Function<MMOLineConfig, Condition> function, ConditionalDisplay display) {
|
||||
conditions.add(new LoadedObject<>(id, function, display));
|
||||
/**
|
||||
* Registers a type of condition in MMOItems crafting stations
|
||||
*
|
||||
* @param id Condition ID
|
||||
* @param function Function that loads a condition from a line conf
|
||||
* @param display How it displays in the item lore, null if it should not
|
||||
*/
|
||||
public void registerCondition(String id, Function<MMOLineConfig, Condition> function, @Nullable ConditionalDisplay display) {
|
||||
conditions.add(new LoadedCraftingObject<>(id, function, display));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a type of trigger in MMOItems crafting stations. Unlike
|
||||
* conditions or ingredients, triggers don't need to be displayed
|
||||
* in the item lore therefore no 'display' argument is required.
|
||||
*
|
||||
* @param id Trigger ID
|
||||
* @param function Function that loads that type of trigger from a line configuration
|
||||
*/
|
||||
public void registerTrigger(String id, Function<MMOLineConfig, Trigger> function) {
|
||||
triggers.add(new LoadedObject<>(id, function, null));
|
||||
triggers.add(new LoadedCraftingObject<Trigger>(id, function, null));
|
||||
}
|
||||
|
||||
public Collection<CraftingStation> getAll() {
|
||||
return stations.values();
|
||||
}
|
||||
|
||||
public static class LoadedObject<C> {
|
||||
private final String id;
|
||||
private final Function<MMOLineConfig, C> function;
|
||||
|
||||
private ConditionalDisplay display;
|
||||
|
||||
public LoadedObject(String id, Function<MMOLineConfig, C> function, ConditionalDisplay display) {
|
||||
this.id = id;
|
||||
this.function = function;
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setDisplay(ConditionalDisplay display) {
|
||||
this.display = display;
|
||||
}
|
||||
|
||||
public boolean hasDisplay() {
|
||||
return display != null;
|
||||
}
|
||||
|
||||
public ConditionalDisplay getDisplay() {
|
||||
return display;
|
||||
}
|
||||
|
||||
public C load(MMOLineConfig config) {
|
||||
return function.apply(config);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IngredientType extends LoadedObject<Ingredient> {
|
||||
private final Predicate<NBTItem> check;
|
||||
private final Function<NBTItem, String> read;
|
||||
|
||||
public IngredientType(String id, Function<MMOLineConfig, Ingredient> function, ConditionalDisplay display, Predicate<NBTItem> check, Function<NBTItem, String> read) {
|
||||
super(id, function, display);
|
||||
|
||||
this.check = check;
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns true if the checked item can be handled by this ingredient
|
||||
*/
|
||||
public boolean check(NBTItem item) {
|
||||
return check.test(item);
|
||||
}
|
||||
|
||||
/*
|
||||
* reads the ingredient read from an NBTItem
|
||||
*/
|
||||
public String readKey(NBTItem item) {
|
||||
return read.apply(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user