diff --git a/PGM/src/main/java/tc/oc/pgm/MapModulesManifest.java b/PGM/src/main/java/tc/oc/pgm/MapModulesManifest.java index 5615ff0..3b95fa2 100644 --- a/PGM/src/main/java/tc/oc/pgm/MapModulesManifest.java +++ b/PGM/src/main/java/tc/oc/pgm/MapModulesManifest.java @@ -1,6 +1,7 @@ package tc.oc.pgm; import tc.oc.commons.core.inject.HybridManifest; +import tc.oc.pgm.beacon.BeaconModule; import tc.oc.pgm.blockdrops.BlockDropsModule; import tc.oc.pgm.crafting.CraftingModule; import tc.oc.pgm.eventrules.EventRuleModule; @@ -41,6 +42,7 @@ public class MapModulesManifest extends HybridManifest { install(new CraftingModule.Factory()); install(new ItemModifyModule.Factory()); install(new PickupModule.Factory()); + install(new BeaconModule.Factory()); install(new GoalModule.Factory()); install(new ProjectileModule.Factory()); install(new SpawnModule.Factory()); diff --git a/PGM/src/main/java/tc/oc/pgm/beacon/Beacon.java b/PGM/src/main/java/tc/oc/pgm/beacon/Beacon.java new file mode 100644 index 0000000..7a1bd77 --- /dev/null +++ b/PGM/src/main/java/tc/oc/pgm/beacon/Beacon.java @@ -0,0 +1,46 @@ +package tc.oc.pgm.beacon; + +import org.bukkit.Material; +import org.bukkit.util.Vector; +import tc.oc.commons.bukkit.util.NMSHacks; +import tc.oc.minecraft.protocol.MinecraftVersion; +import tc.oc.pgm.features.Feature; +import tc.oc.pgm.match.Match; +import tc.oc.pgm.match.MatchPlayer; +import tc.oc.pgm.match.MatchScope; +import tc.oc.pgm.match.Repeatable; + +public class Beacon implements Feature { + + private final BeaconDefinition data; + private final Match match; + + public Beacon(Match match, BeaconDefinition data) { + this.match = match; + this.data = data; + } + + @Repeatable(scope = MatchScope.LOADED) + public void tick() { + Object packet = NMSHacks.particlesPacket("ITEM_CRACK", true, + this.data.location().clone().add(0, 56, 0), + new Vector(0.15, 24, 0.15), // radius on each axis of the particle ball + 0f, // initial horizontal velocity + data.particleCount(), // number of particles + Material.WOOL.getId(), this.data.color().getWoolData()); + + match.getPlayers().stream().filter(this::canSeeParticles).forEach((matchPlayer -> NMSHacks.sendPacket(matchPlayer.getBukkit(), packet))); + + } + + protected boolean canSeeParticles(MatchPlayer player) { + return MinecraftVersion.atLeast(MinecraftVersion.MINECRAFT_1_8, player.getBukkit().getProtocolVersion()) && + data.visible().query(player).isAllowed(); + } + + @Override + public BeaconDefinition getDefinition() { + return data; + } + +} diff --git a/PGM/src/main/java/tc/oc/pgm/beacon/BeaconDefinition.java b/PGM/src/main/java/tc/oc/pgm/beacon/BeaconDefinition.java new file mode 100644 index 0000000..5fd30cb --- /dev/null +++ b/PGM/src/main/java/tc/oc/pgm/beacon/BeaconDefinition.java @@ -0,0 +1,69 @@ +package tc.oc.pgm.beacon; + +import org.bukkit.DyeColor; +import org.bukkit.util.Vector; +import tc.oc.pgm.features.FeatureDefinition; +import tc.oc.pgm.features.FeatureFactory; +import tc.oc.pgm.features.FeatureInfo; +import tc.oc.pgm.filters.Filter; +import tc.oc.pgm.match.Match; +import tc.oc.pgm.module.ModuleLoadException; + +@FeatureInfo(name = "beacon") +public interface BeaconDefinition extends FeatureDefinition, FeatureFactory { + + Filter visible(); + + Integer particleCount(); + + Vector location(); + + DyeColor color(); + +} + +class BeaconDefinitionImpl extends FeatureDefinition.Impl implements BeaconDefinition { + + private final @Inspect Filter visible; + private final @Inspect Integer particleCount; + private final @Inspect Vector location; + private final @Inspect DyeColor color; + + public BeaconDefinitionImpl(Filter visible, Integer particleCount, Vector location, DyeColor color) { + this.visible = visible; + this.particleCount = particleCount; + this.location = location; + this.color = color; + } + + @Override + public Filter visible() { + return visible; + } + + @Override + public Integer particleCount() { + return particleCount; + } + + @Override + public Vector location() { + return location; + } + + @Override + public DyeColor color() { + return color; + } + + @Override + public Beacon createFeature(Match match) throws ModuleLoadException { + return new Beacon(match, this); + } + + @Override + public void load(Match match) { + match.features().get(this); + } + +} diff --git a/PGM/src/main/java/tc/oc/pgm/beacon/BeaconModule.java b/PGM/src/main/java/tc/oc/pgm/beacon/BeaconModule.java new file mode 100644 index 0000000..6e76136 --- /dev/null +++ b/PGM/src/main/java/tc/oc/pgm/beacon/BeaconModule.java @@ -0,0 +1,41 @@ +package tc.oc.pgm.beacon; + +import org.bukkit.DyeColor; +import org.bukkit.util.Vector; +import org.jdom2.Document; +import org.jdom2.Element; +import tc.oc.pgm.filters.Filter; +import tc.oc.pgm.filters.matcher.StaticFilter; +import tc.oc.pgm.filters.parser.FilterParser; +import tc.oc.pgm.map.MapModule; +import tc.oc.pgm.map.MapModuleContext; +import tc.oc.pgm.map.MapModuleFactory; +import tc.oc.pgm.utils.XMLUtils; +import tc.oc.pgm.xml.InvalidXMLException; + +import java.util.logging.Logger; + +public abstract class BeaconModule implements MapModule { + + public static class Factory extends MapModuleFactory { + + @Override + public BeaconModule parse(MapModuleContext context, Logger logger, Document doc) throws InvalidXMLException { + FilterParser filterParser = context.needModule(FilterParser.class); + + for(Element el : XMLUtils.flattenElements(doc.getRootElement(), "beacons", "beacon")) { + DyeColor color = XMLUtils.parseDyeColor(el.getAttribute("color"), DyeColor.WHITE); + Vector location = XMLUtils.parseVector(el.getAttribute("location")); + if(location == null) { + throw new InvalidXMLException("location cannot be null!"); + } + Integer particleCount = XMLUtils.parseNumber(el.getAttribute("particle-count"), Integer.class, 40); + Filter visible = filterParser.property(el, "visibility-filter").optional(StaticFilter.ALLOW); + context.features().define(el, new BeaconDefinitionImpl(visible, particleCount, location, color)); + } + + return null; + } + } + +}