Mineplex2018-withcommit/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameSpectatorManager.java
cnr 6b2f601c7a Prevent a spectator race condition in arcade games
Previously, a player would erratically become a spectator if s/he
spammed the "spectate next player" action between rounds (i.e.
left-click while spectating a player).
2016-04-13 18:20:39 -05:00

266 lines
6.4 KiB
Java

package nautilus.game.arcade.managers;
import java.util.List;
import org.bukkit.GameMode;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.event.vehicle.VehicleDamageEvent;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTextBottom;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import nautilus.game.arcade.ArcadeManager;
import nautilus.game.arcade.game.Game.GameState;
public class GameSpectatorManager implements Listener
{
ArcadeManager Manager;
public GameSpectatorManager(ArcadeManager manager)
{
Manager = manager;
Manager.getPluginManager().registerEvents(this, Manager.getPlugin());
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void interactCancel(PlayerInteractEvent event)
{
if (Manager.GetGame() == null)
return;
Player player = event.getPlayer();
if (!Manager.GetGame().IsAlive(player))
event.setCancelled(true);
processClick(player, event.getAction());
}
public void processClick(Player player, Action action)
{
if (Manager.GetGame() == null)
return;
if(!Manager.GetGame().AllowEntitySpectate)
return;
if(!Manager.GetGame().IsLive())
return;
if(player.getGameMode() != GameMode.SPECTATOR)
return;
if(player.getSpectatorTarget() == null)
return;
if(!(player.getSpectatorTarget() instanceof Player))
return;
List<Player> players = Manager.GetGame().GetPlayers(true);
int currentPlayer = 0;
for(Player otherPlayer : players)
{
currentPlayer++;
if(((Player) player.getSpectatorTarget()) == otherPlayer)
break;
}
if(action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK)
currentPlayer = currentPlayer - 2;
else
return;
if(currentPlayer < 0)
currentPlayer = players.size() - 1;
if(currentPlayer >= players.size())
currentPlayer = 0;
if(players.get(currentPlayer) == null)
return;
Player specPlayer = players.get(currentPlayer);
setSpectating(player, specPlayer);
}
@EventHandler(priority = EventPriority.LOW)
public void interactEntityCancel(PlayerInteractEntityEvent event)
{
if (Manager.GetGame() == null)
return;
Player player = event.getPlayer();
if (Manager.GetGame().GetState() == GameState.Recruit)
{
if (Manager.getCosmeticManager().getMountManager().isMount(event.getRightClicked()))
{
return;
}
}
if (!Manager.GetGame().IsAlive(player))
{
event.setCancelled(true);
if(Manager.GetGame().IsLive())
{
if(Manager.GetGame().AllowEntitySpectate)
{
setSpectating(player, event.getRightClicked());
}
}
}
}
@EventHandler
public void updateSpecEntitys(UpdateEvent event)
{
if(event.getType() != UpdateType.FASTER)
return;
if(Manager.GetGame() == null)
return;
if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End)
{
if(Manager.GetGame().AllowEntitySpectate)
{
for(Player player : UtilServer.getPlayers())
{
if (!Manager.GetGame().IsAlive(player))
{
if(player.getGameMode() == GameMode.SPECTATOR)
{
if(player.getSpectatorTarget() == null)
{
player.setGameMode(GameMode.SURVIVAL);
player.setAllowFlight(true);
}
}
}
}
}
}
}
@EventHandler(priority = EventPriority.LOW)
public void spectatedEntityDeath(PlayerDeathEvent event)
{
if(Manager.GetGame() == null)
return;
if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End)
{
if(Manager.GetGame().AllowEntitySpectate)
{
for(Player player : UtilServer.getPlayers())
{
if (!Manager.GetGame().IsAlive(player))
{
if(player.getGameMode() == GameMode.SPECTATOR)
{
if(player.getSpectatorTarget() == event.getEntity())
{
if(Manager.GetGame().GetPlayers(true).size() >= 1)
{
setSpectating(player, Manager.GetGame().GetPlayers(true).get(UtilMath.r(Manager.GetGame().GetPlayers(true).size())));
return;
}
player.setGameMode(GameMode.SURVIVAL);
player.setAllowFlight(true);
}
}
}
}
}
}
}
@EventHandler(priority = EventPriority.LOW)
public void dismountEntity(PlayerToggleSneakEvent event)
{
if(Manager.GetGame() == null)
return;
if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End)
{
if(Manager.GetGame().AllowEntitySpectate)
{
if(!Manager.GetGame().IsAlive(event.getPlayer()))
{
if(event.getPlayer().getGameMode() == GameMode.SPECTATOR)
{
event.getPlayer().setGameMode(GameMode.SURVIVAL);
event.getPlayer().setAllowFlight(true);
}
}
}
}
}
private void setSpectating(Player player, Entity target)
{
player.setGameMode(GameMode.SURVIVAL);
player.teleport(target.getLocation().add(0, 1, 0));
player.getInventory().setHeldItemSlot(5);
Manager.runSyncLater(new Runnable()
{
@Override
public void run()
{
if (Manager.GetGame().IsAlive(player))
return;
Player ptarget = null;
if (target instanceof Player)
ptarget = (Player) target;
if (ptarget != null)
{
if (!Manager.GetGame().IsAlive(ptarget))
return;
}
player.setGameMode(GameMode.SPECTATOR);
player.setSpectatorTarget(target);
if (ptarget != null)
UtilTextBottom.display(C.cGray + "You are spectating " + F.elem(Manager.GetGame().GetTeam(ptarget).GetColor() + ptarget.getName()) + ".", player);
UtilPlayer.message(player, F.main("Game", "Sneak to stop spectating."));
}
}, 1);
}
@EventHandler(priority = EventPriority.LOW)
public void vehicleDamage(VehicleDamageEvent event)
{
if (Manager.GetGame() == null)
return;
if (!(event.getAttacker() instanceof Player))
return;
Player player = (Player)event.getAttacker();
if (!Manager.GetGame().IsAlive(player))
event.setCancelled(true);
}
}