package tc.oc.pgm.flag.state; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.util.Vector; import tc.oc.commons.bukkit.util.NMSHacks; import tc.oc.pgm.flag.Flag; import tc.oc.pgm.flag.Post; import tc.oc.pgm.flag.event.FlagCaptureEvent; /** * Base class for flag states in which the banner is physically present * somewhere in the map (i.e. most of them). */ public abstract class Spawned extends BaseState { protected int particleClock; public Spawned(Flag flag, Post post) { super(flag, post); } // Location the flag must travel from to respawn public abstract Location getLocation(); /** * True if the flag can transition from its current state to a {@link Respawning} state. * This is false when the flag is already in that state, or in a {@link Returned} state, * in which case there is no reason to respawn it. */ public abstract boolean isRecoverable(); /** * Transition to a {@link Respawning} state, if the flag {@link #isRecoverable()} * in its current state. * * Does nothing unless the match is running. */ protected void recover() { if(flag.getMatch().isRunning()) { forceRecover(); } } /** * Transition to a {@link Respawning} state, if the flag {@link #isRecoverable()} * in its current state. * * This method works even if the match is over, so other states use it as a fallback * to get out of exceptional situations, e.g. the flag carrier disconnecting. */ protected void forceRecover() { if(isRecoverable()) { this.flag.transition(new Respawning(this.flag, this.post, this.getLocation(), false, false)); } } @Override public void onEvent(FlagCaptureEvent event) { super.onEvent(event); // Not crazy about using an event for game logic, but this is by far the simplest way to do it if(event.getNet().getRecoverableFlags().contains(this.flag.getDefinition())) { this.recover(); } } protected boolean canSeeParticles(Player player) { return true; } @Override public void tickLoaded() { super.tickLoaded(); this.particleClock++; if(this.flag.getDefinition().showBeam()) { Object packet = NMSHacks.particlesPacket("ITEM_CRACK", true, this.getLocation().clone().add(0, 56, 0).toVector(), new Vector(0.15, 24, 0.15), // radius on each axis of the particle ball 0f, // initial horizontal velocity 40, // number of particles Material.WOOL.getId(), this.flag.getDyeColor().getWoolData()); for(Player player : this.flag.getMatch().getServer().getOnlinePlayers()) { if(this.canSeeParticles(player)) NMSHacks.sendPacket(player, packet); } } } }