package com.earth2me.essentials.commands; import com.earth2me.essentials.ChargeException; import com.earth2me.essentials.Trade; import com.earth2me.essentials.Trade.OverflowType; import com.earth2me.essentials.User; import net.ess3.api.MaxMoneyException; import org.bukkit.Material; import org.bukkit.Server; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapelessRecipe; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import static com.earth2me.essentials.I18n.tl; public class Commandcondense extends EssentialsCommand { private final Map condenseList = new HashMap<>(); public Commandcondense() { super("condense"); } @Override public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception { List is = new ArrayList<>(); boolean validateReverse = false; if (args.length > 0) { is = ess.getItemDb().getMatching(user, args); } else { for (final ItemStack stack : user.getBase().getInventory().getContents()) { if (stack == null || stack.getType() == Material.AIR) { continue; } is.add(stack); } validateReverse = true; } boolean didConvert = false; for (final ItemStack itemStack : is) { if (condenseStack(user, itemStack, validateReverse)) { didConvert = true; } } user.getBase().updateInventory(); if (didConvert) { user.sendMessage(tl("itemsConverted")); } else { user.sendMessage(tl("itemsNotConverted")); throw new NoChargeException(); } } private boolean condenseStack(final User user, final ItemStack stack, final boolean validateReverse) throws ChargeException, MaxMoneyException { final SimpleRecipe condenseType = getCondenseType(stack); if (condenseType != null) { final ItemStack input = condenseType.getInput(); final ItemStack result = condenseType.getResult(); if (validateReverse) { boolean pass = false; for (final Recipe revRecipe : ess.getServer().getRecipesFor(input)) { if (getStackOnRecipeMatch(revRecipe, result) != null) { pass = true; break; } } if (!pass) { return false; } } int amount = 0; for (final ItemStack contents : user.getBase().getInventory().getContents()) { if (contents != null && contents.isSimilar(stack)) { amount += contents.getAmount(); } } final int output = (amount / input.getAmount()) * result.getAmount(); amount -= amount % input.getAmount(); if (amount > 0) { input.setAmount(amount); result.setAmount(output); final Trade remove = new Trade(input, ess); final Trade add = new Trade(result, ess); remove.charge(user); add.pay(user, OverflowType.DROP); return true; } } return false; } private SimpleRecipe getCondenseType(final ItemStack stack) { if (condenseList.containsKey(stack)) { return condenseList.get(stack); } final Iterator intr = ess.getServer().recipeIterator(); final List bestRecipes = new ArrayList<>(); while (intr.hasNext()) { final Recipe recipe = intr.next(); final Collection recipeItems = getStackOnRecipeMatch(recipe, stack); if (recipeItems != null && (recipeItems.size() == 4 || recipeItems.size() == 9) && (recipeItems.size() > recipe.getResult().getAmount())) { final ItemStack input = stack.clone(); input.setAmount(recipeItems.size()); final SimpleRecipe newRecipe = new SimpleRecipe(recipe.getResult(), input); bestRecipes.add(newRecipe); } } if (!bestRecipes.isEmpty()) { if (bestRecipes.size() > 1) { bestRecipes.sort(SimpleRecipeComparator.INSTANCE); } final SimpleRecipe recipe = bestRecipes.get(0); condenseList.put(stack, recipe); return recipe; } condenseList.put(stack, null); return null; } private Collection getStackOnRecipeMatch(final Recipe recipe, final ItemStack stack) { final Collection inputList; if (recipe instanceof ShapedRecipe) { final ShapedRecipe sRecipe = (ShapedRecipe) recipe; if (sRecipe.getShape().length != sRecipe.getShape()[0].length()) { // Only accept square recipes return null; } inputList = sRecipe.getIngredientMap().values(); } else if (recipe instanceof ShapelessRecipe) { final ShapelessRecipe slRecipe = (ShapelessRecipe) recipe; inputList = slRecipe.getIngredientList(); } else { return null; } boolean match = true; final Iterator iter = inputList.iterator(); while (iter.hasNext()) { final ItemStack inputSlot = iter.next(); if (inputSlot == null) { iter.remove(); continue; } if (inputSlot.getDurability() == Short.MAX_VALUE) { inputSlot.setDurability((short) 0); } if (!inputSlot.isSimilar(stack)) { match = false; } } if (match) { return inputList; } return null; } @Override protected List getTabCompleteOptions(final Server server, final User user, final String commandLabel, final String[] args) { if (args.length == 1) { return getMatchingItems(args[0]); } else { return Collections.emptyList(); } } private static final class SimpleRecipe implements Recipe { private final ItemStack result; private final ItemStack input; private SimpleRecipe(final ItemStack result, final ItemStack input) { this.result = result; this.input = input; } @Override public ItemStack getResult() { return result.clone(); } public ItemStack getInput() { return input.clone(); } } private static class SimpleRecipeComparator implements Comparator { private static final SimpleRecipeComparator INSTANCE = new SimpleRecipeComparator(); @Override public int compare(final SimpleRecipe o1, final SimpleRecipe o2) { return Integer.compare(o2.getInput().getAmount(), o1.getInput().getAmount()); } } }