package tc.oc.pgm.renewable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import java.time.Duration;
import tc.oc.pgm.filters.Filter;
import tc.oc.pgm.filters.matcher.StaticFilter;
import tc.oc.pgm.filters.matcher.block.MaterialFilter;
import tc.oc.pgm.filters.operator.AllFilter;
import tc.oc.pgm.filters.operator.AnyFilter;
import tc.oc.pgm.filters.parser.FilterParser;
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.regions.EverywhereRegion;
import tc.oc.pgm.regions.RegionParser;
import tc.oc.pgm.utils.XMLUtils;
import tc.oc.pgm.xml.InvalidXMLException;
@ModuleDescription(name = "Renewable Resources")
public class RenewableModule implements MapModule, MatchModuleFactory<RenewableMatchModule> {
private static final double DEFAULT_AVOID_PLAYERS_RANGE = 2d;
private final List<RenewableDefinition> renewableDefinitions = new ArrayList<>();
@Override
public RenewableMatchModule createMatchModule(Match match) {
return new RenewableMatchModule(match, this.renewableDefinitions);
}
private static Filter parseFilter(FilterParser parser, Element el, String name, Filter def) throws InvalidXMLException {
Filter property = parser.parseOptionalProperty(el, name + "-filter").orElse(null);
List<Filter> inline = new ArrayList<>();
for(Element child : el.getChildren(name)) {
inline.add(new MaterialFilter(XMLUtils.parseMaterialPattern(child)));
}
if(property == null) {
if(inline.isEmpty()) {
return def;
} else {
return new AnyFilter(inline);
}
} else {
if(inline.isEmpty()) {
return property;
} else {
return AllFilter.of(property, new AnyFilter(inline));
}
}
}
public static RenewableModule parse(MapModuleContext context, Logger logger, Document doc) throws InvalidXMLException {
RenewableModule renewableModule = new RenewableModule();
RegionParser regionParser = context.needModule(RegionParser.class);
FilterParser filterParser = context.needModule(FilterParser.class);
for(Element elRenewable : XMLUtils.flattenElements(doc.getRootElement(), "renewables", "renewable")) {
RenewableDefinition renewableDefinition = new RenewableDefinition();
renewableDefinition.region = regionParser.property(elRenewable, "region").optionalUnion(EverywhereRegion.INSTANCE);
renewableDefinition.renewableBlocks = parseFilter(filterParser, elRenewable, "renew", StaticFilter.ALLOW);
renewableDefinition.replaceableBlocks = parseFilter(filterParser, elRenewable, "replace", StaticFilter.ALLOW);
renewableDefinition.shuffleableBlocks = parseFilter(filterParser, elRenewable, "shuffle", StaticFilter.DENY);
Attribute attrRate = elRenewable.getAttribute("rate");
Attribute attrInterval = elRenewable.getAttribute("interval");
if(attrRate != null) {
if(attrInterval != null) {
throw new InvalidXMLException("Attributes 'rate' and 'interval' cannot be combined", elRenewable);
} else {
renewableDefinition.renewalsPerSecond = XMLUtils.parseNumber(attrRate, Float.class);
}
} else {
if(attrInterval != null) {
Duration interval = XMLUtils.parseDuration(attrInterval);
renewableDefinition.renewalsPerSecond = 1000f / interval.toMillis();
renewableDefinition.rateScaled = true;
} else {
renewableDefinition.renewalsPerSecond = 1f;
}
}
renewableDefinition.growAdjacent = XMLUtils.parseBoolean(
elRenewable.getAttribute("grow"), true);
renewableDefinition.particles = XMLUtils.parseBoolean(
elRenewable.getAttribute("particles"), true);
renewableDefinition.sound = XMLUtils.parseBoolean(
elRenewable.getAttribute("sound"), true);
if(!XMLUtils.parseBoolean(elRenewable.getAttribute("avoid-entities"), true)) {
// Legacy compatibility
renewableDefinition.avoidPlayersRange = 0;
} else {
renewableDefinition.avoidPlayersRange = XMLUtils.parseNumber(elRenewable.getAttribute("avoid-players"), Double.class, DEFAULT_AVOID_PLAYERS_RANGE);
}
renewableModule.renewableDefinitions.add(renewableDefinition);
}
return renewableModule;
}
}