package tc.oc.pgm.doublejump; import java.util.Iterator; import java.util.Map; import javax.annotation.Nullable; import javax.inject.Inject; import org.bukkit.GameMode; import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerToggleFlightEvent; import org.bukkit.plugin.Plugin; import org.bukkit.util.Vector; import tc.oc.commons.bukkit.util.OnlinePlayerMapAdapter; import tc.oc.pgm.events.ListenerScope; import tc.oc.pgm.events.PlayerResetEvent; import tc.oc.pgm.match.MatchModule; import tc.oc.pgm.match.MatchPlayer; import tc.oc.pgm.match.MatchScope; @ListenerScope(MatchScope.RUNNING) public class DoubleJumpMatchModule extends MatchModule implements Listener { private class Jumper { final Player player; final DoubleJumpKit kit; float charge; private Jumper(Player player, DoubleJumpKit kit) { this.player = player; this.kit = kit; } } private final OnlinePlayerMapAdapter<Jumper> jumpers; @Inject DoubleJumpMatchModule(Plugin plugin) { this.jumpers = new OnlinePlayerMapAdapter<>(plugin); this.jumpers.enable(); } @Override public void enable() { super.enable(); getMatch().getScheduler(MatchScope.LOADED).createRepeatingTask(1, new Runnable() { public void run() { for(Map.Entry<Player, Jumper> entry : jumpers.entrySetCopy()) { Player player = entry.getKey(); Jumper jumper = entry.getValue(); if(player.isOnGround() || jumper.kit.rechargeInAir || jumper.charge > 0f) { setCharge(jumper, jumper.charge + jumper.kit.chargePerTick()); refreshJump(player); } } } }); } @Override public void disable() { this.disableAll(); super.disable(); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerReset(PlayerResetEvent event) { this.setKit(event.getPlayer().getBukkit(), null); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerDeath(PlayerDeathEvent event) { this.setKit(event.getEntity(), null); } public void setKit(Player player, @Nullable DoubleJumpKit kit) { if(kit != null && kit.enabled) { Jumper jumper = new Jumper(player, kit); this.jumpers.put(player, jumper); this.setCharge(jumper, 1f); } else { this.jumpers.remove(player); this.refreshJump(player); } } public void disableAll() { for(Iterator<Player> iterator = this.jumpers.keySet().iterator(); iterator.hasNext(); ) { Player player = iterator.next(); iterator.remove(); this.refreshJump(player); } } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerToggleFlight(final PlayerToggleFlightEvent event) { Player player = event.getPlayer(); Jumper jumper = this.jumpers.get(player); if(jumper == null) return; if(event.isFlying()) { event.setCancelled(true); this.setCharge(jumper, 0f); this.refreshJump(player); // calculate jump Vector impulse = player.getLocation().getDirection(); impulse.setY(0.75 + Math.abs(impulse.getY()) * 0.5); impulse.multiply(jumper.kit.power / 3f); event.getPlayer().applyImpulse(impulse, true); player.getWorld().playSound(player.getLocation(), Sound.ENTITY_ZOMBIE_INFECT, 0.5f, 1.8f); } } private void setCharge(Jumper jumper, float charge) { if(jumper.kit.needsRecharge()) { charge = Math.min(charge, 1.0f); if(charge != jumper.charge) { jumper.charge = charge; jumper.player.setExp(jumper.charge); } } } private void refreshJump(Player player) { if(player.getGameMode() != GameMode.CREATIVE) { player.setAllowFlight(this.canJump(player)); } } private boolean canJump(Player player) { Jumper jumper = this.jumpers.get(player); return jumper != null && (!jumper.kit.needsRecharge() || jumper.charge >= 1f); } public boolean hasKit(MatchPlayer player) { return jumpers.containsKey(player.getBukkit()); } }