package com.comphenix.xp.rewards.items; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Random; import org.apache.commons.lang.NullArgumentException; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.bukkit.inventory.ItemStack; import com.comphenix.xp.expressions.NamedParameter; import com.comphenix.xp.expressions.VariableFunction; import com.comphenix.xp.extra.ConstantRandom; import com.comphenix.xp.lookup.ItemQuery; import com.comphenix.xp.rewards.ResourceFactory; import com.comphenix.xp.rewards.ResourceHolder; public class ItemsFactory implements ResourceFactory { // Going above this seems ridiculous public static final int MAX_STACKS = 100; private List<Entry> entries = new ArrayList<Entry>(); private double multiplier; public ItemsFactory() { this(new ArrayList<Entry>(), 1); } public ItemsFactory(double multiplier) { this(new ArrayList<Entry>(), multiplier); } private ItemsFactory(List<Entry> entries, double multiplier) { this.entries = entries; this.multiplier = multiplier; } public void addItems(ItemQuery item, VariableFunction range) { if (range == null) throw new NullArgumentException("range"); if (item == null) throw new NullArgumentException("item"); if (!item.hasItemID()) throw new IllegalArgumentException("Item must have an ID."); if (getMaximum(range) > 64 * MAX_STACKS) throw new IllegalArgumentException(String.format("Range cannot exceed %d.", 64 * MAX_STACKS)); entries.add(new Entry(item, range)); } private double getMaximum(VariableFunction range) { try { // Estimate the maximum return range.apply(ConstantRandom.MAXIMUM, null); } catch (Exception e) { return 0; } } @Override public ResourceHolder getResource(Collection<NamedParameter> params, Random rnd, int count) { List<ItemStack> stacks = new ArrayList<ItemStack>(); // Find the correct item ID and metadata for (Entry entry : entries) { try { fillInventory(params, rnd, stacks, entry, count); } catch (Exception e) { throw new RuntimeException(e); } } return new ItemsHolder(stacks); } private void fillInventory(Collection<NamedParameter> params, Random rnd, List<ItemStack> inventory, Entry entry, int count) throws Exception { int itemID = RandomSampling.getRandomElement(entry.getItemID()); int data = RandomSampling.getRandomElement(entry.getDurability(), 0); int amount = (int) (entry.getRange().apply(rnd, params) * count); while (amount > 0) { ItemStack stack = new ItemStack(itemID, 1, (short) data); Integer size = stack.getMaxStackSize(); if (amount / size > MAX_STACKS) { // NO, stop! return; } // Now, see how big this stack can become stack.setAmount(Math.min(amount, size)); amount -= stack.getAmount(); inventory.add(stack); } } @Override public ResourceFactory withMultiplier(double newMultiplier) { return new ItemsFactory(entries, newMultiplier); } @Override public double getMultiplier() { return multiplier; } @Override public ResourceHolder getResource(Collection<NamedParameter> params, Random rnd) { // Default value return getResource(params, rnd, 1); } @Override public ResourceHolder getMinimum(Collection<NamedParameter> params, int count) { return getResource(params, ConstantRandom.MINIMUM, count); } @Override public ResourceHolder getMaximum(Collection<NamedParameter> params, int count) { return getResource(params, ConstantRandom.MAXIMUM, count); } @Override public String toString() { return StringUtils.join(entries, ", "); } @Override public int hashCode() { return new HashCodeBuilder(17, 31). append(multiplier). append(entries). toHashCode(); } @Override public boolean equals(Object obj) { if (obj == null) return false; if (obj == this) return true; if (obj.getClass() != getClass()) return false; ItemsFactory other = (ItemsFactory) obj; return new EqualsBuilder(). append(multiplier, other.multiplier). append(entries, other.entries). isEquals(); } // An item and the amount to award private class Entry { private ItemQuery item; private VariableFunction range; public Entry(ItemQuery item, VariableFunction range) { this.item = item; this.range = range; } public VariableFunction getRange() { return range; } public List<Integer> getItemID() { return item.getItemID(); } public List<Integer> getDurability() { return item.getDurability(); } @Override public String toString() { return String.format("%s %s", range, item); } @Override public int hashCode() { return new HashCodeBuilder(17, 31). append(item). append(range). toHashCode(); } @Override public boolean equals(Object obj) { if (obj == null) return false; if (obj == this) return true; if (obj.getClass() != getClass()) return false; Entry other = (Entry) obj; return new EqualsBuilder(). append(item, other.item). append(range, other.range). isEquals(); } } }