264 lines
11 KiB
Java
264 lines
11 KiB
Java
package tc.oc.pgm.kits;
|
|
|
|
import java.util.Optional;
|
|
import java.util.Set;
|
|
import java.util.stream.Stream;
|
|
import javax.inject.Inject;
|
|
|
|
import com.google.common.collect.Range;
|
|
import org.bukkit.inventory.ItemStack;
|
|
import org.jdom2.Element;
|
|
import tc.oc.commons.bukkit.inventory.ArmorType;
|
|
import tc.oc.commons.bukkit.inventory.Slot;
|
|
import tc.oc.pgm.blitz.LivesKit;
|
|
import tc.oc.pgm.compose.CompositionParser;
|
|
import tc.oc.pgm.doublejump.DoubleJumpKit;
|
|
import tc.oc.pgm.features.FeatureDefinitionContext;
|
|
import tc.oc.pgm.features.FeatureDefinitionParser;
|
|
import tc.oc.pgm.features.FeatureParser;
|
|
import tc.oc.pgm.features.MagicMethodFeatureParser;
|
|
import tc.oc.pgm.filters.matcher.StaticFilter;
|
|
import tc.oc.pgm.filters.parser.FilterParser;
|
|
import tc.oc.pgm.itemmeta.ItemModifier;
|
|
import tc.oc.pgm.map.MapLogger;
|
|
import tc.oc.pgm.physics.RelativeFlags;
|
|
import tc.oc.pgm.shield.ShieldKit;
|
|
import tc.oc.pgm.shield.ShieldParameters;
|
|
import tc.oc.pgm.teams.TeamFactory;
|
|
import tc.oc.pgm.utils.AllMaterialMatcher;
|
|
import tc.oc.pgm.utils.MethodParser;
|
|
import tc.oc.pgm.utils.XMLUtils;
|
|
import tc.oc.pgm.xml.InvalidXMLException;
|
|
import tc.oc.pgm.xml.Node;
|
|
import tc.oc.pgm.xml.NodeSplitter;
|
|
import tc.oc.pgm.xml.property.PropertyBuilderFactory;
|
|
|
|
import static tc.oc.commons.core.exception.LambdaExceptionUtils.rethrowFunction;
|
|
import static tc.oc.commons.core.stream.Collectors.toImmutableSet;
|
|
|
|
public class KitDefinitionParser extends MagicMethodFeatureParser<Kit> implements FeatureDefinitionParser<Kit> {
|
|
|
|
@Inject protected FeatureDefinitionContext features;
|
|
@Inject protected ItemParser itemParser;
|
|
@Inject protected FilterParser filterParser;
|
|
@Inject protected FeatureParser<TeamFactory> teamParser;
|
|
@Inject protected CompositionParser<Kit> composer;
|
|
@Inject protected KitParser kitParser;
|
|
@Inject protected PropertyBuilderFactory<Boolean, ?> booleanParser;
|
|
@Inject protected MapLogger mapLogger;
|
|
@Inject protected ItemModifier itemModifier;
|
|
|
|
private Stream<Kit> parseParentKits(Element el) throws InvalidXMLException {
|
|
return Node.attributes(el, "parent", "parents")
|
|
.flatMap(attr -> NodeSplitter.LIST.split(attr)
|
|
.map(rethrowFunction(id -> kitParser.parseReference(attr, id.trim()))));
|
|
}
|
|
|
|
// TODO: this check can be removed after a little while
|
|
private static final Set<String> LEGACY_ACTION_ATTRS = Stream.of(KitRule.Action.values())
|
|
.map(action -> action.name().toLowerCase())
|
|
.collect(toImmutableSet());
|
|
@MethodParser
|
|
Kit kit(Element el) throws InvalidXMLException {
|
|
Node.nodes(el, LEGACY_ACTION_ATTRS).forEach(attr ->
|
|
mapLogger.warning(attr, "Kit give/take/lend attributes are no longer supported")
|
|
);
|
|
|
|
return new KitNodeImpl(
|
|
parseParentKits(el),
|
|
composer.parseElement(el),
|
|
filterParser.property(el, "filter").optional(StaticFilter.ALLOW),
|
|
booleanParser.property(el, "force").elements(false).optional(), // attrs only, since <force> is a type of kit
|
|
booleanParser.property(el, "potion-particles").optional()
|
|
);
|
|
}
|
|
|
|
protected Kit makeItemKit(Optional<Slot.Player> slot, ItemStack item) throws InvalidXMLException {
|
|
final ItemStack modded = itemModifier.modify(item).immutableCopy();
|
|
return slot.map(s -> (Kit) new SlotItemKit(modded, s))
|
|
.orElseGet(() -> new FreeItemKit(modded));
|
|
}
|
|
|
|
public Kit parseArmorKit(Element el, ArmorType type) throws InvalidXMLException {
|
|
return makeItemKit(Optional.of(Slot.Armor.forType(type)), itemParser.parseItem(el, true));
|
|
}
|
|
|
|
public Optional<Slot.Player> parseSlot(Element el) throws InvalidXMLException {
|
|
return Optional.ofNullable(Node.fromAttr(el, "slot"))
|
|
.map(rethrowFunction(XMLUtils::parsePlayerSlot));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit item(Element el) throws InvalidXMLException {
|
|
return makeItemKit(parseSlot(el), itemParser.parseItem(el, true));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit book(Element el) throws InvalidXMLException {
|
|
return makeItemKit(parseSlot(el), itemParser.parseBook(el));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit head(Element el) throws InvalidXMLException {
|
|
return makeItemKit(parseSlot(el), itemParser.parseHead(el));
|
|
}
|
|
|
|
@MethodParser public Kit boots(Element el) throws InvalidXMLException { return parseArmorKit(el, ArmorType.BOOTS); }
|
|
@MethodParser public Kit leggings(Element el) throws InvalidXMLException { return parseArmorKit(el, ArmorType.LEGGINGS); }
|
|
@MethodParser public Kit chestplate(Element el) throws InvalidXMLException { return parseArmorKit(el, ArmorType.CHESTPLATE); }
|
|
@MethodParser public Kit helmet(Element el) throws InvalidXMLException { return parseArmorKit(el, ArmorType.HELMET); }
|
|
|
|
@MethodParser
|
|
public Kit clear(Element el) throws InvalidXMLException {
|
|
return new ClearKit(
|
|
parseSlot(el),
|
|
XMLUtils.parseMaterialMatcher(el, AllMaterialMatcher.INSTANCE)
|
|
);
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit clear_items(Element el) throws InvalidXMLException {
|
|
return new ClearItemsKit();
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit knockback_reduction(Element el) throws InvalidXMLException {
|
|
return new KnockbackReductionKit(XMLUtils.parseNumber(el, Float.class));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit walk_speed(Element el) throws InvalidXMLException {
|
|
return new WalkSpeedKit(XMLUtils.parseNumber(el, Float.class, Range.closed(WalkSpeedKit.MIN, WalkSpeedKit.MAX)));
|
|
}
|
|
|
|
/*
|
|
~ <fly/> {FlyKit: allowFlight = true, flying = null }
|
|
~ <fly flying="false"/> {FlyKit: allowFlight = true, flying = false }
|
|
~ <fly allowFlight="false"/> {FlyKit: allowFlight = false, flying = null }
|
|
~ <fly flying="true"/> {FlyKit: allowFlight = true, flying = true }
|
|
*/
|
|
@MethodParser
|
|
public Kit fly(Element el) throws InvalidXMLException {
|
|
final boolean canFly = XMLUtils.parseBoolean(el.getAttribute("can-fly"), true);
|
|
final Boolean flying = XMLUtils.parseBoolean(el.getAttribute("flying"), null);
|
|
org.jdom2.Attribute flySpeedAtt = el.getAttribute("fly-speed");
|
|
float flySpeedMultiplier = 1;
|
|
if(flySpeedAtt != null) {
|
|
flySpeedMultiplier = XMLUtils.parseNumber(el.getAttribute("fly-speed"), Float.class, Range.closed(FlyKit.MIN, FlyKit.MAX));
|
|
}
|
|
|
|
return new FlyKit(canFly, flying, flySpeedMultiplier);
|
|
}
|
|
|
|
@MethodParser({"effect", "potion"})
|
|
public Kit effect(Element el) throws InvalidXMLException {
|
|
return new PotionKit(itemParser.parsePotionEffect(el));
|
|
}
|
|
|
|
|
|
@MethodParser
|
|
public Kit attribute(Element el) throws InvalidXMLException {
|
|
return new AttributeKit(XMLUtils.parseAttributeModifier(el));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit health(Element el) throws InvalidXMLException {
|
|
int health = XMLUtils.parseNumber(el, Integer.class);
|
|
if(health < 1 || health > 20) {
|
|
throw new InvalidXMLException(health + " is not a valid health value, must be between 1 and 20", el);
|
|
}
|
|
return new HealthKit(health);
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit max_health(Element el) throws InvalidXMLException {
|
|
return new MaxHealthKit(XMLUtils.parseNumber(el, Double.class, Range.atLeast(1d)));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit saturation(Element el) throws InvalidXMLException {
|
|
return new HungerKit(XMLUtils.parseNumber(el, Float.class, Range.atLeast(0f)), null);
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit foodlevel(Element el) throws InvalidXMLException {
|
|
return new HungerKit(null, XMLUtils.parseNumber(el, Integer.class, Range.atLeast(0)));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit double_jump(Element el) throws InvalidXMLException {
|
|
return new DoubleJumpKit(XMLUtils.parseBoolean(el.getAttribute("enabled"), true),
|
|
XMLUtils.parseNumber(el.getAttribute("power"), Float.class, DoubleJumpKit.DEFAULT_POWER),
|
|
XMLUtils.parseDuration(el.getAttribute("recharge-time"), DoubleJumpKit.DEFAULT_RECHARGE),
|
|
XMLUtils.parseBoolean(el.getAttribute("recharge-before-landing"), false));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit reser_ender_pearls(Element el) throws InvalidXMLException {
|
|
return new ResetEnderPearlsKit();
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit game_mode(Element el) throws InvalidXMLException {
|
|
return new GameModeKit(XMLUtils.parseGameMode(new Node(el)));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit shield(Element el) throws InvalidXMLException {
|
|
return new ShieldKit(new ShieldParameters(XMLUtils.parseNumber(el.getAttribute("health"), Double.class, ShieldParameters.DEFAULT_HEALTH),
|
|
XMLUtils.parseDuration(el.getAttribute("delay"), ShieldParameters.DEFAULT_DELAY)));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit fast_regeneration(Element el) throws InvalidXMLException {
|
|
return new NaturalRegenerationKit(true, XMLUtils.parseBoolean(new Node(el)));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit slow_regeneration(Element el) throws InvalidXMLException {
|
|
return new NaturalRegenerationKit(false, XMLUtils.parseBoolean(new Node(el)));
|
|
}
|
|
|
|
@MethodParser
|
|
public Kit hitbox(Element el) throws InvalidXMLException {
|
|
return new HitboxKit(XMLUtils.parseNumber(Node.fromRequiredAttr(el, "width"), Double.class));
|
|
}
|
|
|
|
@MethodParser
|
|
private Kit remove(Element el) throws InvalidXMLException {
|
|
return features.validate(new RemoveKit(kitParser.parseReferenceElement(el)), new Node(el), RemovableValidation.get());
|
|
}
|
|
|
|
@MethodParser
|
|
private Kit team_switch(Element el) throws InvalidXMLException {
|
|
return new TeamSwitchKit(teamParser.property(el, "team").required());
|
|
}
|
|
|
|
@MethodParser
|
|
private Kit eliminate(Element el) throws InvalidXMLException {
|
|
return new EliminateKit();
|
|
}
|
|
|
|
private RelativeFlags parseRelativeFlags(Element el) throws InvalidXMLException {
|
|
return RelativeFlags.of(XMLUtils.parseBoolean(el.getAttribute("yaw"), false),
|
|
XMLUtils.parseBoolean(el.getAttribute("pitch"), false));
|
|
}
|
|
|
|
@MethodParser
|
|
private Kit impulse(Element el) throws InvalidXMLException {
|
|
return new ImpulseKit(XMLUtils.parseVector(new Node(el)),
|
|
parseRelativeFlags(el));
|
|
}
|
|
|
|
@MethodParser
|
|
private Kit force(Element el) throws InvalidXMLException {
|
|
return new ForceKit(XMLUtils.parseVector(new Node(el)),
|
|
parseRelativeFlags(el));
|
|
}
|
|
|
|
@MethodParser
|
|
private Kit lives(Element el) throws InvalidXMLException {
|
|
return new LivesKit(XMLUtils.parseNumber(new Node(el), Integer.class, false, +1));
|
|
}
|
|
}
|