package com.earth2me.essentials; import static com.earth2me.essentials.I18n._; import com.earth2me.essentials.textreader.IText; import com.earth2me.essentials.textreader.KeywordReplacer; import com.earth2me.essentials.textreader.TextInput; import com.earth2me.essentials.textreader.TextPager; import com.earth2me.essentials.utils.DateUtil; import com.earth2me.essentials.utils.LocationUtil; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; import net.ess3.api.IEssentials; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.*; import org.bukkit.event.player.PlayerLoginEvent.Result; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; public class EssentialsPlayerListener implements Listener { private static final Logger LOGGER = Logger.getLogger("Minecraft"); private final transient IEssentials ess; public EssentialsPlayerListener(final IEssentials parent) { this.ess = parent; } @EventHandler(priority = EventPriority.NORMAL) public void onPlayerRespawn(final PlayerRespawnEvent event) { final User user = ess.getUser(event.getPlayer()); updateCompass(user); user.setDisplayNick(); if (ess.getSettings().isTeleportInvulnerability()) { user.enableInvulnerabilityAfterTeleport(); } } @EventHandler(priority = EventPriority.LOWEST) public void onPlayerChat(final AsyncPlayerChatEvent event) { final User user = ess.getUser(event.getPlayer()); if (user.isMuted()) { event.setCancelled(true); user.sendMessage(_("voiceSilenced")); LOGGER.info(_("mutedUserSpeaks", user.getName())); } try { final Iterator it = event.getRecipients().iterator(); while (it.hasNext()) { final User u = ess.getUser(it.next()); if (u.isIgnoredPlayer(user)) { it.remove(); } } } catch (UnsupportedOperationException ex) { if (ess.getSettings().isDebug()) { ess.getLogger().log(Level.INFO, "Ignore could not block chat due to custom chat plugin event.", ex); } else { ess.getLogger().info("Ignore could not block chat due to custom chat plugin event."); } } user.updateActivity(true); user.setDisplayNick(); } @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onPlayerMove(final PlayerMoveEvent event) { if (event.getFrom().getBlockX() == event.getTo().getBlockX() && event.getFrom().getBlockZ() == event.getTo().getBlockZ() && event.getFrom().getBlockY() == event.getTo().getBlockY()) { return; } if (!ess.getSettings().cancelAfkOnMove() && !ess.getSettings().getFreezeAfkPlayers()) { event.getHandlers().unregister(this); if (ess.getSettings().isDebug()) { LOGGER.log(Level.INFO, "Unregistering move listener"); } return; } final User user = ess.getUser(event.getPlayer()); if (user.isAfk() && ess.getSettings().getFreezeAfkPlayers()) { final Location from = event.getFrom(); final Location origTo = event.getTo(); final Location to = origTo.clone(); if (ess.getSettings().cancelAfkOnMove() && origTo.getY() >= from.getBlockY() + 1) { user.updateActivity(true); return; } to.setX(from.getX()); to.setY(from.getY()); to.setZ(from.getZ()); try { event.setTo(LocationUtil.getSafeDestination(to)); } catch (Exception ex) { event.setTo(to); } return; } final Location afk = user.getAfkPosition(); if (afk == null || !event.getTo().getWorld().equals(afk.getWorld()) || afk.distanceSquared(event.getTo()) > 9) { user.updateActivity(true); } } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerQuit(final PlayerQuitEvent event) { final User user = ess.getUser(event.getPlayer()); if (ess.getSettings().removeGodOnDisconnect() && user.isGodModeEnabled()) { user.setGodModeEnabled(false); } if (user.isVanished()) { user.setVanished(false); } user.setLogoutLocation(); if (user.isRecipeSee()) { user.getBase().getOpenInventory().getTopInventory().clear(); } user.updateActivity(false); user.dispose(); } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerJoin(final PlayerJoinEvent event) { ess.runTaskAsynchronously(new Runnable() { @Override public void run() { delayedJoin(event.getPlayer()); } }); } public void delayedJoin(final Player player) { if (!player.isOnline()) { return; } ess.getBackup().onPlayerJoin(); final User user = ess.getUser(player); if (user.isNPC()) { user.setNPC(false); } final long currentTime = System.currentTimeMillis(); user.checkMuteTimeout(currentTime); user.updateActivity(false); ess.scheduleSyncDelayedTask(new Runnable() { @Override public void run() { if (!user.isOnline()) { return; } user.setLastLogin(currentTime); user.setDisplayNick(); updateCompass(user); if (!ess.getVanishedPlayers().isEmpty() && !user.isAuthorized("essentials.vanish.see")) { for (String p : ess.getVanishedPlayers()) { Player toVanish = ess.getServer().getPlayerExact(p); if (toVanish != null && toVanish.isOnline()) { user.hidePlayer(toVanish); } } } if (user.isAuthorized("essentials.sleepingignored")) { user.setSleepingIgnored(true); } if (!ess.getSettings().isCommandDisabled("motd") && user.isAuthorized("essentials.motd")) { try { final IText input = new TextInput(user.getSource(), "motd", true, ess); final IText output = new KeywordReplacer(input, user.getSource(), ess); final TextPager pager = new TextPager(output, true); pager.showPage("1", null, "motd", user.getSource()); } catch (IOException ex) { if (ess.getSettings().isDebug()) { LOGGER.log(Level.WARNING, ex.getMessage(), ex); } else { LOGGER.log(Level.WARNING, ex.getMessage()); } } } if (!ess.getSettings().isCommandDisabled("mail") && user.isAuthorized("essentials.mail")) { final List mail = user.getMails(); if (mail.isEmpty()) { user.sendMessage(_("noNewMail")); } else { user.sendMessage(_("youHaveNewMail", mail.size())); } } if (user.isAuthorized("essentials.fly.safelogin")) { if (LocationUtil.shouldFly(user.getLocation())) { user.setAllowFlight(true); user.setFlying(true); user.sendMessage(_("flyMode", _("enabled"), user.getDisplayName())); } } user.setFlySpeed(0.1f); user.setWalkSpeed(0.2f); } }); } // Makes the compass item ingame always point to the first essentials home. #EasterEgg private void updateCompass(final User user) { Location loc = user.getHome(user.getLocation()); if (loc == null) { loc = user.getBedSpawnLocation(); } if (loc != null) { final Location updateLoc = loc; user.setCompassTarget(updateLoc); } } @EventHandler(priority = EventPriority.LOWEST) public void onPlayerLogin2(final PlayerLoginEvent event) { switch (event.getResult()) { case KICK_BANNED: break; default: return; } final String banReason = _("banFormat", _("defaultBanReason"), "Console"); event.disallow(Result.KICK_BANNED, banReason); } @EventHandler(priority = EventPriority.HIGH) public void onPlayerLogin(final PlayerLoginEvent event) { switch (event.getResult()) { case KICK_FULL: case KICK_BANNED: break; default: return; } final User user = ess.getUser(event.getPlayer()); if (event.getResult() == Result.KICK_BANNED || user.isBanned()) { final boolean banExpired = user.checkBanTimeout(System.currentTimeMillis()); if (!banExpired) { String banReason = user.getBanReason(); if (banReason == null || banReason.isEmpty() || banReason.equalsIgnoreCase("ban")) { banReason = event.getKickMessage(); } if (user.getBanTimeout() > 0) { //TODO: TL This banReason += "\n\n" + "Expires in " + DateUtil.formatDateDiff(user.getBanTimeout()); } event.disallow(Result.KICK_BANNED, banReason); return; } } if (event.getResult() == Result.KICK_FULL && !user.isAuthorized("essentials.joinfullserver")) { event.disallow(Result.KICK_FULL, _("serverFull")); return; } event.allow(); } @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onPlayerTeleport(final PlayerTeleportEvent event) { final boolean backListener = ess.getSettings().registerBackInListener(); final boolean teleportInvulnerability = ess.getSettings().isTeleportInvulnerability(); if (backListener || teleportInvulnerability) { final User user = ess.getUser(event.getPlayer()); //There is TeleportCause.COMMMAND but plugins have to actively pass the cause in on their teleports. if (backListener && (event.getCause() == TeleportCause.PLUGIN || event.getCause() == TeleportCause.COMMAND)) { user.setLastLocation(); } if (teleportInvulnerability) { user.enableInvulnerabilityAfterTeleport(); } } } @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onPlayerEggThrow(final PlayerEggThrowEvent event) { final User user = ess.getUser(event.getPlayer()); final ItemStack stack = new ItemStack(Material.EGG, 1); if (user.hasUnlimited(stack)) { user.getInventory().addItem(stack); user.updateInventory(); } } @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onPlayerBucketEmpty(final PlayerBucketEmptyEvent event) { final User user = ess.getUser(event.getPlayer()); if (user.hasUnlimited(new ItemStack(event.getBucket()))) { event.getItemStack().setType(event.getBucket()); ess.scheduleSyncDelayedTask(new Runnable() { @Override public void run() { user.updateInventory(); } }); } } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) { final Player player = event.getPlayer(); final String cmd = event.getMessage().toLowerCase(Locale.ENGLISH).split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH); if (ess.getSettings().getSocialSpyCommands().contains(cmd)) { for (Player onlinePlayer : ess.getServer().getOnlinePlayers()) { final User spyer = ess.getUser(onlinePlayer); if (spyer.isSocialSpyEnabled() && !player.equals(onlinePlayer)) { spyer.sendMessage(player.getDisplayName() + " : " + event.getMessage()); } } } else if (!cmd.equalsIgnoreCase("afk")) { final User user = ess.getUser(player); user.updateActivity(true); } } @EventHandler(priority = EventPriority.NORMAL) public void onPlayerChangedWorldFlyReset(final PlayerChangedWorldEvent event) { final User user = ess.getUser(event.getPlayer()); if (user.getGameMode() != GameMode.CREATIVE && !user.isAuthorized("essentials.fly")) { user.setFallDistance(0f); user.setAllowFlight(false); } user.setFlySpeed(0.1f); user.setWalkSpeed(0.2f); } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerChangedWorld(final PlayerChangedWorldEvent event) { final User user = ess.getUser(event.getPlayer()); final String newWorld = event.getPlayer().getLocation().getWorld().getName(); user.setDisplayNick(); updateCompass(user); if (ess.getSettings().getNoGodWorlds().contains(newWorld) && user.isGodModeEnabledRaw()) { user.sendMessage(_("noGodWorldWarning")); } if (!user.getWorld().getName().equals(newWorld)) { user.sendMessage(_("currentWorld", newWorld)); } if (user.isVanished()) { user.setVanished(user.isAuthorized("essentials.vanish")); } } @EventHandler(priority = EventPriority.NORMAL) public void onPlayerInteract(final PlayerInteractEvent event) { switch (event.getAction()) { case RIGHT_CLICK_BLOCK: if (!event.isCancelled() && event.getClickedBlock().getType() == Material.BED_BLOCK && ess.getSettings().getUpdateBedAtDaytime()) { User player = ess.getUser(event.getPlayer()); if (player.isAuthorized("essentials.sethome.bed")) { player.setBedSpawnLocation(event.getClickedBlock().getLocation()); player.sendMessage(_("bedSet", player.getLocation().getWorld().getName(), player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ())); } } break; case LEFT_CLICK_AIR: if (event.getPlayer().isFlying()) { final User user = ess.getUser(event.getPlayer()); if (user.isFlyClickJump()) { useFlyClickJump(user); return; } } case LEFT_CLICK_BLOCK: if (event.getItem() != null && event.getItem().getType() != Material.AIR) { final User user = ess.getUser(event.getPlayer()); user.updateActivity(true); if (user.hasPowerTools() && user.arePowerToolsEnabled() && usePowertools(user, event.getItem().getTypeId())) { event.setCancelled(true); } } break; default: break; } } // This method allows the /jump lock feature to work, allows teleporting while flying #EasterEgg private void useFlyClickJump(final User user) { try { final Location otarget = LocationUtil.getTarget(user.getBase()); ess.scheduleSyncDelayedTask( new Runnable() { @Override public void run() { Location loc = user.getLocation(); loc.setX(otarget.getX()); loc.setZ(otarget.getZ()); while (LocationUtil.isBlockDamaging(loc.getWorld(), loc.getBlockX(), loc.getBlockY() - 1, loc.getBlockZ())) { loc.setY(loc.getY() + 1d); } user.getBase().teleport(loc, TeleportCause.PLUGIN); } }); } catch (Exception ex) { if (ess.getSettings().isDebug()) { LOGGER.log(Level.WARNING, ex.getMessage(), ex); } } } private boolean usePowertools(final User user, final int id) { final List commandList = user.getPowertool(id); if (commandList == null || commandList.isEmpty()) { return false; } boolean used = false; // We need to loop through each command and execute for (final String command : commandList) { if (command.contains("{player}")) { continue; } else if (command.startsWith("c:")) { used = true; user.chat(command.substring(2)); } else { used = true; ess.scheduleSyncDelayedTask( new Runnable() { @Override public void run() { user.getServer().dispatchCommand(user.getBase(), command); LOGGER.log(Level.INFO, String.format("[PT] %s issued server command: /%s", user.getName(), command)); } }); } } return used; } @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onPlayerPickupItem(final PlayerPickupItemEvent event) { if (ess.getSettings().getDisableItemPickupWhileAfk()) { if (ess.getUser(event.getPlayer()).isAfk()) { event.setCancelled(true); } } } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onInventoryClickEvent(final InventoryClickEvent event) { final Inventory top = event.getView().getTopInventory(); final InventoryType type = top.getType(); if (type == InventoryType.PLAYER) { final User user = ess.getUser((Player)event.getWhoClicked()); final InventoryHolder invHolder = top.getHolder(); if (invHolder != null && invHolder instanceof HumanEntity) { final User invOwner = ess.getUser((Player)invHolder); if (user.isInvSee() && (!user.isAuthorized("essentials.invsee.modify") || invOwner.isAuthorized("essentials.invsee.preventmodify") || !invOwner.isOnline())) { event.setCancelled(true); user.updateInventory(); } } } else if (type == InventoryType.ENDER_CHEST) { final User user = ess.getUser((Player)event.getWhoClicked()); if (user.isEnderSee() && (!user.isAuthorized("essentials.enderchest.modify"))) { event.setCancelled(true); } } else if (type == InventoryType.WORKBENCH) { User user = ess.getUser((Player)event.getWhoClicked()); if (user.isRecipeSee()) { event.setCancelled(true); } } else if (type == InventoryType.CHEST && top.getSize() == 9) { final User user = ess.getUser((Player)event.getWhoClicked()); final InventoryHolder invHolder = top.getHolder(); if (invHolder != null && invHolder instanceof HumanEntity && user.isInvSee()) { event.setCancelled(true); } } } @EventHandler(priority = EventPriority.MONITOR) public void onInventoryCloseEvent(final InventoryCloseEvent event) { final Inventory top = event.getView().getTopInventory(); final InventoryType type = top.getType(); if (type == InventoryType.PLAYER) { final User user = ess.getUser((Player)event.getPlayer()); user.setInvSee(false); user.updateInventory(); } else if (type == InventoryType.ENDER_CHEST) { final User user = ess.getUser((Player)event.getPlayer()); user.setEnderSee(false); user.updateInventory(); } else if (type == InventoryType.WORKBENCH) { final User user = ess.getUser((Player)event.getPlayer()); if (user.isRecipeSee()) { user.setRecipeSee(false); event.getView().getTopInventory().clear(); user.updateInventory(); } } else if (type == InventoryType.CHEST && top.getSize() == 9) { final InventoryHolder invHolder = top.getHolder(); if (invHolder != null && invHolder instanceof HumanEntity) { final User user = ess.getUser((Player)event.getPlayer()); user.setInvSee(false); user.updateInventory(); } } } @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onPlayerFishEvent(final PlayerFishEvent event) { final User user = ess.getUser(event.getPlayer()); user.updateActivity(true); } }