Java tutorial
/* * 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 3 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, see <http://www.gnu.org/licenses/>. */ package lineage2.gameserver.data.xml.parser; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import lineage2.commons.data.xml.AbstractDirParser; import lineage2.commons.data.xml.AbstractHolder; import lineage2.gameserver.model.entity.residence.ResidenceType; import lineage2.gameserver.stats.StatTemplate; import lineage2.gameserver.stats.Stats; import lineage2.gameserver.stats.conditions.Condition; import lineage2.gameserver.stats.conditions.ConditionCastleDark; import lineage2.gameserver.stats.conditions.ConditionCastleDarkClanLeader; import lineage2.gameserver.stats.conditions.ConditionCastleLight; import lineage2.gameserver.stats.conditions.ConditionCastleLightClanLeader; import lineage2.gameserver.stats.conditions.ConditionLogicAnd; import lineage2.gameserver.stats.conditions.ConditionLogicNot; import lineage2.gameserver.stats.conditions.ConditionLogicOr; import lineage2.gameserver.stats.conditions.ConditionPlayerClassId; import lineage2.gameserver.stats.conditions.ConditionPlayerInstanceZone; import lineage2.gameserver.stats.conditions.ConditionPlayerMinMaxDamage; import lineage2.gameserver.stats.conditions.ConditionPlayerOlympiad; import lineage2.gameserver.stats.conditions.ConditionPlayerRace; import lineage2.gameserver.stats.conditions.ConditionPlayerResidence; import lineage2.gameserver.stats.conditions.ConditionSlotItemId; import lineage2.gameserver.stats.conditions.ConditionTargetPlayable; import lineage2.gameserver.stats.conditions.ConditionUsingItemType; import lineage2.gameserver.stats.conditions.ConditionUsingSkill; import lineage2.gameserver.stats.conditions.ConditionZoneType; import lineage2.gameserver.stats.funcs.FuncTemplate; import lineage2.gameserver.stats.triggers.TriggerInfo; import lineage2.gameserver.stats.triggers.TriggerType; import lineage2.gameserver.templates.item.ArmorTemplate; import lineage2.gameserver.templates.item.WeaponTemplate; import org.dom4j.Attribute; import org.dom4j.Element; /** * @author Mobius * @version $Revision: 1.0 $ * @param <H> */ abstract class StatParser<H extends AbstractHolder> extends AbstractDirParser<H> { /** * Constructor for StatParser. * @param holder H */ protected StatParser(H holder) { super(holder); } /** * Method parseFirstCond. * @param sub Element * @return Condition */ protected Condition parseFirstCond(Element sub) { List<Element> e = sub.elements(); if (e.isEmpty()) { return null; } Element element = e.get(0); return parseCond(element); } /** * Method parseCond. * @param element Element * @return Condition */ private Condition parseCond(Element element) { String name = element.getName(); if (name.equalsIgnoreCase("and")) { return parseLogicAnd(element); } else if (name.equalsIgnoreCase("or")) { return parseLogicOr(element); } else if (name.equalsIgnoreCase("not")) { return parseLogicNot(element); } else if (name.equalsIgnoreCase("target")) { return parseTargetCondition(element); } else if (name.equalsIgnoreCase("player")) { return parsePlayerCondition(element); } else if (name.equalsIgnoreCase("using")) { return parseUsingCondition(element); } else if (name.equalsIgnoreCase("zone")) { return parseZoneCondition(element); } return null; } /** * Method parseLogicAnd. * @param n Element * @return Condition */ private Condition parseLogicAnd(Element n) { ConditionLogicAnd cond = new ConditionLogicAnd(); for (Iterator<Element> iterator = n.elementIterator(); iterator.hasNext();) { Element condElement = iterator.next(); cond.add(parseCond(condElement)); } if ((cond._conditions == null) || (cond._conditions.length == 0)) { error("Empty <and> condition in " + getCurrentFileName()); } return cond; } /** * Method parseLogicOr. * @param n Element * @return Condition */ private Condition parseLogicOr(Element n) { ConditionLogicOr cond = new ConditionLogicOr(); for (Iterator<Element> iterator = n.elementIterator(); iterator.hasNext();) { Element condElement = iterator.next(); cond.add(parseCond(condElement)); } if ((cond._conditions == null) || (cond._conditions.length == 0)) { error("Empty <or> condition in " + getCurrentFileName()); } return cond; } /** * Method parseLogicNot. * @param n Element * @return Condition */ private Condition parseLogicNot(Element n) { for (Object element : n.elements()) { return new ConditionLogicNot(parseCond((Element) element)); } error("Empty <not> condition in " + getCurrentFileName()); return null; } /** * Method parseTargetCondition. * @param element Element * @return Condition */ private Condition parseTargetCondition(Element element) { Condition cond = null; for (Iterator<Attribute> iterator = element.attributeIterator(); iterator.hasNext();) { Attribute attribute = iterator.next(); String name = attribute.getName(); String value = attribute.getValue(); if (name.equalsIgnoreCase("pvp")) { cond = joinAnd(cond, new ConditionTargetPlayable(Boolean.valueOf(value))); } } return cond; } /** * Method parseZoneCondition. * @param element Element * @return Condition */ private Condition parseZoneCondition(Element element) { Condition cond = null; for (Iterator<Attribute> iterator = element.attributeIterator(); iterator.hasNext();) { Attribute attribute = iterator.next(); String name = attribute.getName(); String value = attribute.getValue(); if (name.equalsIgnoreCase("type")) { cond = joinAnd(cond, new ConditionZoneType(value)); } } return cond; } /** * Method parsePlayerCondition. * @param element Element * @return Condition */ private Condition parsePlayerCondition(Element element) { Condition cond = null; for (Iterator<Attribute> iterator = element.attributeIterator(); iterator.hasNext();) { Attribute attribute = iterator.next(); String name = attribute.getName(); String value = attribute.getValue(); if (name.equalsIgnoreCase("residence")) { String[] st = value.split(";"); cond = joinAnd(cond, new ConditionPlayerResidence(Integer.parseInt(st[1]), ResidenceType.valueOf(st[0]))); } else if (name.equalsIgnoreCase("classId")) { cond = joinAnd(cond, new ConditionPlayerClassId(value.split(","))); } else if (name.equalsIgnoreCase("olympiad")) { cond = joinAnd(cond, new ConditionPlayerOlympiad(Boolean.valueOf(value))); } else if (name.equalsIgnoreCase("instance_zone")) { cond = joinAnd(cond, new ConditionPlayerInstanceZone(Integer.parseInt(value))); } else if (name.equalsIgnoreCase("race")) { cond = joinAnd(cond, new ConditionPlayerRace(value)); } else if (name.equalsIgnoreCase("damage")) { String[] st = value.split(";"); cond = joinAnd(cond, new ConditionPlayerMinMaxDamage(Double.parseDouble(st[0]), Double.parseDouble(st[1]))); } else if (name.equalsIgnoreCase("castleLight")) { cond = joinAnd(cond, new ConditionCastleLight()); } else if (name.equalsIgnoreCase("castleLightClanLeader")) { cond = joinAnd(cond, new ConditionCastleLightClanLeader()); } else if (name.equalsIgnoreCase("castleDark")) { cond = joinAnd(cond, new ConditionCastleDark()); } else if (name.equalsIgnoreCase("castleDarkClanLeader")) { cond = joinAnd(cond, new ConditionCastleDarkClanLeader()); } } return cond; } /** * Method parseUsingCondition. * @param element Element * @return Condition */ private Condition parseUsingCondition(Element element) { Condition cond = null; for (Iterator<Attribute> iterator = element.attributeIterator(); iterator.hasNext();) { Attribute attribute = iterator.next(); String name = attribute.getName(); String value = attribute.getValue(); if (name.equalsIgnoreCase("slotitem")) { StringTokenizer st = new StringTokenizer(value, ";"); int id = Integer.parseInt(st.nextToken().trim()); int slot = Integer.parseInt(st.nextToken().trim()); int enchant = 0; if (st.hasMoreTokens()) { enchant = Integer.parseInt(st.nextToken().trim()); } cond = joinAnd(cond, new ConditionSlotItemId(slot, id, enchant)); } else if (name.equalsIgnoreCase("kind") || name.equalsIgnoreCase("weapon")) { long mask = 0; StringTokenizer st = new StringTokenizer(value, ","); tokens: while (st.hasMoreTokens()) { String item = st.nextToken().trim(); for (WeaponTemplate.WeaponType wt : WeaponTemplate.WeaponType.VALUES) { if (wt.toString().equalsIgnoreCase(item)) { mask |= wt.mask(); continue tokens; } } for (ArmorTemplate.ArmorType at : ArmorTemplate.ArmorType.VALUES) { if (at.toString().equalsIgnoreCase(item)) { mask |= at.mask(); continue tokens; } } error("Invalid item kind: \"" + item + "\" in " + getCurrentFileName()); } if (mask != 0) { cond = joinAnd(cond, new ConditionUsingItemType(mask)); } } else if (name.equalsIgnoreCase("skill")) { cond = joinAnd(cond, new ConditionUsingSkill(Integer.parseInt(value))); } } return cond; } /** * Method joinAnd. * @param cond Condition * @param c Condition * @return Condition */ private Condition joinAnd(Condition cond, Condition c) { if (cond == null) { return c; } if (cond instanceof ConditionLogicAnd) { ((ConditionLogicAnd) cond).add(c); return cond; } ConditionLogicAnd and = new ConditionLogicAnd(); and.add(cond); and.add(c); return and; } /** * Method parseFor. * @param forElement Element * @param template StatTemplate */ protected void parseFor(Element forElement, StatTemplate template) { for (Iterator<Element> iterator = forElement.elementIterator(); iterator.hasNext();) { Element element = iterator.next(); final String elementName = element.getName(); if (elementName.equalsIgnoreCase("add")) { attachFunc(element, template, "Add"); } else if (elementName.equalsIgnoreCase("set")) { attachFunc(element, template, "Set"); } else if (elementName.equalsIgnoreCase("sub")) { attachFunc(element, template, "Sub"); } else if (elementName.equalsIgnoreCase("mul")) { attachFunc(element, template, "Mul"); } else if (elementName.equalsIgnoreCase("div")) { attachFunc(element, template, "Div"); } else if (elementName.equalsIgnoreCase("enchant")) { attachFunc(element, template, "Enchant"); } } } /** * Method parseTriggers. * @param f Element * @param triggerable StatTemplate */ protected void parseTriggers(Element f, StatTemplate triggerable) { for (Iterator<Element> iterator = f.elementIterator(); iterator.hasNext();) { Element element = iterator.next(); int id = parseNumber(element.attributeValue("id")).intValue(); int level = parseNumber(element.attributeValue("level")).intValue(); TriggerType t = TriggerType.valueOf(element.attributeValue("type")); double chance = parseNumber(element.attributeValue("chance")).doubleValue(); TriggerInfo trigger = new TriggerInfo(id, level, t, chance); triggerable.addTrigger(trigger); for (Iterator<Element> subIterator = element.elementIterator(); subIterator.hasNext();) { Element subElement = subIterator.next(); Condition condition = parseFirstCond(subElement); if (condition != null) { trigger.addCondition(condition); } } } } /** * Method attachFunc. * @param n Element * @param template StatTemplate * @param name String */ private void attachFunc(Element n, StatTemplate template, String name) { Stats stat = Stats.valueOfXml(n.attributeValue("stat")); String order = n.attributeValue("order"); int ord = parseNumber(order).intValue(); Condition applyCond = parseFirstCond(n); double val = 0; if (n.attributeValue("value") != null) { val = parseNumber(n.attributeValue("value")).doubleValue(); } template.attachFunc(new FuncTemplate(applyCond, name, stat, ord, val)); } /** * Method parseNumber. * @param value String * @return Number */ protected Number parseNumber(String value) { if (value.charAt(0) == '#') { value = getTableValue(value).toString(); } try { if (value.indexOf('.') == -1) { int radix = 10; if ((value.length() > 2) && value.substring(0, 2).equalsIgnoreCase("0x")) { value = value.substring(2); radix = 16; } return Integer.valueOf(value, radix); } return Double.valueOf(value); } catch (NumberFormatException e) { return null; } } /** * Method getTableValue. * @param name String * @return Object */ protected abstract Object getTableValue(String name); }