package tc.oc.pgm.animation; import com.google.common.collect.Range; import org.bukkit.util.ImVector; import org.bukkit.util.Vector; import org.jdom2.Document; import org.jdom2.Element; import tc.oc.pgm.features.FeatureDefinitionContext; import tc.oc.pgm.map.MapRootParser; import tc.oc.pgm.regions.CuboidValidation; import tc.oc.pgm.regions.RegionParser; import tc.oc.pgm.utils.XMLUtils; import tc.oc.pgm.xml.InvalidXMLException; import tc.oc.pgm.xml.Node; import tc.oc.pgm.xml.property.DurationProperty; import tc.oc.pgm.xml.property.NumberProperty; import tc.oc.pgm.xml.property.PropertyBuilderFactory; import javax.inject.Inject; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Optional; public class AnimationParser implements MapRootParser { @Inject FeatureDefinitionContext features; @Inject Document doc; @Inject AnimationDefinitionImpl.Factory animationDefinitionFactory; @Inject RegionParser regionParser; @Inject PropertyBuilderFactory durations; @Inject PropertyBuilderFactory> integers; @Override public void parse() throws InvalidXMLException { for(Element elFrame : XMLUtils.flattenElements(doc.getRootElement(), "animations", "frame")) { features.define( elFrame, new FrameDefinitionImpl( XMLUtils.parseVector(elFrame.getAttribute("origin"), (Vector) null), regionParser.property(elFrame, "region").validate(CuboidValidation.INSTANCE).required(), XMLUtils.parseBoolean(elFrame.getAttribute("air"), false), XMLUtils.parseBoolean(elFrame.getAttribute("clear"), true) ) ); } for(Element elAnimation : XMLUtils.flattenElements(doc.getRootElement(), "animations", "animation")) { List frames = new ArrayList<>(); for (Node elFrames : Node.fromChildren(elAnimation, "frames")) { for (Node elFrame : Node.fromChildren(elFrames.asElement(), "frame")) { frames.add(features.reference(Node.fromRequiredAttr(elFrame.asElement(), "id"), FrameDefinition.class)); } } Duration after = durations.property(elAnimation, "after").required(); Duration loop = durations.property(elAnimation, "loop").required(); int count = integers.property(elAnimation, "count") .range(Range.atLeast(1)) .infinity(true) .optional(Integer.MAX_VALUE); final Optional position = XMLUtils.parseVector(elAnimation, "location").optional(), offset = XMLUtils.parseVector(elAnimation, "offset").optional(); if(position.isPresent() && offset.isPresent()) { throw new InvalidXMLException("attributes 'location' and 'offset' cannot be used together", elAnimation); } features.define(elAnimation, animationDefinitionFactory.create(frames, after, loop, count, position)); } } }