/* * 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.parser.text; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.bukkit.DyeColor; import org.bukkit.GrassSpecies; import org.bukkit.Material; import org.bukkit.SandstoneType; import org.bukkit.TreeSpecies; import org.bukkit.material.MonsterEggs; import org.bukkit.material.Step; import com.comphenix.xp.extra.SmoothBrickType; import com.comphenix.xp.parser.TextParser; import com.comphenix.xp.parser.ParsingException; import com.comphenix.xp.parser.Utility; public class ItemDurabilityParser extends TextParser<Integer> { // Quick lookup of items private static Map<Integer, ItemCategory> lookup = new HashMap<Integer, ItemCategory>(); // Every item type public enum ItemCategory { TREE_BLOCKS(Material.WOOD.getId(), Material.LEAVES.getId(), WOODEN_STEPS, WOODEN_DOUBLE_STEPS), DYED_BLOCKS(Material.WOOL.getId(), Material.INK_SACK.getId()), GRASS_BLOCKS(Material.GRASS.getId()), STEP_BLOCKS(Material.STEP.getId(), Material.DOUBLE_STEP.getId()), SANDSTONE_BLOCKS(Material.SANDSTONE.getId()), SMOOTH_BRICK_BLOCKS(Material.SMOOTH_BRICK.getId(), Material.SMOOTH_STAIRS.getId()), MONSTER_EGGS_BLOCKS(Material.MONSTER_EGGS.getId()), COAL_ITEMS(Material.COAL.getId()); private ItemCategory(Integer... items) { for (Integer item : items) lookup.put(item, this); } public static ItemCategory matchItem(Integer itemID) { return lookup.get(itemID); } } // New blocks private static final int WOODEN_STEPS = 125; private static final int WOODEN_DOUBLE_STEPS = 126; private static final int COAL_NORMAL = 0; private static final int COAL_CHARCOAL = 1; private Integer itemID; private boolean usedName; public ItemDurabilityParser() { this.itemID = null; } public ItemDurabilityParser(Integer itemID) { this.itemID = itemID; } public Integer getItemID() { return itemID; } public void setItemID(Integer itemID) { this.itemID = itemID; } public boolean isUsedName() { return usedName; } public void setUsedName(boolean usedName) { this.usedName = usedName; } @Override public Integer parse(String text) throws ParsingException { if (Utility.isNullOrIgnoreable(text)) throw new ParsingException("Text cannot be empty or null."); String filtered = Utility.getEnumName(text); Integer durability = tryParse(text); if (durability == null) { if (isItem(itemID, Material.POTION)) { // Let the caller figure this out. The token are to be processed further, // so we'll keep it in. throw new ParsingException("This is a potion."); } // ToDo: Make it possible to use named durabilities without the correct item ID if (itemID == null) { throw ParsingException.fromFormat( "Cannot parse %s - named durabilities only works with known item ids.", text); } ItemCategory category = ItemCategory.matchItem(itemID); // Cannot parse durability if (category == null) { throw ParsingException.fromFormat("Invalid durability value %s.", text); } // Quickly find the correct durability list to use switch (category) { case TREE_BLOCKS: durability = getTreeSpecies(text, filtered); break; case DYED_BLOCKS: // Convert color values durability = getDyeColor(text, filtered); break; case GRASS_BLOCKS: // Grass types durability = getGrassSpecies(text, filtered); break; case STEP_BLOCKS: durability = getStepMaterial(text); break; case SANDSTONE_BLOCKS: durability = getSandstoneType(text, filtered); break; case SMOOTH_BRICK_BLOCKS: durability = getSmoothstoneType(text, filtered); break; case MONSTER_EGGS_BLOCKS: durability = getMonsterEgg(text); break; case COAL_ITEMS: durability = getCoalData(text, filtered); break; } // We used a name! setUsedName(true); } return durability; } public static boolean inSameCategory(List<Integer> listItemID) { Integer first = !listItemID.isEmpty() ? listItemID.get(0) : null; ItemCategory category = ItemCategory.matchItem(first); // Make sure every item is in the same category for (Integer item : listItemID) { if (ItemCategory.matchItem(item) != category) return false; } return true; } private int getCoalData(String text, String filtered) throws ParsingException { // No corresponding constants in Bukkit if (filtered.equals("NORMAL") || filtered.equals("COAL_NORMAL")) return COAL_NORMAL; else if (filtered.equals("CHARCOAL") || filtered.equals("CHAR_COAL")) return COAL_CHARCOAL; else throw ParsingException.fromFormat("Unable to find coal type %s", text); } private int getTreeSpecies(String text, String filtered) throws ParsingException { try { // Hard coded names if (filtered.equals("OAK")) return 0; else return (int) TreeSpecies.valueOf(filtered).getData(); } catch (IllegalArgumentException e) { throw ParsingException.fromFormat("Unable to find tree species %s.", text); } } private int getStepMaterial(String text) throws ParsingException { Material material = getMaterial(text); Step step = new Step(); // Get texture durability value if (step.getTextures().contains(material)) { return (int) new Step(material).getData(); } else { throw ParsingException.fromFormat("Unable to parse texture material %s.", text); } } private int getSandstoneType(String text, String filtered) throws ParsingException { // Extra types if (filtered.equals("NORMAL")) return 0; if (filtered.equals("CHISELED")) return 1; // Note: Like many enums, this doesn't correspond to MinecraftWiki try { return (int) SandstoneType.valueOf(filtered).getData(); } catch (IllegalArgumentException e) { throw ParsingException.fromFormat("Unable to find sandstone type %s.", text); } } private int getMonsterEgg(String text) throws ParsingException { Material material = getMaterial(text); MonsterEggs monsterEgg = new MonsterEggs(); // Get texture durability value if (monsterEgg.getTextures().contains(material)) { return (int) new MonsterEggs(material).getData(); } else { throw ParsingException.fromFormat("Unable to parse texture material %s", text); } } private int getSmoothstoneType(String text, String filtered) throws ParsingException { // Alternatives if (filtered.equals("CHISELED")) return 3; try { return (int) SmoothBrickType.valueOf(filtered).getData(); } catch (IllegalArgumentException e) { throw ParsingException.fromFormat("Unable to find smoothstone type %s.", text); } } private int getDyeColor(String text, String filtered) throws ParsingException { try { // Look up value directly return (int) DyeColor.valueOf(filtered).getData(); } catch (IllegalArgumentException e) { throw ParsingException.fromFormat("Unable to find dye color %s.", text); } } private int getGrassSpecies(String text, String filtered) throws ParsingException { try { return (int) GrassSpecies.valueOf(filtered).getData(); } catch (IllegalArgumentException e) { throw ParsingException.fromFormat("Unable to grass species %s.", text); } } private boolean isItem(Integer itemID, Material material) { // Check for equality if (itemID == null) return false; else return itemID == material.getId(); } private Material getMaterial(String text) throws ParsingException { try { ItemNameParser parser = new ItemNameParser(); Set<Integer> attempt = parser.parse(text); // Get the first Bukkit material for (Integer id : attempt) { Material mat = Material.getMaterial(id); if (mat != null) return mat; } // Or just NULL return null; } catch (ParsingException e) { return null; } catch (IllegalArgumentException e) { return null; } } }