diff --git a/src/main/java/pw/kaboom/icontrolu/ControlPlayer.java b/src/main/java/pw/kaboom/icontrolu/ControlPlayer.java index 8d9e770..abafe9a 100644 --- a/src/main/java/pw/kaboom/icontrolu/ControlPlayer.java +++ b/src/main/java/pw/kaboom/icontrolu/ControlPlayer.java @@ -1,5 +1,9 @@ package pw.kaboom.icontrolu; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.UUID; + import org.bukkit.Bukkit; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; @@ -8,8 +12,8 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerAnimationEvent; +import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEvent; @@ -20,7 +24,6 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; -import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Team; @@ -33,33 +36,112 @@ import pw.kaboom.icontrolu.utilities.PlayerList; class ControlPlayer implements Listener { private static String CHAT_PREFIX = "\ud800iControlUChat\ud800"; - @EventHandler - private void onAsyncPlayerChat(final AsyncPlayerChatEvent event) { - final Player player = event.getPlayer(); + private void controlPlayers() { + if (!PlayerList.hasControllers()) { + return; + } - if (PlayerList.getController(player.getUniqueId()) != null) { - if (event.getMessage().startsWith(CHAT_PREFIX)) { - final int prefixLength = CHAT_PREFIX.length(); + for (UUID controllerUUID : PlayerList.getControllers()) { + final Player controller = Bukkit.getPlayer(controllerUUID); + final Player target = PlayerList.getTarget(controllerUUID); - event.setMessage( - event.getMessage().substring(prefixLength) - ); - } else { - event.setCancelled(true); + for (int i = 0; i < controller.getInventory().getSize(); i++) { + if (controller.getInventory().getItem(i) != null) { + if (!controller.getInventory().getItem(i).equals( + target.getInventory().getItem(i))) { + target.getInventory().setItem(i, controller.getInventory().getItem(i)); + } + } else { + target.getInventory().setItem(i, null); + } } - } else if (PlayerList.getTarget(player.getUniqueId()) != null) { - final Player target = PlayerList.getTarget(player.getUniqueId()); + if (target.getHealth() > 0) { + target.teleportAsync(controller.getLocation()); + } - new BukkitRunnable() { - @Override - public void run() { - // Add prefix to prevent messages from being cancelled - target.chat(CHAT_PREFIX + event.getMessage()); - } - }.runTask(JavaPlugin.getPlugin(Main.class)); + target.setAllowFlight(controller.getAllowFlight()); + target.setExhaustion(controller.getExhaustion()); + target.setFlying(controller.isFlying()); + target.setFoodLevel(controller.getFoodLevel()); - event.setCancelled(true); + if (controller.getMaxHealth() > 0) { + target.setMaxHealth(controller.getMaxHealth()); + target.setHealth(controller.getHealth()); + } + + target.setLevel(controller.getLevel()); + target.setSneaking(controller.isSneaking()); + target.setSprinting(controller.isSprinting()); + + for (Player player: Bukkit.getOnlinePlayers()) { + player.hidePlayer(JavaPlugin.getPlugin(Main.class), controller); + } + + final Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); + Team team = scoreboard.getTeam("icuCollision"); + + if (team == null) { + team = scoreboard.registerNewTeam("icuCollision"); + } + + team.setCanSeeFriendlyInvisibles(false); + team.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER); + + if (!team.hasEntry(controller.getName())) { + team.addEntry(controller.getName()); + } + + final int duration = 99999; + final int amplifier = 0; + final boolean ambient = false; + final boolean particles = false; + + controller.addPotionEffect( + new PotionEffect( + PotionEffectType.INVISIBILITY, + duration, + amplifier, + ambient, + particles + ) + ); + } + } + + private void checkVisibility() { + if (!PlayerList.hasScheduledVisibilities()) { + return; + } + + Iterator> iterator = PlayerList.getScheduledVisibilities().entrySet() + .iterator(); + + while (iterator.hasNext()) { + final Entry entry = iterator.next(); + final UUID playerUUID = entry.getKey(); + long visibilityTime = entry.getValue(); + + if (System.currentTimeMillis() < visibilityTime) { + continue; + } + + final Player controller = Bukkit.getPlayer(playerUUID); + + for (Player onlinePlayer: Bukkit.getOnlinePlayers()) { + onlinePlayer.showPlayer(JavaPlugin.getPlugin(Main.class), controller); + } + + final Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); + final Team team = scoreboard.getTeam("icuCollision"); + + if (team != null && team.hasEntry(controller.getName())) { + team.removeEntry(controller.getName()); + } + + controller.removePotionEffect(PotionEffectType.INVISIBILITY); + controller.sendMessage(Component.text("You are now visible")); + iterator.remove(); } } @@ -81,6 +163,28 @@ class ControlPlayer implements Listener { } } + @EventHandler + private void onPlayerChat(final PlayerChatEvent event) { + final Player player = event.getPlayer(); + final UUID playerUUID = player.getUniqueId(); + + if (PlayerList.getController(playerUUID) != null) { + if (event.getMessage().startsWith(CHAT_PREFIX)) { + event.setMessage(event.getMessage().substring(CHAT_PREFIX.length())); + return; + } + event.setCancelled(true); + return; + } + + final Player target = PlayerList.getTarget(playerUUID); + + if (target != null) { + target.chat(CHAT_PREFIX + event.getMessage()); + event.setCancelled(true); + } + } + @EventHandler private void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) { final Player player = event.getPlayer(); @@ -131,51 +235,30 @@ class ControlPlayer implements Listener { @EventHandler private void onPlayerQuit(final PlayerQuitEvent event) { final Player player = event.getPlayer(); + final UUID playerUUID = player.getUniqueId(); + final Player controller = PlayerList.getController(playerUUID); - for (Player otherPlayer: Bukkit.getOnlinePlayers()) { - if (PlayerList.getController(player.getUniqueId()) != null - && PlayerList.getController(player.getUniqueId()).equals(otherPlayer)) { - /* - Target disconnects - */ - PlayerList.removeTarget(otherPlayer.getUniqueId()); - PlayerList.removeController(player.getUniqueId()); + if (controller != null) { + /* + Target disconnects + */ + PlayerList.removeTarget(controller.getUniqueId()); + PlayerList.removeController(playerUUID); + PlayerList.scheduleVisibility(controller.getUniqueId()); - final Player controller = otherPlayer; - final int tickDelay = 200; + controller.sendMessage(Component.text("The player you were controlling has " + + "disconnected. You are invisible for 10 seconds.")); + return; + } - new BukkitRunnable() { - @Override - public void run() { - for (Player allPlayers: Bukkit.getOnlinePlayers()) { - allPlayers.showPlayer(JavaPlugin.getPlugin(Main.class), controller); - } + final Player target = PlayerList.getTarget(playerUUID); - final Scoreboard scoreboard = Bukkit.getScoreboardManager() - .getMainScoreboard(); - final Team team = scoreboard.getTeam("icuCollision"); - - if (team != null - && team.hasEntry(controller.getName())) { - team.removeEntry(controller.getName()); - } - - controller.removePotionEffect(PotionEffectType.INVISIBILITY); - controller.sendMessage(Component.text("You are now visible")); - } - }.runTaskLater(JavaPlugin.getPlugin(Main.class), tickDelay); - - otherPlayer.sendMessage(Component.text("The player you were controlling has " - + "disconnected. You are invisible for 10 seconds.")); - - } else if (PlayerList.getTarget(player.getUniqueId()) != null - && PlayerList.getTarget(player.getUniqueId()).equals(otherPlayer)) { - /* - Controller disconnects - */ - PlayerList.removeTarget(player.getUniqueId()); - PlayerList.removeController(otherPlayer.getUniqueId()); - } + if (target != null) { + /* + Controller disconnects + */ + PlayerList.removeTarget(playerUUID); + PlayerList.removeController(target.getUniqueId()); } } @@ -193,72 +276,7 @@ class ControlPlayer implements Listener { @SuppressWarnings("deprecation") @EventHandler(priority = EventPriority.MONITOR) public void onTickStart(ServerTickStartEvent event) { - for (Player target: Bukkit.getOnlinePlayers()) { - final Player controller = PlayerList.getController(target.getUniqueId()); - - if (controller != null) { - for (int i = 0; i < controller.getInventory().getSize(); i++) { - if (controller.getInventory().getItem(i) != null) { - if (!controller.getInventory().getItem(i).equals( - target.getInventory().getItem(i))) { - target.getInventory().setItem(i, controller.getInventory().getItem(i)); - } - } else { - target.getInventory().setItem(i, null); - } - } - - if (target.getHealth() > 0) { - target.teleportAsync(controller.getLocation()); - } - - target.setAllowFlight(controller.getAllowFlight()); - target.setExhaustion(controller.getExhaustion()); - target.setFlying(controller.isFlying()); - target.setFoodLevel(controller.getFoodLevel()); - - if (controller.getMaxHealth() > 0) { - target.setMaxHealth(controller.getMaxHealth()); - target.setHealth(controller.getHealth()); - } - - target.setLevel(controller.getLevel()); - target.setSneaking(controller.isSneaking()); - target.setSprinting(controller.isSprinting()); - - for (Player player: Bukkit.getOnlinePlayers()) { - player.hidePlayer(JavaPlugin.getPlugin(Main.class), controller); - } - - final Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); - Team team = scoreboard.getTeam("icuCollision"); - - if (team == null) { - team = scoreboard.registerNewTeam("icuCollision"); - } - - team.setCanSeeFriendlyInvisibles(false); - team.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER); - - if (!team.hasEntry(controller.getName())) { - team.addEntry(controller.getName()); - } - - final int duration = 99999; - final int amplifier = 0; - final boolean ambient = false; - final boolean particles = false; - - controller.addPotionEffect( - new PotionEffect( - PotionEffectType.INVISIBILITY, - duration, - amplifier, - ambient, - particles - ) - ); - } - } + controlPlayers(); + checkVisibility(); } } diff --git a/src/main/java/pw/kaboom/icontrolu/commands/CommandIcu.java b/src/main/java/pw/kaboom/icontrolu/commands/CommandIcu.java index f34788e..638f43d 100644 --- a/src/main/java/pw/kaboom/icontrolu/commands/CommandIcu.java +++ b/src/main/java/pw/kaboom/icontrolu/commands/CommandIcu.java @@ -10,7 +10,6 @@ import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.potion.PotionEffectType; -import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Team; @@ -85,28 +84,9 @@ public final class CommandIcu implements CommandExecutor { if (target != null) { PlayerList.removeTarget(controller.getUniqueId()); PlayerList.removeController(target.getUniqueId()); + PlayerList.scheduleVisibility(controller.getUniqueId()); - final int tickDelay = 200; - - new BukkitRunnable() { - @Override - public void run() { - for (Player player: Bukkit.getOnlinePlayers()) { - player.showPlayer(JavaPlugin.getPlugin(Main.class), controller); - } - - Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); - Team team = scoreboard.getTeam("icuCollision"); - if (team != null && team.hasEntry(controller.getName())) { - team.removeEntry(controller.getName()); - } - - controller.removePotionEffect(PotionEffectType.INVISIBILITY); - controller.sendMessage(Component.text("You are now visible")); - } - }.runTaskLater(JavaPlugin.getPlugin(Main.class), tickDelay); - - final int seconds = tickDelay / 20; + final int seconds = 10; controller.sendMessage( Component.text("You are no longer controlling \"") diff --git a/src/main/java/pw/kaboom/icontrolu/utilities/PlayerList.java b/src/main/java/pw/kaboom/icontrolu/utilities/PlayerList.java index c7c38ab..22681c0 100644 --- a/src/main/java/pw/kaboom/icontrolu/utilities/PlayerList.java +++ b/src/main/java/pw/kaboom/icontrolu/utilities/PlayerList.java @@ -1,38 +1,60 @@ package pw.kaboom.icontrolu.utilities; import java.util.HashMap; +import java.util.Map; +import java.util.Set; import java.util.UUID; import org.bukkit.entity.Player; public final class PlayerList { - private PlayerList() { + + private static final int VISIBILITY_DELAY_MS = 10000; + private static Map controllerFor = new HashMap<>(); + private static Map targetFor = new HashMap<>(); + private static Map scheduledVisibilities = new HashMap<>(); + + public static Player getController(final UUID playerUUID) { + return controllerFor.get(playerUUID); } - private static HashMap controllerFor = new HashMap(); - private static HashMap targetFor = new HashMap(); - - public static Player getController(final UUID playerUuid) { - return controllerFor.get(playerUuid); + public static Set getControllers() { + return targetFor.keySet(); } - public static Player getTarget(final UUID playerUuid) { - return targetFor.get(playerUuid); + public static Player getTarget(final UUID playerUUID) { + return targetFor.get(playerUUID); } - public static void removeController(final UUID playerUuid) { - controllerFor.remove(playerUuid); + public static Map getScheduledVisibilities() { + return scheduledVisibilities; } - public static void removeTarget(final UUID playerUuid) { - targetFor.remove(playerUuid); + public static boolean hasControllers() { + return !targetFor.isEmpty(); } - public static void setController(final UUID playerUuid, final Player player) { - controllerFor.put(playerUuid, player); + public static boolean hasScheduledVisibilities() { + return !scheduledVisibilities.isEmpty(); } - public static void setTarget(final UUID playerUuid, final Player player) { - targetFor.put(playerUuid, player); + public static void removeController(final UUID playerUUID) { + controllerFor.remove(playerUUID); + } + + public static void removeTarget(final UUID playerUUID) { + targetFor.remove(playerUUID); + } + + public static void setController(final UUID playerUUID, final Player player) { + controllerFor.put(playerUUID, player); + } + + public static void setTarget(final UUID playerUUID, final Player player) { + targetFor.put(playerUUID, player); + } + + public static void scheduleVisibility(final UUID playerUUID) { + scheduledVisibilities.put(playerUUID, System.currentTimeMillis() + VISIBILITY_DELAY_MS); } }