package tc.oc.pgm.flag; import java.util.Collection; import java.util.Optional; import java.util.stream.Stream; import javax.annotation.Nullable; import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.DyeColor; import tc.oc.api.docs.virtual.MapDoc; import tc.oc.commons.bukkit.util.BukkitUtils; import tc.oc.commons.core.stream.Collectors; import tc.oc.pgm.features.FeatureInfo; import tc.oc.pgm.features.GamemodeFeature; import tc.oc.pgm.filters.Filter; import tc.oc.pgm.filters.query.IQuery; import tc.oc.pgm.goals.ProximityGoalDefinition; import tc.oc.pgm.goals.ProximityGoalDefinitionImpl; import tc.oc.pgm.goals.ProximityMetric; import tc.oc.pgm.kits.Kit; import tc.oc.pgm.match.Match; import tc.oc.pgm.module.ModuleLoadException; import tc.oc.pgm.teams.TeamFactory; @FeatureInfo(name = "flag") public interface FlagDefinition extends ProximityGoalDefinition<Flag>, GamemodeFeature { @Nullable DyeColor getColor(); @Override String getColoredName(); Post getDefaultPost(); double getPointsPerCapture(); double getPointsPerSecond(); Filter getPickupFilter(); Filter getDropFilter(); Filter getCaptureFilter(); @Nullable Kit getPickupKit(); @Nullable Kit getDropKit(); @Nullable Kit getCarryKit(); boolean hasMultipleCarriers(); @Nullable BaseComponent getCarryMessage(); boolean canDropOnWater(); boolean showBeam(); boolean canPickup(IQuery query); boolean canCapture(IQuery query, Collection<Net> nets); } class FlagDefinitionImpl extends ProximityGoalDefinitionImpl<Flag> implements FlagDefinition { private static String makeName(@Nullable String name, @Nullable DyeColor color) { if(name != null) return name; if(color != null) return color.name().charAt(0) + color.name().substring(1).toLowerCase() + " Flag"; return "Flag"; } private final @Inspect @Nullable DyeColor color; // Flag color, null detects color from the banner at match load time private final @Inspect Post defaultPost; // Flag starts the match at this post private final @Inspect double pointsPerCapture; // Points awarded for capturing this flag, in addition to points from the Net private final @Inspect double pointsPerSecond; // Points awarded while carrying this flag private final @Inspect Filter pickupFilter; // Filter players who can pickup this flag private final @Inspect Filter dropFilter; // Filter players who can drop the flag private final @Inspect Filter captureFilter; // Filter players who can capture this flag private final @Inspect @Nullable Kit pickupKit; // Kit to give on flag pickup private final @Inspect @Nullable Kit dropKit; // Kit to give carrier when they drop the flag private final @Inspect @Nullable Kit carryKit; // Kit to give to/take from the flag carrier private final @Inspect boolean multiCarrier; // Affects how the flag appears in the scoreboard private final @Inspect @Nullable BaseComponent carryMessage; // Custom message to show flag carrier private final @Inspect boolean dropOnWater; // Flag can freeze water to drop on it private final @Inspect boolean showBeam; public FlagDefinitionImpl(@Nullable String name, @Nullable Boolean required, boolean visible, @Nullable DyeColor color, Post defaultPost, Optional<TeamFactory> owner, double pointsPerCapture, double pointsPerSecond, Filter pickupFilter, Filter dropFilter, Filter captureFilter, @Nullable Kit pickupKit, @Nullable Kit dropKit, @Nullable Kit carryKit, boolean multiCarrier, @Nullable BaseComponent carryMessage, boolean dropOnWater, boolean showBeam, ProximityMetric flagProximityMetric, ProximityMetric netProximityMetric) { // We can't use the owner field in OwnedGoal because our owner // is a reference that can't be resolved until after parsing. super(makeName(name, color), required, visible, owner, flagProximityMetric, netProximityMetric); this.color = color; this.defaultPost = defaultPost; this.pointsPerCapture = pointsPerCapture; this.pointsPerSecond = pointsPerSecond; this.pickupFilter = pickupFilter; this.dropFilter = dropFilter; this.captureFilter = captureFilter; this.pickupKit = pickupKit; this.dropKit = dropKit; this.carryKit = carryKit; this.multiCarrier = multiCarrier; this.carryMessage = carryMessage; this.dropOnWater = dropOnWater; this.showBeam = showBeam; } @Override public Stream<MapDoc.Gamemode> gamemodes() { return Stream.of(MapDoc.Gamemode.ctf); } @Override public boolean isShared() { return true; } @Override public @Nullable DyeColor getColor() { return this.color; } @Override public String getColoredName() { if(this.getColor() != null) { return BukkitUtils.dyeColorToChatColor(this.getColor()) + this.getName(); } else { return super.getColoredName(); } } @Override public Post getDefaultPost() { return this.defaultPost; } @Override public double getPointsPerCapture() { return this.pointsPerCapture; } @Override public double getPointsPerSecond() { return this.pointsPerSecond; } @Override public Filter getPickupFilter() { return this.pickupFilter; } @Override public Filter getDropFilter() { return dropFilter; } @Override public Filter getCaptureFilter() { return captureFilter; } @Override public @Nullable Kit getPickupKit() { return pickupKit; } @Override public @Nullable Kit getDropKit() { return dropKit; } @Override public @Nullable Kit getCarryKit() { return carryKit; } @Override public boolean hasMultipleCarriers() { return multiCarrier; } @Override public @Nullable BaseComponent getCarryMessage() { return carryMessage; } @Override public boolean canDropOnWater() { return dropOnWater; } @Override public boolean showBeam() { return showBeam; } @Override public Flag createFeature(Match match) throws ModuleLoadException { return new Flag(match, this, match.featureDefinitions() .all(Net.class) .filter(net -> net.getCapturableFlags().contains(this)) .collect(Collectors.toImmutableSet())); } @Override public boolean canPickup(IQuery query) { return getPickupFilter().query(query).isAllowed() && getDefaultPost().getPickupFilter().query(query).isAllowed(); } @Override public boolean canCapture(IQuery query, Collection<Net> nets) { if(getCaptureFilter().query(query).isDenied()) return false; for(Net net : nets) { if(net.getCaptureFilter().query(query).isAllowed()) return true; } return false; } }