Essentials/Essentials/src/main/java/com/earth2me/essentials/commands/Commandcondense.java

217 lines
7.3 KiB
Java

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<ItemStack, SimpleRecipe> 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<ItemStack> 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<Recipe> intr = ess.getServer().recipeIterator();
final List<SimpleRecipe> bestRecipes = new ArrayList<>();
while (intr.hasNext()) {
final Recipe recipe = intr.next();
final Collection<ItemStack> 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<ItemStack> getStackOnRecipeMatch(final Recipe recipe, final ItemStack stack) {
final Collection<ItemStack> 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<ItemStack> 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<String> 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<SimpleRecipe> {
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());
}
}
}