diff --git a/.gitignore b/.gitignore index f845591..d3ee570 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ target/ .classpath .project *.iml +.theia/ +run/ \ No newline at end of file diff --git a/pom.xml b/pom.xml index e418344..5e21319 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.1.2 + 3.3.0 checkstyle diff --git a/src/main/java/pw/kaboom/icontrolu/Main.java b/src/main/java/pw/kaboom/icontrolu/Main.java index ee09a3d..5771f95 100644 --- a/src/main/java/pw/kaboom/icontrolu/Main.java +++ b/src/main/java/pw/kaboom/icontrolu/Main.java @@ -1,30 +1,25 @@ package pw.kaboom.icontrolu; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.scoreboard.Scoreboard; -import org.bukkit.scoreboard.Team; - -import net.kyori.adventure.text.Component; import pw.kaboom.icontrolu.commands.CommandIcu; -import pw.kaboom.icontrolu.PlayerControl; +import pw.kaboom.icontrolu.modules.PlayerControl; public final class Main extends JavaPlugin { + private final PlayerControl controlModule = new PlayerControl(); + @Override public void onEnable() { /* Commands */ - this.getCommand("icu").setExecutor(new CommandIcu()); + this.getCommand("icu").setExecutor(new CommandIcu(controlModule)); /* Modules */ - PlayerControl.enable(); - this.getServer().getPluginManager().registerEvents(new PlayerControl(), this); + controlModule.enable(); + this.getServer().getPluginManager().registerEvents(controlModule, this); } @Override public void onDisable() { - PlayerControl.disable(); + controlModule.disable(); } } diff --git a/src/main/java/pw/kaboom/icontrolu/commands/CommandIcu.java b/src/main/java/pw/kaboom/icontrolu/commands/CommandIcu.java index 18819ea..90c304b 100644 --- a/src/main/java/pw/kaboom/icontrolu/commands/CommandIcu.java +++ b/src/main/java/pw/kaboom/icontrolu/commands/CommandIcu.java @@ -8,18 +8,20 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.scoreboard.Scoreboard; -import org.bukkit.scoreboard.Team; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import pw.kaboom.icontrolu.Main; -import pw.kaboom.icontrolu.PlayerControl; +import pw.kaboom.icontrolu.modules.ControlManager; +import pw.kaboom.icontrolu.modules.PlayerControl; public final class CommandIcu implements CommandExecutor { + private final PlayerControl controlModule; + + public CommandIcu(final PlayerControl controlModule) { + this.controlModule = controlModule; + } + private void controlCommand(final Player controller, final String label, final String[] args) { if (args.length == 1) { controller.sendMessage(Component @@ -47,16 +49,13 @@ private void controlCommand(final Player controller, final String label, final S return; } - if (PlayerControl.getTarget(controller.getUniqueId()) != null) { - controller.sendMessage( - Component.text("You are already controlling \"") - .append(Component.text(target.getName())) - .append(Component.text("\"")) - ); + final ControlManager manager = controlModule.manager; + if (manager.hasController(controller.getUniqueId())) { + controller.sendMessage(Component.text("You are already controlling someone")); return; } - if (PlayerControl.getController(target.getUniqueId()) != null) { + if (manager.hasTarget(target.getUniqueId())) { controller.sendMessage( Component.text("Player \"") .append(Component.text(target.getName())) @@ -65,7 +64,7 @@ private void controlCommand(final Player controller, final String label, final S return; } - if (PlayerControl.getTarget(target.getUniqueId()) != null) { + if (manager.hasController(target.getUniqueId())) { controller.sendMessage( Component.text("Player \"") .append(Component.text(target.getName())) @@ -82,9 +81,7 @@ private void controlCommand(final Player controller, final String label, final S controller.teleportAsync(target.getLocation()); controller.getInventory().setContents(target.getInventory().getContents()); - PlayerControl.setTarget(controller.getUniqueId(), target); - PlayerControl.setController(target.getUniqueId(), controller); - + manager.control(controller, target); controller.sendMessage( Component.text("You are now controlling \"") .append(Component.text(target.getName())) @@ -93,16 +90,14 @@ private void controlCommand(final Player controller, final String label, final S } private void stopCommand(final Player controller) { - final Player target = PlayerControl.getTarget(controller.getUniqueId()); + final Player target = controlModule.manager.removeController(controller.getUniqueId()); if (target == null) { controller.sendMessage(Component.text("You are not controlling anyone at the moment")); return; } - PlayerControl.removeTarget(controller.getUniqueId()); - PlayerControl.removeController(target.getUniqueId()); - PlayerControl.scheduleVisibility(controller.getUniqueId()); + controlModule.scheduleVisibility(controller.getUniqueId()); controller.sendMessage( Component.text("You are no longer controlling \"") diff --git a/src/main/java/pw/kaboom/icontrolu/modules/ControlManager.java b/src/main/java/pw/kaboom/icontrolu/modules/ControlManager.java new file mode 100644 index 0000000..06a3832 --- /dev/null +++ b/src/main/java/pw/kaboom/icontrolu/modules/ControlManager.java @@ -0,0 +1,71 @@ +package pw.kaboom.icontrolu.modules; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; +import java.util.function.BiConsumer; + +public final class ControlManager { + // + private final BiMap<@NotNull UUID, @NotNull UUID> map = HashBiMap.create(); + + public void control(final Player controller, final Player target) { + map.put(controller.getUniqueId(), target.getUniqueId()); + } + + public boolean hasController(final UUID controllerUUID) { + return map.containsKey(controllerUUID); + } + + public boolean hasTarget(final UUID targetUUID) { + return map.containsValue(targetUUID); + } + + public Player getTarget(final UUID controllerUUID) { + final UUID targetUUID = map.get(controllerUUID); + if (targetUUID == null) return null; + + final Player target = Bukkit.getPlayer(targetUUID); + if (target == null) map.remove(controllerUUID); + return target; + } + + public Player getController(final UUID targetUUID) { + final UUID controllerUUID = map.inverse().get(targetUUID); + if (controllerUUID == null) return null; + + final Player controller = Bukkit.getPlayer(controllerUUID); + if (controller == null) map.remove(controllerUUID); + return controller; + } + + public void forEach(final BiConsumer<@NotNull Player, @NotNull Player> consumer) { + this.map.entrySet().removeIf(e -> { + final Player controller = Bukkit.getPlayer(e.getKey()); + if (controller == null) return true; + final Player target = Bukkit.getPlayer(e.getValue()); + if (target == null) return true; + + consumer.accept(controller, target); + return false; + }); + } + + public Player removeController(final UUID controllerUUID) { + final UUID targetUUID = map.remove(controllerUUID); + if (targetUUID == null) return null; + + return Bukkit.getPlayer(targetUUID); + } + + public Player removeTarget(final UUID targetUUID) { + final UUID controlerUUID = map.inverse().remove(targetUUID); + if (controlerUUID == null) return null; + + return Bukkit.getPlayer(controlerUUID); + } +} diff --git a/src/main/java/pw/kaboom/icontrolu/modules/PlayerControl.java b/src/main/java/pw/kaboom/icontrolu/modules/PlayerControl.java index a61a181..92d9e79 100644 --- a/src/main/java/pw/kaboom/icontrolu/modules/PlayerControl.java +++ b/src/main/java/pw/kaboom/icontrolu/modules/PlayerControl.java @@ -1,4 +1,4 @@ -package pw.kaboom.icontrolu; +package pw.kaboom.icontrolu.modules; import java.util.HashMap; import java.util.Iterator; @@ -32,17 +32,21 @@ import com.destroystokyo.paper.event.server.ServerTickStartEvent; import net.kyori.adventure.text.Component; +import pw.kaboom.icontrolu.Main; public final class PlayerControl implements Listener { private static final String CHAT_PREFIX = "\ud800iControlUChat\ud800"; private static final int VISIBILITY_DELAY_MS = 10000; - private static Map controllers = new HashMap<>(); - private static Map targets = new HashMap<>(); - private static Map scheduledVisibilities = new HashMap<>(); + private final Map scheduledVisibilities = new HashMap<>(); + public final ControlManager manager = new ControlManager(); - public static void enable() { + public static int getVisibilityDelay() { + return VISIBILITY_DELAY_MS / 1000; + } + + public void enable() { /* Setup scoreboard team to prevent player collisions */ final Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); final Team team = scoreboard.getTeam("icuCollision"); @@ -51,11 +55,8 @@ public static void enable() { } } - public static void disable() { - for (UUID controllerUUID : targets.keySet()) { - final Player controller = Bukkit.getPlayer(controllerUUID); - final Player target = getTarget(controller.getUniqueId()); - + public void disable() { + manager.forEach((controller, target) -> { for (Player player: Bukkit.getOnlinePlayers()) { player.showPlayer(JavaPlugin.getPlugin(Main.class), controller); } @@ -73,50 +74,15 @@ public static void disable() { .append(Component.text(target.getName())) .append(Component.text("\" due to server reload")) ); - } - } - - public static Player getController(final UUID playerUUID) { - return controllers.get(playerUUID); - } - - public static Player getTarget(final UUID playerUUID) { - return targets.get(playerUUID); - } - - public static int getVisibilityDelay() { - return VISIBILITY_DELAY_MS / 1000; - } - - public static void removeController(final UUID playerUUID) { - controllers.remove(playerUUID); - } - - public static void removeTarget(final UUID playerUUID) { - targets.remove(playerUUID); - } - - public static void setController(final UUID playerUUID, final Player player) { - controllers.put(playerUUID, player); + }); } - public static void setTarget(final UUID playerUUID, final Player player) { - targets.put(playerUUID, player); - } - - public static void scheduleVisibility(final UUID playerUUID) { + public void scheduleVisibility(final UUID playerUUID) { scheduledVisibilities.put(playerUUID, System.currentTimeMillis() + VISIBILITY_DELAY_MS); } private void controlPlayers() { - if (targets.isEmpty()) { - return; - } - - for (UUID controllerUUID : targets.keySet()) { - final Player controller = Bukkit.getPlayer(controllerUUID); - final Player target = getTarget(controllerUUID); - + manager.forEach((controller, target) -> { for (int i = 0; i < controller.getInventory().getSize(); i++) { if (controller.getInventory().getItem(i) != null) { if (!controller.getInventory().getItem(i).equals( @@ -178,7 +144,7 @@ private void controlPlayers() { particles ) ); - } + }); } private void checkVisibility() { @@ -197,7 +163,9 @@ private void checkVisibility() { continue; } + iterator.remove(); final Player controller = Bukkit.getPlayer(playerUUID); + if (controller == null) return; for (Player onlinePlayer: Bukkit.getOnlinePlayers()) { onlinePlayer.showPlayer(JavaPlugin.getPlugin(Main.class), controller); @@ -212,7 +180,6 @@ private void checkVisibility() { controller.removePotionEffect(PotionEffectType.INVISIBILITY); controller.sendMessage(Component.text("You are now visible")); - iterator.remove(); } } @@ -220,7 +187,7 @@ private void checkVisibility() { private void onEntityDamage(final EntityDamageEvent event) { final Entity player = event.getEntity(); - if (getTarget(player.getUniqueId()) != null) { + if (manager.hasController(player.getUniqueId())) { event.setCancelled(true); } } @@ -229,7 +196,7 @@ private void onEntityDamage(final EntityDamageEvent event) { private void onPlayerAnimation(final PlayerAnimationEvent event) { final Player player = event.getPlayer(); - if (getController(player.getUniqueId()) != null) { + if (manager.hasTarget(player.getUniqueId())) { event.setCancelled(true); } } @@ -239,7 +206,7 @@ private void onPlayerChat(final PlayerChatEvent event) { final Player player = event.getPlayer(); final UUID playerUUID = player.getUniqueId(); - if (getController(playerUUID) != null) { + if (manager.hasTarget(playerUUID)) { if (event.getMessage().startsWith(CHAT_PREFIX)) { event.setMessage(event.getMessage().substring(CHAT_PREFIX.length())); return; @@ -248,8 +215,7 @@ private void onPlayerChat(final PlayerChatEvent event) { return; } - final Player target = getTarget(playerUUID); - + final Player target = manager.getTarget(playerUUID); if (target != null) { target.chat(CHAT_PREFIX + event.getMessage()); event.setCancelled(true); @@ -260,7 +226,7 @@ private void onPlayerChat(final PlayerChatEvent event) { private void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) { final Player player = event.getPlayer(); - if (getController(player.getUniqueId()) != null) { + if (manager.hasTarget(player.getUniqueId())) { event.setCancelled(true); } } @@ -269,7 +235,7 @@ private void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) private void onPlayerDropItem(final PlayerDropItemEvent event) { final Player player = event.getPlayer(); - if (getController(player.getUniqueId()) != null) { + if (manager.hasTarget(player.getUniqueId())) { event.setCancelled(true); } } @@ -278,14 +244,15 @@ private void onPlayerDropItem(final PlayerDropItemEvent event) { private void onPlayerInteract(final PlayerInteractEvent event) { final Player player = event.getPlayer(); - if (getController(player.getUniqueId()) != null) { + if (manager.hasTarget(player.getUniqueId())) { event.setCancelled(true); + return; + } - } else if ((event.getAction() == Action.LEFT_CLICK_AIR + final Player target = manager.getTarget(player.getUniqueId()); + if ((event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) - && getTarget(player.getUniqueId()) != null) { - final Player target = getTarget(player.getUniqueId()); - + && target != null) { if (event.getHand() == EquipmentSlot.HAND) { target.swingMainHand(); } else if (event.getHand() == EquipmentSlot.OFF_HAND) { @@ -298,54 +265,37 @@ && getTarget(player.getUniqueId()) != null) { private void onPlayerMove(final PlayerMoveEvent event) { final Player player = event.getPlayer(); - if (getController(player.getUniqueId()) != null) { + if (manager.hasTarget(player.getUniqueId())) { event.setCancelled(true); } } @EventHandler private void onPlayerQuit(final PlayerQuitEvent event) { - final Player player = event.getPlayer(); - final UUID playerUUID = player.getUniqueId(); - final Player controller = getController(playerUUID); + final UUID uuid = event.getPlayer().getUniqueId(); + if (manager.removeController(uuid) != null) return; + final Player controller = manager.removeTarget(uuid); if (controller != null) { - /* - Target disconnects - */ - removeTarget(controller.getUniqueId()); - removeController(playerUUID); scheduleVisibility(controller.getUniqueId()); controller.sendMessage(Component.text("The player you were controlling has " + "disconnected. You are invisible for 10 seconds.")); - return; - } - - final Player target = getTarget(playerUUID); - - if (target != null) { - /* - Controller disconnects - */ - removeTarget(playerUUID); - removeController(target.getUniqueId()); } } @EventHandler private void onPlayerRespawn(final PlayerRespawnEvent event) { final Player player = event.getPlayer(); - final Player controller = getController(player.getUniqueId()); + final Player controller = manager.getController(player.getUniqueId()); if (controller != null) { controller.teleportAsync(player.getLocation()); } } - @SuppressWarnings("deprecation") @EventHandler(priority = EventPriority.MONITOR) - public void onTickStart(ServerTickStartEvent event) { + public void onTickStart(final ServerTickStartEvent event) { controlPlayers(); checkVisibility(); } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 8865876..ca2f132 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: iControlU main: pw.kaboom.icontrolu.Main description: Plugin that allows players to control other players. -api-version: 1.13 +api-version: '1.18' version: master commands: diff --git a/suppressions.xml b/suppressions.xml index 8990963..23ef9a0 100644 --- a/suppressions.xml +++ b/suppressions.xml @@ -5,4 +5,6 @@ + +