package org.mctourney.autoreferee.listeners; import java.util.Iterator; import java.util.Set; import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Sign; 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.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.plugin.Plugin; import org.mctourney.autoreferee.AutoRefMatch; import org.mctourney.autoreferee.AutoRefPlayer; import org.mctourney.autoreferee.AutoRefTeam; import org.mctourney.autoreferee.AutoReferee; import org.mctourney.autoreferee.AutoRefMatch.Role; import org.mctourney.autoreferee.event.player.PlayerTeamJoinEvent; public class TeamListener implements Listener { AutoReferee plugin = null; public TeamListener(Plugin p) { plugin = (AutoReferee) p; } @EventHandler(priority=EventPriority.HIGHEST) public void chatMessage(AsyncPlayerChatEvent event) { // typical chat message format, swap out with colored version Player speaker = event.getPlayer(); AutoRefMatch match = plugin.getMatch(speaker.getWorld()); // restrict listeners to being in the same match (not world). // this should avoid messing up multi-world chat on multipurpose servers Iterator<Player> iter = event.getRecipients().iterator(); while (iter.hasNext()) { Player listener = iter.next(); if (plugin.getMatch(listener.getWorld()) != match) { iter.remove(); continue; } } // if the speaker isn't in a match, that's all we can do if (match == null) return; AutoRefTeam speakerTeam = match.getPlayerTeam(speaker); if (speakerTeam != null) { ChatColor teamColor = speakerTeam.getColor(); event.setFormat("<" + teamColor + "%s" + ChatColor.RESET + "> %s"); } else event.setFormat("<%s> %s"); modifyChatRecipients(match, speaker, event.getRecipients()); } @EventHandler(priority=EventPriority.HIGHEST) public void commandPreProcess(PlayerCommandPreprocessEvent event) { String message = event.getMessage(); if (message.startsWith("/me ")) event.setMessage("/autoref me " + message.substring(4)); } public static void modifyChatRecipients(AutoRefMatch match, Player speaker, Set<Player> recipients) { AutoRefTeam speakerTeam = match.getPlayerTeam(speaker); Role speakerRole = match.getRole(speaker); boolean practiceMode = match.isPracticeMode(); Iterator<Player> iter = recipients.iterator(); if (!match.getCurrentState().isBeforeMatch()) while (iter.hasNext()) { Player listener = iter.next(); // if listener is a streamer and the speaker is a non-streamer spectator, hide it if (match.isStreamer(listener) && speakerTeam == null && speakerRole != Role.STREAMER) { iter.remove(); continue; } // if listener is on a team, and speaker is a spectator, hide message (unless practice mode) if (!practiceMode && speakerTeam == null && match.getPlayerTeam(listener) != null) { iter.remove(); continue; } } } @EventHandler public void playerRespawn(PlayerRespawnEvent event) { World world = event.getPlayer().getWorld(); AutoRefMatch match = plugin.getMatch(world); if (match != null && match.isPlayer(event.getPlayer())) { // does this player have a bed spawn? boolean hasBed = event.getPlayer().getBedSpawnLocation() != null; // if the player attempts to respawn in a different world, bring them back Location respawnLocation = event.getRespawnLocation(); boolean changeRespawn = !hasBed || respawnLocation.getWorld() != match.getWorld() || match.inStartRegion(respawnLocation); if (changeRespawn) event.setRespawnLocation(match.getPlayerSpawn(event.getPlayer())); // setup respawn for the player match.getPlayer(event.getPlayer()).respawn(); } } @EventHandler(priority=EventPriority.HIGHEST) public void playerLogin(PlayerLoginEvent event) { Player player = event.getPlayer(); // if this player needs to be in a specific world, put them there AutoRefTeam team = plugin.getExpectedTeam(player); AutoRefMatch match = plugin.getMatch(player.getWorld()); if (team != null) { team.join(player, PlayerTeamJoinEvent.Reason.EXPECTED); match = team.getMatch(); } if (match != null && match.isPlayer(player)) match.messageReferees("player", player.getName(), "login"); } @EventHandler(priority=EventPriority.MONITOR) public void playerQuit(PlayerQuitEvent event) { Player player = event.getPlayer(); AutoRefMatch match = plugin.getMatch(player.getWorld()); if (match == null) return; // leave the team, if necessary AutoRefTeam team = plugin.getTeam(player); if (team != null) match.messageReferees("player", player.getName(), "logout"); if (team != null && !match.getCurrentState().inProgress()) team.leave(player); AutoRefPlayer apl = match.getPlayer(player); if (apl != null && player.getLocation() != null) apl.setLastLogoutLocation(player.getLocation()); // if this player was damaged recently (during the match), notify if (match.getCurrentState().inProgress() && apl != null && !apl.isDead() && apl.wasDamagedRecently()) { String message = apl.getDisplayName() + ChatColor.GRAY + " logged out during combat " + String.format("with %2.1f hearts remaining", apl.getPlayer().getHealth() / 2.0); for (Player ref : match.getReferees(true)) ref.sendMessage(message); } } @EventHandler(priority=EventPriority.HIGHEST) public void signCommand(PlayerInteractEvent event) { Player player = event.getPlayer(); AutoRefMatch match = plugin.getMatch(player.getWorld()); if (event.hasBlock() && event.getClickedBlock().getState() instanceof Sign) { String[] lines = ((Sign) event.getClickedBlock().getState()).getLines(); if (lines[0] == null || !"[AutoReferee]".equals(lines[0])) return; if (match != null && match.getCurrentState().isBeforeMatch() && match.inStartRegion(event.getClickedBlock().getLocation())) { // execute the command on the sign (and hope like hell that AutoReferee picks it up) if (event.getAction() == Action.RIGHT_CLICK_BLOCK) player.performCommand(ChatColor.stripColor(lines[1] + " " + lines[2]).trim()); event.setCancelled(true); } } } @EventHandler(priority=EventPriority.HIGHEST) public void changeGamemode(PlayerGameModeChangeEvent event) { Player player = event.getPlayer(); AutoRefMatch match = plugin.getMatch(player.getWorld()); // if there is a match currently in progress on this world... if (match != null && !match.isPracticeMode() && match.getCurrentState().inProgress()) { // cancel the gamemode change if the player is a participant if (event.getNewGameMode() == GameMode.CREATIVE && match.isPlayer(player) && !player.hasPermission("autoreferee.admin")) { player.sendMessage(ChatColor.RED + "Cannot change gamemode outside of practice mode!"); event.setCancelled(true); } } } }