package tc.oc.pgm.blockdrops; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.logging.Logger; import com.google.common.collect.ImmutableSet; import org.bukkit.inventory.ItemStack; import org.bukkit.material.MaterialData; import org.jdom2.Document; import org.jdom2.Element; import tc.oc.commons.core.util.Pair; import tc.oc.pgm.filters.Filter; import tc.oc.pgm.filters.parser.FilterParser; import tc.oc.pgm.itemmeta.ItemModifyModule; import tc.oc.pgm.kits.ItemParser; import tc.oc.pgm.kits.Kit; import tc.oc.pgm.kits.KitParser; import tc.oc.pgm.map.MapModule; import tc.oc.pgm.map.MapModuleContext; import tc.oc.pgm.match.Match; import tc.oc.pgm.match.MatchModuleFactory; import tc.oc.pgm.module.ModuleDescription; import tc.oc.pgm.modules.InfoModule; import tc.oc.pgm.regions.EverywhereRegion; import tc.oc.pgm.regions.Region; import tc.oc.pgm.regions.RegionParser; import tc.oc.pgm.utils.XMLUtils; import tc.oc.pgm.xml.InvalidXMLException; import tc.oc.pgm.xml.Node; @ModuleDescription(name = "Custom Block Drops", requires = { InfoModule.class }) public class BlockDropsModule implements MapModule, MatchModuleFactory<BlockDropsMatchModule> { private final BlockDropsRuleSet ruleSet; public BlockDropsModule(BlockDropsRuleSet ruleSet) { this.ruleSet = ruleSet; } @Override public BlockDropsMatchModule createMatchModule(Match match) { return new BlockDropsMatchModule(match, this.ruleSet); } // --------------------- // ---- XML Parsing ---- // --------------------- @SuppressWarnings("deprecation") public static BlockDropsModule parse(MapModuleContext context, Logger logger, Document doc) throws InvalidXMLException { final List<BlockDropsRule> rules = new ArrayList<>(); final FilterParser filterParser = context.needModule(FilterParser.class); final RegionParser regionParser = context.needModule(RegionParser.class); final KitParser kitParser = context.needModule(KitParser.class); final ItemParser itemParser = context.needModule(ItemParser.class); final Optional<ItemModifyModule> itemModifier = context.module(ItemModifyModule.class); for(Element elRule : XMLUtils.flattenElements(doc.getRootElement(), ImmutableSet.of("block-drops", "blockdrops"), ImmutableSet.of("rule"))) { Filter filter = filterParser.parseOptionalProperty(elRule, "filter").orElse(null); Region region = regionParser.property(elRule).optionalUnion(EverywhereRegion.INSTANCE); Kit kit = kitParser.property(elRule, "kit").optional(null); boolean dropOnWrongTool = XMLUtils.parseBoolean(Node.fromChildOrAttr(elRule, "wrong-tool", "wrongtool"), false); boolean punchable = XMLUtils.parseBoolean(Node.fromChildOrAttr(elRule, "punch"), false); boolean trample = XMLUtils.parseBoolean(Node.fromChildOrAttr(elRule, "trample"), false); Float fallChance = XMLUtils.parseNumber(Node.fromChildOrAttr(elRule, "fall-chance"), Float.class, (Float) null); Float landChance = XMLUtils.parseNumber(Node.fromChildOrAttr(elRule, "land-chance"), Float.class, (Float) null); Double fallSpeed = XMLUtils.parseNumber(Node.fromChildOrAttr(elRule, "fall-speed"), Double.class, (Double) null); MaterialData replacement = null; if(elRule.getChild("replacement") != null) { replacement = XMLUtils.parseBlockMaterialData(Node.fromChildOrAttr(elRule, "replacement")); } int experience = XMLUtils.parseNumber(Node.fromChildOrAttr(elRule, "experience"), Integer.class, 0); List<Pair<Double, ItemStack>> items = new ArrayList<>(); for(Element elDrops : elRule.getChildren("drops")) { for(Element elItem : elDrops.getChildren("item")) { final ItemStack item = itemParser.parseItem(elItem, false); itemModifier.ifPresent(imm -> imm.applyRules(item)); items.add(Pair.create(XMLUtils.parseNumber(elItem.getAttribute("chance"), Double.class, 1d), item.immutableCopy())); } } rules.add(new BlockDropsRule(filter, region, dropOnWrongTool, punchable, trample, new BlockDrops(items, kit, experience, replacement, fallChance, landChance, fallSpeed))); } // BlockDropsModule must always be loaded, even if there are no rules defined, // otherwise modules that depend on it e.g. DestroyablesModule will be silently // skipped by the module loader. We need better module dependency logic. return new BlockDropsModule(new BlockDropsRuleSet(rules)); } }