/* * ExperienceMod - Bukkit server plugin for modifying the experience system in Minecraft. * Copyright (C) 2012 Kristian S. Stangeland * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ package com.comphenix.xp.lookup; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.bukkit.Material; import org.bukkit.potion.Potion; import org.bukkit.potion.PotionType; import com.comphenix.xp.parser.Utility; import com.comphenix.xp.rewards.items.RandomSampling; import com.google.common.collect.Lists; public class PotionQuery implements Query { // DON'T CARE fields are empty private List<PotionType> type; private List<Integer> level; private List<Boolean> extended; private List<Boolean> splash; // Optimize away object creations private static List<PotionType> noTypes = new ArrayList<PotionType>(); private static List<Integer> noLevels = new ArrayList<Integer>(); private static List<Boolean> noBooleans = new ArrayList<Boolean>(); /** * Universal query. * @return Universal query. */ public static PotionQuery fromAny() { return new PotionQuery(noTypes, noLevels, noBooleans, noBooleans); } public static PotionQuery fromAny(PotionType type) { return fromAny(type, null, null, null); } public static PotionQuery fromAny(PotionType type, Integer level) { return fromAny(type, level, null, null); } public static PotionQuery fromAny(PotionType type, Integer level, Boolean extended, Boolean splash) { return new PotionQuery( Utility.getElementList(type), Utility.getElementList(level), Utility.getElementList(extended), Utility.getElementList(splash) ); } public static PotionQuery fromExact(PotionType type, Integer level, Boolean extended, Boolean splash) { return new PotionQuery( Lists.newArrayList(type), Lists.newArrayList(level), Lists.newArrayList(extended), Lists.newArrayList(splash) ); } public PotionQuery(List<PotionType> type, List<Integer> level, List<Boolean> extended, List<Boolean> splash) { this.type = type; this.level = level; this.extended = extended; this.splash = splash; } public PotionQuery(Potion potionObject) { if (potionObject == null) throw new IllegalArgumentException("Potion must be non-zero."); addPotion(potionObject); } public PotionQuery(ItemQuery query) { if (!query.match(Material.POTION)) throw new IllegalArgumentException("Can only create potion queries from potions."); if (!query.hasDurability()) throw new IllegalArgumentException("Must contain a durability value."); reset(); for (Integer durability : query.getDurability()) { if (durability == 0) { type.add(PotionType.WATER); } else { addPotion(Potion.fromDamage(durability)); } } } private void addPotion(Potion potion) { // Load values if (potion != null) { type.add(potion.getType()); level.add(potion.getLevel()); extended.add(potion.hasExtendedDuration()); splash.add(potion.isSplash()); } } private void reset() { this.type = new ArrayList<PotionType>(); this.level = new ArrayList<Integer>(); this.extended = new ArrayList<Boolean>(); this.splash = new ArrayList<Boolean>(); } public List<PotionType> getType() { return type; } public List<Integer> getLevel() { return level; } public List<Boolean> getExtended() { return extended; } public List<Boolean> getSplash() { return splash; } public boolean hasType() { return type != null && !type.isEmpty(); } public boolean hasLevel() { return level != null && !level.isEmpty(); } public boolean hasExtended() { return extended != null && !extended.isEmpty(); } public boolean hasSplash() { return splash != null && !splash.isEmpty(); } /** * Converts this potion query to an item query. * <p> * If this query contains multiple conflicting parameters, a value will be picked at random if <i>pickRandom</i> * is set to TRUE. If it is FALSE, an exception will be thrown. * * @param pickRandom - TRUE to solve conflicts by picking values at random. * @return Item query equivalent of this query. * @throws IllegalArgumentException - if pickRandom is FALSE and there are conflicting parameters, */ public ItemQuery toItemQuery(boolean pickRandom) { // Handle if (!pickRandom) { if (hasType() && type.size() == 1 && hasLevel() && level.size() == 1 && hasExtended() && extended.size() == 1 && hasSplash() && splash.size() == 1) { // Acceptible } else { throw new IllegalArgumentException("Cannot create potion from conflicting parameters."); } } return ItemQuery.fromExact(Material.POTION.getId(), (int) createPotion().toDamageValue()); } private Potion createPotion() { Potion current = new Potion(RandomSampling.getRandomElement(type, PotionType.WATER), RandomSampling.getRandomElement(level, 1)); // Set extended or splash potion if (RandomSampling.getRandomElement(extended, false)) current.extend(); if (RandomSampling.getRandomElement(splash, false)) current.splash(); return current; } @Override public int hashCode() { return new HashCodeBuilder(17, 31). append(type). append(level). append(extended). append(splash). toHashCode(); } @Override public boolean equals(Object obj) { if (obj == null) return false; if (obj == this) return true; if (obj.getClass() != getClass()) return false; PotionQuery other = (PotionQuery) obj; return new EqualsBuilder(). append(type, other.type). append(level, other.level). append(extended, other.extended). append(splash, other.splash). isEquals(); } @Override public boolean match(Query other) { // Yes, we could construct a MobTree, put the current MobQuery // into it and query after other, but this is faster. Probably. if (other instanceof PotionQuery) { PotionQuery query = (PotionQuery) other; // Make sure the current query is the superset of other return QueryMatching.matchParameter(type, query.type) && QueryMatching.matchParameter(level, query.level) && QueryMatching.matchParameter(extended, query.extended) && QueryMatching.matchParameter(splash, query.splash); } // Query must be of the same type return false; } @Override public String toString() { return String.format("Potion|%s|%s|%s|%s", hasType() ? StringUtils.join(type, ", ") : "", hasLevel() ? StringUtils.join(level, ", ") : "", Utility.formatBoolean("extended", extended), Utility.formatBoolean("splash", splash)); } @Override public Types getQueryType() { return Types.POTIONS; } }