package tc.oc.pgm.structure;
import java.util.Optional;
import javax.inject.Inject;
import org.bukkit.util.ImVector;
import org.bukkit.util.Vector;
import org.jdom2.Document;
import org.jdom2.Element;
import tc.oc.api.docs.SemanticVersion;
import tc.oc.pgm.features.FeatureDefinitionContext;
import tc.oc.pgm.filters.Filter;
import tc.oc.pgm.filters.matcher.StaticFilter;
import tc.oc.pgm.filters.parser.FilterParser;
import tc.oc.pgm.filters.query.IMatchQuery;
import tc.oc.pgm.map.MapProto;
import tc.oc.pgm.map.MapRootParser;
import tc.oc.pgm.map.ProtoVersions;
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;
public class StructureParser implements MapRootParser {
@Inject FeatureDefinitionContext features;
@Inject @MapProto SemanticVersion proto;
@Inject Document doc;
@Inject FilterParser filterParser;
@Inject RegionParser regionParser;
@Inject DynamicDefinitionImpl.Factory dynamicDefinitionFactory;
@Override
public void parse() throws InvalidXMLException {
if(proto.isOlderThan(ProtoVersions.FILTER_FEATURES)) return;
for(Element elStruct : XMLUtils.flattenElements(doc.getRootElement(), "structures", "structure")) {
features.define(
elStruct,
new StructureDefinitionImpl(
XMLUtils.parseVector(elStruct.getAttribute("origin"), (Vector) null),
regionParser.property(elStruct, "region").validate(CuboidValidation.INSTANCE).required(),
XMLUtils.parseBoolean(elStruct.getAttribute("air"), false),
XMLUtils.parseBoolean(elStruct.getAttribute("clear"), true)
)
);
}
for(Element elDynamic : XMLUtils.flattenElements(doc.getRootElement(), "structures", "dynamic")) {
final Optional<ImVector>
position = XMLUtils.parseVector(elDynamic, "location").optional(),
offset = XMLUtils.parseVector(elDynamic, "offset").optional();
if(position.isPresent() && offset.isPresent()) {
throw new InvalidXMLException("attributes 'location' and 'offset' cannot be used together", elDynamic);
}
final StructureDefinition structure = features.reference(Node.fromRequiredAttr(elDynamic, "structure"), StructureDefinition.class);
final Filter trigger, filter;
if(proto.isOlderThan(ProtoVersions.DYNAMIC_FILTERS)) {
// Legacy maps use "filter" as the trigger
trigger = filterParser.property(elDynamic, "filter")
.respondsTo(IMatchQuery.class)
.dynamic()
.optional(StaticFilter.ALLOW);
filter = StaticFilter.ALLOW;
} else {
// New maps have seperate "trigger" and "filter" properties
trigger = filterParser.property(elDynamic, "trigger")
.respondsTo(IMatchQuery.class)
.dynamic()
.optional(StaticFilter.ALLOW);
filter = filterParser.property(elDynamic, "filter")
.optional(StaticFilter.ALLOW);
}
features.define(elDynamic, dynamicDefinitionFactory.create(structure, trigger, filter, position, offset));
}
}
}