Fixed recipe ingredients calculation

This commit is contained in:
Indyuce 2020-02-16 14:55:10 +01:00
parent 6c7c5df856
commit c5c2ff58a8
12 changed files with 82 additions and 48 deletions

View File

@ -20,7 +20,7 @@ public class CraftingStatus {
* saves data about items being constructed in specific stations. players
* must go back to the station GUI and claim their item once it's ready
*/
private Map<String, CraftingQueue> queues = new HashMap<>();
private final Map<String, CraftingQueue> queues = new HashMap<>();
public void load(PlayerData data, ConfigurationSection config) {
@ -72,7 +72,7 @@ public class CraftingStatus {
public class CraftingQueue {
private final String station;
private List<CraftingInfo> crafts = new ArrayList<>();
private final List<CraftingInfo> crafts = new ArrayList<>();
public CraftingQueue(CraftingStation station) {
this.station = station.getId();
@ -238,7 +238,7 @@ public class CraftingStatus {
// public void craft() {
// timedOut = true;
//
// for (IngredientInfo ingredient : recipe.getIngredients())
// for (CheckedIngredient ingredient : recipe.getIngredients())
// ingredient.getPlayerIngredient().reduceItem(ingredient.getIngredient().getAmount(),
// ingredient.getIngredient());
//

View File

@ -35,11 +35,12 @@ public class IngredientInventory {
loop: for (ItemStack item : inv.getContents())
if (item != null && item.getType() != Material.AIR) {
NBTItem nbt = MMOLib.plugin.getNMS().getNBTItem(item);
for (IngredientType ingredient : MMOItems.plugin.getCrafting().getIngredients())
for (IngredientType ingredient : MMOItems.plugin.getCrafting().getIngredients()) {
if (ingredient.check(nbt)) {
addIngredient(nbt, ingredient);
continue loop;
}
}
}
}
@ -61,11 +62,11 @@ public class IngredientInventory {
ingredients.put(key, new PlayerIngredient(item.getItem()));
}
public PlayerIngredient getIngredient(Ingredient ingredient, boolean isUpgrading) {
public PlayerIngredient getIngredient(Ingredient ingredient, IngredientLookupMode lookupMode) {
String key = ingredient.getKey();
for (String invKey : ingredients.keySet()) {
String ingredientKey = isUpgrading ? invKey.replaceFirst("-\\d*_", "_") : invKey;
String ingredientKey = lookupMode == IngredientLookupMode.IGNORE_ITEM_LEVEL ? invKey.replaceFirst("-\\d*_", "_") : invKey;
if (ingredientKey.equals(key))
return ingredients.get(invKey);
}
@ -73,20 +74,18 @@ public class IngredientInventory {
return null;
}
/*
* warning, this method might make the code run an extra set checkup! not
* deprecated because used with upgrading recipes.
*/
@Deprecated
public boolean hasIngredient(Ingredient ingredient) {
PlayerIngredient found = getIngredient(ingredient, true);
PlayerIngredient found = getIngredient(ingredient, IngredientLookupMode.IGNORE_ITEM_LEVEL);
return found != null && found.getAmount() >= ingredient.getAmount();
}
public class PlayerIngredient {
/*
* stores the corresponding ItemStacks. when the ingredient is taken off
* the player inventory, the itemstack amounts get lowered
* 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<>();
@ -110,16 +109,23 @@ public class IngredientInventory {
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;
@ -127,4 +133,22 @@ public class IngredientInventory {
}
}
}
/*
* 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;
}
}

View File

@ -29,15 +29,15 @@ public abstract class Condition {
public abstract void whenCrafting(PlayerData data);
public ConditionInfo newConditionInfo(PlayerData data) {
return new ConditionInfo(this, isMet(data));
public CheckedCondition newConditionInfo(PlayerData data) {
return new CheckedCondition(this, isMet(data));
}
public class ConditionInfo {
public class CheckedCondition {
private final Condition condition;
private final boolean met;
public ConditionInfo(Condition condition, boolean met) {
public CheckedCondition(Condition condition, boolean met) {
this.condition = condition;
this.met = met;
}

View File

@ -5,6 +5,7 @@ import org.bukkit.inventory.ItemStack;
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.util.MMOLineConfig;
@ -50,8 +51,8 @@ public abstract class Ingredient {
public abstract ItemStack generateItemStack();
public IngredientInfo newIngredientInfo(IngredientInventory inv) {
return new IngredientInfo(this, inv.getIngredient(this, false));
public CheckedIngredient newIngredientInfo(IngredientInventory inv) {
return new CheckedIngredient(this, inv.getIngredient(this, IngredientLookupMode.BASIC));
}
/*
@ -59,20 +60,20 @@ public abstract class Ingredient {
* station. ingredientInfo instances must be updated everytime the player's
* inventory updates.
*/
public class IngredientInfo {
public class CheckedIngredient {
private final Ingredient inventory;
private final PlayerIngredient player;
private final PlayerIngredient found;
private IngredientInfo(Ingredient inventory, PlayerIngredient player) {
private CheckedIngredient(Ingredient inventory, PlayerIngredient found) {
this.inventory = inventory;
this.player = player;
this.found = found;
}
/*
* checks if the player has a specific item or not
*/
public boolean isHad() {
return player != null && player.getAmount() >= inventory.getAmount();
return found != null && found.getAmount() >= inventory.getAmount();
}
public Ingredient getIngredient() {
@ -80,7 +81,7 @@ public abstract class Ingredient {
}
public PlayerIngredient getPlayerIngredient() {
return player;
return found;
}
}
}

View File

@ -42,7 +42,7 @@ public class MMOItemIngredient extends Ingredient {
@Override
public String getKey() {
return type.getId().toLowerCase() + (level != 0 ? "-" + level : "") + "_" + id.toLowerCase();
return "mmoitem:" + type.getId().toLowerCase() + (level != 0 ? "-" + level : "") + "_" + id.toLowerCase();
}
public Type getType() {

View File

@ -30,7 +30,7 @@ public class VanillaIngredient extends Ingredient {
@Override
public String getKey() {
return material.name().toLowerCase() + "_" + displayName;
return "vanilla:" + material.name().toLowerCase() + "_" + displayName;
}
@Override

View File

@ -7,17 +7,17 @@ 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.ConditionInfo;
import net.Indyuce.mmoitems.api.crafting.condition.Condition.CheckedCondition;
import net.Indyuce.mmoitems.api.crafting.condition.IngredientCondition;
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient;
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient.IngredientInfo;
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient.CheckedIngredient;
import net.Indyuce.mmoitems.api.player.PlayerData;
public class RecipeInfo {
private final Recipe recipe;
private final Set<ConditionInfo> conditions = new LinkedHashSet<>();
private final Set<IngredientInfo> ingredients = new LinkedHashSet<>();
private final Set<CheckedCondition> conditions = new LinkedHashSet<>();
private final Set<CheckedIngredient> ingredients = new LinkedHashSet<>();
private boolean ingredientsHad = true, conditionsMet = true;
@ -29,14 +29,14 @@ public class RecipeInfo {
this.recipe = recipe;
for (Ingredient ingredient : recipe.getIngredients()) {
IngredientInfo info = ingredient.newIngredientInfo(inv);
CheckedIngredient info = ingredient.newIngredientInfo(inv);
ingredients.add(info);
if (!info.isHad())
ingredientsHad = false;
}
for (Condition condition : recipe.getConditions()) {
ConditionInfo info = condition.newConditionInfo(data);
CheckedCondition info = condition.newConditionInfo(data);
conditions.add(info);
if (!info.isMet())
conditionsMet = false;
@ -68,18 +68,18 @@ public class RecipeInfo {
return recipe.display(this);
}
public ConditionInfo getCondition(String format) {
for (ConditionInfo condition : conditions)
public CheckedCondition getCondition(String format) {
for (CheckedCondition condition : conditions)
if (condition.getCondition().getId().equals(format))
return condition;
return null;
}
public Set<ConditionInfo> getConditions() {
public Set<CheckedCondition> getConditions() {
return conditions;
}
public Set<IngredientInfo> getIngredients() {
public Set<CheckedIngredient> getIngredients() {
return ingredients;
}
}

View File

@ -11,6 +11,8 @@ 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.Ingredient;
import net.Indyuce.mmoitems.api.crafting.ingredient.MMOItemIngredient;
import net.Indyuce.mmoitems.api.item.MMOItem;
@ -55,14 +57,21 @@ public class UpgradingRecipe extends Recipe {
@Override
public boolean canUse(PlayerData data, IngredientInventory inv, RecipeInfo uncastRecipe, CraftingStation station) {
if (!inv.hasIngredient(ingredient)) {
/*
* 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) {
Message.NOT_HAVE_ITEM_UPGRADE.format(ChatColor.RED).send(data.getPlayer());
data.getPlayer().playSound(data.getPlayer().getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);
return false;
}
UpgradingRecipeInfo recipe = (UpgradingRecipeInfo) uncastRecipe;
if (!(recipe.mmoitem = new MMOItem(MMOLib.plugin.getNMS().getNBTItem(inv.getIngredient(ingredient, true).getFirstItem()))).hasData(ItemStat.UPGRADE))
if (!(recipe.mmoitem = new MMOItem(MMOLib.plugin.getNMS().getNBTItem(upgraded.getFirstItem()))).hasData(ItemStat.UPGRADE))
return false;
if (!(recipe.upgradeData = (UpgradeData) recipe.getMMOItem().getData(ItemStat.UPGRADE)).canLevelUp()) {
@ -75,7 +84,7 @@ public class UpgradingRecipe extends Recipe {
Message.UPGRADE_FAIL_STATION.format(ChatColor.RED).send(data.getPlayer());
if (recipe.getUpgradeData().destroysOnFail())
recipe.getUpgraded().setAmount(recipe.getUpgraded().getAmount() - 1);
recipe.getIngredients().forEach(ingredient -> ingredient.getPlayerIngredient().reduceItem(ingredient.getIngredient().getAmount()));
data.getPlayer().playSound(data.getPlayer().getLocation(), Sound.ENTITY_ITEM_BREAK, 1, 2);
return false;

View File

@ -15,7 +15,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay;
import net.Indyuce.mmoitems.api.crafting.condition.Condition.ConditionInfo;
import net.Indyuce.mmoitems.api.crafting.condition.Condition.CheckedCondition;
import net.Indyuce.mmoitems.api.crafting.recipe.CraftingRecipe;
import net.Indyuce.mmoitems.api.crafting.recipe.RecipeInfo;
import net.Indyuce.mmoitems.api.item.plugin.ConfigItem;
@ -81,7 +81,7 @@ public class CraftingRecipeDisplay extends ConfigItem {
*/
if (str.startsWith("#condition_")) {
String format = str.substring("#condition_".length(), str.length() - 1);
ConditionInfo info = recipe.getCondition(format);
CheckedCondition info = recipe.getCondition(format);
if (info == null) {
iterator.remove();
continue;

View File

@ -14,7 +14,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay;
import net.Indyuce.mmoitems.api.crafting.condition.Condition.ConditionInfo;
import net.Indyuce.mmoitems.api.crafting.condition.Condition.CheckedCondition;
import net.Indyuce.mmoitems.api.crafting.recipe.RecipeInfo;
import net.Indyuce.mmoitems.api.crafting.recipe.UpgradingRecipe;
import net.Indyuce.mmoitems.api.item.plugin.ConfigItem;
@ -65,7 +65,7 @@ public class UpgradingRecipeDisplay extends ConfigItem {
*/
if (str.startsWith("#condition_")) {
String format = str.substring("#condition_".length(), str.length() - 1);
ConditionInfo info = recipe.getCondition(format);
CheckedCondition info = recipe.getCondition(format);
if (info == null) {
iterator.remove();
continue;

View File

@ -14,7 +14,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.crafting.CraftingStation;
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient.IngredientInfo;
import net.Indyuce.mmoitems.api.crafting.ingredient.Ingredient.CheckedIngredient;
import net.Indyuce.mmoitems.api.crafting.recipe.CraftingRecipe;
import net.Indyuce.mmoitems.api.crafting.recipe.RecipeInfo;
import net.Indyuce.mmoitems.api.crafting.recipe.UpgradingRecipe;
@ -27,7 +27,7 @@ public class CraftingStationPreview extends PluginInventory {
private final CraftingStation station;
private final RecipeInfo recipe;
private List<IngredientInfo> ingredients = new ArrayList<>();
private List<CheckedIngredient> ingredients = new ArrayList<>();
private static final int[]
slots = { 12, 13, 14, 21, 22, 23, 30, 31, 32 },

View File

@ -57,12 +57,12 @@ public class CraftingManager {
registerCondition("class", config -> new ClassCondition(config), new ConditionalDisplay("&a" + AltChar.check + " Required Class: #class#", "&c" + AltChar.cross + " Required Class: #class#"));
registerCondition("ingredient", config -> new IngredientCondition(), null);
registerIngredient("vanilla", config -> new VanillaIngredient(config), new ConditionalDisplay("&8" + AltChar.check + " &7#amount# #item#", "&c" + AltChar.cross + " &7#amount# #item#"), nbt -> true, item -> {
registerIngredient("vanilla", config -> new VanillaIngredient(config), 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", config -> new MMOItemIngredient(config), new ConditionalDisplay("&8" + AltChar.check + " &7#amount# #level# #item#", "&c" + AltChar.cross + " &7#amount# #level# #item#"), nbt -> nbt.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();
});
registerIngredient("mmoitem", config -> new MMOItemIngredient(config), new ConditionalDisplay("&8" + AltChar.check + " &7#amount# #level# #item#", "&c" + AltChar.cross + " &7#amount# #level# #item#"), nbt -> nbt.hasType(), item -> item.getItem().getType().name().toLowerCase() + "_" + (item.getItem().hasItemMeta() ? item.getItem().getItemMeta().getDisplayName() : null));
}
public void reload() {