From e4abbae6af086e4ea71bb20e25d29b3ed646ae83 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Wed, 27 Jul 2022 18:20:11 -0400 Subject: [PATCH 01/11] blockhunt start --- pom.xml | 2 +- .../net/tylermurphy/hideAndSeek/Main.java | 8 +++ .../hideAndSeek/command/About.java | 2 +- .../hideAndSeek/command/Debug.java | 6 +- .../hideAndSeek/configuration/Config.java | 18 +++++- .../hideAndSeek/game/Disguiser.java | 62 +++++++++++++++++++ .../hideAndSeek/game/PlayerLoader.java | 14 +++++ .../game/listener/DamageHandler.java | 8 +++ .../game/listener/DisguiseHandler.java | 46 ++++++++++++++ .../game/listener/InventoryHandler.java | 41 +++++++++++- src/main/resources/config.yml | 8 +++ src/main/resources/plugin.yml | 2 +- 12 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java create mode 100644 src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java diff --git a/pom.xml b/pom.xml index 13e6590..cb6097e 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ 4.0.0 net.tylermurphy KenshinsHideAndSeek - 1.5.1 + 1.6.0 Hide and Seek Plugin UTF-8 diff --git a/src/main/java/net/tylermurphy/hideAndSeek/Main.java b/src/main/java/net/tylermurphy/hideAndSeek/Main.java index 69619f1..dc36752 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/Main.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/Main.java @@ -24,6 +24,7 @@ import net.tylermurphy.hideAndSeek.configuration.Items; import net.tylermurphy.hideAndSeek.configuration.Localization; import net.tylermurphy.hideAndSeek.database.Database; import net.tylermurphy.hideAndSeek.game.Board; +import net.tylermurphy.hideAndSeek.game.Disguiser; import net.tylermurphy.hideAndSeek.game.PlayerLoader; import net.tylermurphy.hideAndSeek.game.util.Status; import net.tylermurphy.hideAndSeek.util.CommandHandler; @@ -56,6 +57,7 @@ public class Main extends JavaPlugin implements Listener { private final Database database; private final Board board; + private final Disguiser disguiser; private Game game; @@ -64,6 +66,7 @@ public class Main extends JavaPlugin implements Listener { onConstructed(); board = new Board(); database = new Database(); + disguiser = new Disguiser(); } protected Main(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) { @@ -71,6 +74,7 @@ public class Main extends JavaPlugin implements Listener { onConstructed(); board = new Board(); database = new Database(); + disguiser = new Disguiser(); } private void onConstructed(){ @@ -123,12 +127,14 @@ public class Main extends JavaPlugin implements Listener { private void onTick() { if(game.getStatus() == Status.ENDED) game = new Game(board); game.onTick(); + disguiser.check(); } private void registerListeners() { getServer().getPluginManager().registerEvents(new BlockedCommandHandler(), this); getServer().getPluginManager().registerEvents(new ChatHandler(), this); getServer().getPluginManager().registerEvents(new DamageHandler(), this); + getServer().getPluginManager().registerEvents(new DisguiseHandler(), this); getServer().getPluginManager().registerEvents(new InteractHandler(), this); getServer().getPluginManager().registerEvents(new InventoryHandler(), this); getServer().getPluginManager().registerEvents(new JoinLeaveHandler(), this); @@ -165,6 +171,8 @@ public class Main extends JavaPlugin implements Listener { return game; } + public Disguiser getDisguiser() { return disguiser; } + public boolean supports(int v){ return version >= v; } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/About.java b/src/main/java/net/tylermurphy/hideAndSeek/command/About.java index e36ee84..a4eca9f 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/About.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/About.java @@ -26,7 +26,7 @@ public class About implements ICommand { public void execute(Player sender, String[] args) { sender.sendMessage( - String.format("%s%sHide and Seek %s(%s1.5.1%s)\n", ChatColor.AQUA, ChatColor.BOLD, ChatColor.GRAY,ChatColor.WHITE,ChatColor.GRAY) + + String.format("%s%sHide and Seek %s(%s1.6.0%s)\n", ChatColor.AQUA, ChatColor.BOLD, ChatColor.GRAY,ChatColor.WHITE,ChatColor.GRAY) + String.format("%sAuthor: %s[KenshinEto]\n", ChatColor.GRAY, ChatColor.WHITE) + String.format("%sHelp Command: %s/hs %shelp", ChatColor.GRAY, ChatColor.AQUA, ChatColor.WHITE) ); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/Debug.java b/src/main/java/net/tylermurphy/hideAndSeek/command/Debug.java index 1275ceb..7ddc72c 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/Debug.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/Debug.java @@ -31,7 +31,7 @@ public class Debug implements ICommand { } private void createMenu(){ - debugMenu = Main.getInstance().getServer().createInventory(null, 9, "Debug Menu"); + debugMenu = Main.getInstance().getServer().createInventory(null, 18, "Debug Menu"); debugMenu.setItem(0, createOption(0, XMaterial.LEATHER_CHESTPLATE.parseMaterial(), "&6Become a &lHider", 1, player -> { if(mapSaveEnabled) { if(Bukkit.getWorld(Main.getInstance().getGame().getGameWorld()) == null) Main.getInstance().getGame().getWorldLoader().loadMap(); @@ -79,6 +79,10 @@ public class Debug implements ICommand { debugMenu.setItem(8, createOption(8, Material.ENDER_PEARL, "&d&lTeleport: &fExit", 3, player -> { player.teleport(new Location(Bukkit.getWorld(exitWorld), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ())); })); + debugMenu.setItem(9, createOption(9, XMaterial.GLASS.parseMaterial(), "&dEnable Disguise", 1, PlayerLoader::openBlockHuntPicker)); + debugMenu.setItem(10, createOption(10, XMaterial.PLAYER_HEAD.parseMaterial(), "&dDisable Disguise", 1, player -> { + Main.getInstance().getDisguiser().reveal(player); + })); } private ItemStack createOption(int slow, Material material, String name, int amount, Consumer callback){ diff --git a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java index 123432d..f988d5a 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java @@ -90,7 +90,8 @@ public class Config { leaveOnEnd, mapSaveEnabled, allowNaturalCauses, - saveInventory; + saveInventory, + blockhuntEnabled; public static int minPlayers, @@ -126,6 +127,9 @@ public class Config { blockedCommands, blockedInteracts; + public static List + blockhuntBlocks; + public static String LOBBY_TITLE, GAME_TITLE, @@ -288,6 +292,18 @@ public class Config { } bungeeLeave = config.getString("leaveType") == null || config.getString("leaveType").equalsIgnoreCase("proxy"); leaveServer = config.getString("leaveServer"); + blockhuntEnabled = config.getBoolean("blockhunt.enabled"); + blockhuntBlocks = new ArrayList<>(); + tempInteracts = config.getStringList("blockhunt.blocks"); + for(String id : tempInteracts) { + Optional optional_mat = XMaterial.matchXMaterial(id); + if (optional_mat.isPresent()) { + Material mat = optional_mat.get().parseMaterial(); + if (mat != null) { + blockhuntBlocks.add(mat); + } + } + } //Leaderboard LOBBY_TITLE = leaderboard.getString("lobby.title"); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java new file mode 100644 index 0000000..b4f70ad --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java @@ -0,0 +1,62 @@ +package net.tylermurphy.hideAndSeek.game; + +import org.bukkit.Material; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.HashMap; +import java.util.Map; + +public class Disguiser { + + private final Map blocks; + + public Disguiser(){ + this.blocks = new HashMap<>(); + } + + public FallingBlock getBlock(Player player){ + return blocks.get(player); + } + + public boolean contains(FallingBlock block) { return blocks.containsValue(block); } + + public boolean disguised(Player player) { return blocks.containsKey(player); } + + public void check(){ + for(Map.Entry set : blocks.entrySet()){ + Player player = set.getKey(); + FallingBlock block = set.getValue(); + if(block.isDead()){ + block.remove(); + FallingBlock replacement = player.getLocation().getWorld().spawnFallingBlock(player.getLocation(), block.getMaterial(), (byte)0); + replacement.setGravity(false); + replacement.setDropItem(false); + blocks.put(player, replacement); + } + } + } + + public void disguise(Player player, Material material){ + if(blocks.containsKey(player)){ + FallingBlock block = blocks.get(player); + block.remove(); + } + FallingBlock block = player.getLocation().getWorld().spawnFallingBlock(player.getLocation(), material, (byte)0); + block.setGravity(false); + block.setDropItem(false); + blocks.put(player, block); + player.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 1000000, 0,false, false)); + } + + public void reveal(Player player){ + if(!blocks.containsKey(player)) return; + FallingBlock block = blocks.get(player); + block.remove(); + blocks.remove(player); + player.removePotionEffect(PotionEffectType.INVISIBILITY); + } + +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java b/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java index bd2a965..2ddfeca 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java @@ -27,9 +27,11 @@ import net.tylermurphy.hideAndSeek.configuration.Items; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -45,6 +47,9 @@ public class PlayerLoader { loadPlayer(player); player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED,1000000,5,false,false)); Titles.sendTitle(player, 10, 70, 20, ChatColor.WHITE + "" + message("HIDER_TEAM_NAME"), ChatColor.WHITE + message("HIDERS_SUBTITLE").toString()); + if(blockhuntEnabled){ + openBlockHuntPicker(player); + } } public static void loadSeeker(Player player, String gameWorld){ @@ -141,4 +146,13 @@ public class PlayerLoader { } } + public static void openBlockHuntPicker(Player player){ + int slots = ((blockhuntBlocks.size()-1)/9)*9+9; + Inventory inventory = Main.getInstance().getServer().createInventory(null, slots, "Select a Block"); + for(int i=0;i { + teleportEntity(player, block, event.getPlayer().getLocation()); + }); + } + + private void teleportEntity(Player player, FallingBlock block, Location location) { + PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.ENTITY_TELEPORT); + packet.getModifier().writeDefaults(); + packet.getIntegers().write(0, block.getEntityId()); + packet.getDoubles().write(0, location.getX()); + packet.getDoubles().write(1, location.getY()); + packet.getDoubles().write(2, location.getZ()); + try { + protocolManager.sendServerPacket(player, packet); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/InventoryHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/InventoryHandler.java index f0fb4f9..e72bea0 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/InventoryHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/InventoryHandler.java @@ -19,26 +19,29 @@ package net.tylermurphy.hideAndSeek.game.listener; +import static net.tylermurphy.hideAndSeek.configuration.Config.*; + import com.cryptomorin.xseries.XMaterial; import net.tylermurphy.hideAndSeek.Main; import net.tylermurphy.hideAndSeek.command.Debug; import net.tylermurphy.hideAndSeek.game.util.Status; +import org.bukkit.Material; 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; public class InventoryHandler implements Listener { @EventHandler(priority = EventPriority.HIGHEST) public void onInventoryClick(InventoryClickEvent event) { if (!(event.getWhoClicked() instanceof Player)) return; - - Player player = (Player) event.getWhoClicked(); checkForInventoryMove(event); checkForSpectatorTeleportMenu(event); checkForDebugMenu(event); + checkForBlockHuntMenu(event); } private void checkForInventoryMove(InventoryClickEvent event){ @@ -74,4 +77,38 @@ public class InventoryHandler implements Listener { } } + private void checkForBlockHuntMenu(InventoryClickEvent event){ + boolean test; + if(Main.getInstance().supports(14)){ + test = event.getView().getTitle().equals("Select a Block"); + } else { + test = event.getInventory().getName().equals("Select a Block"); + } + if(!test) return; + event.setCancelled(true); + Material mat = blockhuntBlocks.get(event.getRawSlot()); + if(mat == null) return; + Player player = (Player) event.getWhoClicked(); + Main.getInstance().getDisguiser().disguise(player, mat); + player.closeInventory(); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onInventoryClose(InventoryCloseEvent event){ + if (!(event.getPlayer() instanceof Player)) return; + boolean test; + if(Main.getInstance().supports(14)){ + test = event.getView().getTitle().equals("Select a Block"); + } else { + test = event.getInventory().getName().equals("Select a Block"); + } + if(!test) return; + Material mat = blockhuntBlocks.get(0); + if(mat == null) return; + Player player = (Player) event.getPlayer(); + if(Main.getInstance().getDisguiser().disguised(player)) return; + Main.getInstance().getDisguiser().disguise(player, mat); + player.closeInventory(); + } + } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index d782edb..9500859 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -124,6 +124,14 @@ databaseName: hideandseek # Thw world border starts at [size], and decreases 100 blocks every interval. # x & z are the center location. [enabled] is whenever the border is enabled. # You can choose if Hiders are warned 30 seconds before the border moves. + +# You want block hunt? We have block hunt! Just enable it below, and set the +# available blocks to pick from, and you're all set! It's that easy! +# Items are displayed in the order that they are listed below. +blockhunt: + enabled: false + blocks: [CRAFTING_TABLE, GRASS_BLOCK, DIRT, BEACON, BOOKSHELF] + worldBorder: x: 0 z: 0 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 8cd75ee..eab74ad 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: KenshinsHideAndSeek main: net.tylermurphy.hideAndSeek.Main -version: 1.5.1 +version: 1.6.0 author: KenshinEto load: STARTUP api-version: 1.13 From aa159314100c701c4a76f01c7ae8f57e86fbcab2 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Wed, 27 Jul 2022 21:15:48 -0400 Subject: [PATCH 02/11] block snapping --- .../game/listener/DisguiseHandler.java | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java index 9bc6504..e3eb341 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java @@ -15,27 +15,59 @@ import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerMoveEvent; import java.lang.reflect.InvocationTargetException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; public class DisguiseHandler implements Listener { private static final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + private final Map locations = new HashMap<>(); + private final Map times = new HashMap<>(); + @EventHandler(priority = EventPriority.HIGHEST) public void onMove(PlayerMoveEvent event) { + checkStandingStill(event.getPlayer()); FallingBlock block = Main.getInstance().getDisguiser().getBlock(event.getPlayer()); if(block == null) return; + UUID uuid = event.getPlayer().getUniqueId(); + boolean finalFixLocation = times.containsKey(uuid) && new Date().getTime()-times.get(uuid) > 1000; Bukkit.getOnlinePlayers().forEach(player -> { - teleportEntity(player, block, event.getPlayer().getLocation()); + teleportEntity(player, block, event.getPlayer().getLocation(), finalFixLocation); }); } - private void teleportEntity(Player player, FallingBlock block, Location location) { + private void checkStandingStill(Player player){ + UUID uuid = player.getUniqueId(); + Location lastLoc = locations.get(uuid); + Location currentLoc = player.getLocation(); + if(lastLoc == null) lastLoc = currentLoc; + double distance = lastLoc.distance(currentLoc); + if(distance < .05){ + if(!times.containsKey(uuid)) + times.put(uuid, new Date().getTime()); + } else { + times.remove(uuid); + } + locations.put(uuid, currentLoc); + } + + private void teleportEntity(Player player, FallingBlock block, Location location, boolean fixLocation) { PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.ENTITY_TELEPORT); packet.getModifier().writeDefaults(); packet.getIntegers().write(0, block.getEntityId()); - packet.getDoubles().write(0, location.getX()); - packet.getDoubles().write(1, location.getY()); - packet.getDoubles().write(2, location.getZ()); + if(fixLocation){ + packet.getDoubles().write(0, Math.round(location.getX()+.5)-.5); + packet.getDoubles().write(1, (double)Math.round(location.getY())); + packet.getDoubles().write(2, Math.round(location.getZ()+.5)-.5); + } else { + packet.getDoubles().write(0, location.getX()); + packet.getDoubles().write(1, location.getY()); + packet.getDoubles().write(2, location.getZ()); + } + try { protocolManager.sendServerPacket(player, packet); } catch (InvocationTargetException e) { From 361b97d4146efd6cdc5b06612e2dc499cccfce1d Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Thu, 28 Jul 2022 21:57:49 -0400 Subject: [PATCH 03/11] added ability to attack block in solid form, blocks now go solid --- .../net/tylermurphy/hideAndSeek/Main.java | 61 ++-- .../tylermurphy/hideAndSeek/game/Board.java | 2 + .../hideAndSeek/game/Disguiser.java | 67 +++-- .../hideAndSeek/game/EntityHider.java | 282 ++++++++++++++++++ .../hideAndSeek/game/PlayerLoader.java | 3 + .../game/listener/DamageHandler.java | 3 +- .../game/listener/DisguiseHandler.java | 212 ++++++++++--- .../hideAndSeek/game/util/Disguise.java | 143 +++++++++ 8 files changed, 658 insertions(+), 115 deletions(-) create mode 100644 src/main/java/net/tylermurphy/hideAndSeek/game/EntityHider.java create mode 100644 src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java diff --git a/src/main/java/net/tylermurphy/hideAndSeek/Main.java b/src/main/java/net/tylermurphy/hideAndSeek/Main.java index dc36752..9a589ae 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/Main.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/Main.java @@ -23,12 +23,9 @@ import net.tylermurphy.hideAndSeek.configuration.Config; import net.tylermurphy.hideAndSeek.configuration.Items; import net.tylermurphy.hideAndSeek.configuration.Localization; import net.tylermurphy.hideAndSeek.database.Database; -import net.tylermurphy.hideAndSeek.game.Board; -import net.tylermurphy.hideAndSeek.game.Disguiser; -import net.tylermurphy.hideAndSeek.game.PlayerLoader; +import net.tylermurphy.hideAndSeek.game.*; import net.tylermurphy.hideAndSeek.game.util.Status; import net.tylermurphy.hideAndSeek.util.CommandHandler; -import net.tylermurphy.hideAndSeek.game.Game; import net.tylermurphy.hideAndSeek.game.listener.*; import net.tylermurphy.hideAndSeek.util.PAPIExpansion; import net.tylermurphy.hideAndSeek.util.TabCompleter; @@ -55,46 +52,23 @@ public class Main extends JavaPlugin implements Listener { private static Main instance; private static int version; - private final Database database; - private final Board board; - private final Disguiser disguiser; - + private Database database; + private Board board; + private Disguiser disguiser; + private EntityHider entityHider; private Game game; - public Main() { - super(); - onConstructed(); - board = new Board(); - database = new Database(); - disguiser = new Disguiser(); - } - - protected Main(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) { - super(loader, description, dataFolder, file); - onConstructed(); - board = new Board(); - database = new Database(); - disguiser = new Disguiser(); - } - - private void onConstructed(){ - - instance = this; - - Matcher matcher = Pattern.compile("MC: \\d\\.(\\d+)").matcher(Bukkit.getVersion()); - if (matcher.find()) { - version = Integer.parseInt(matcher.group(1)); - } else { - throw new IllegalArgumentException("Failed to parse server version from: " + Bukkit.getVersion()); - } - + public void onEnable() { + Main.instance = this; Config.loadConfig(); Localization.loadLocalization(); Items.loadItems(); - } - - public void onEnable() { + this.updateVersion(); + this.board = new Board(); + this.database = new Database(); + this.disguiser = new Disguiser(); + this.entityHider = new EntityHider(this, EntityHider.Policy.BLACKLIST); this.registerListeners(); CommandHandler.registerCommands(); @@ -142,6 +116,15 @@ public class Main extends JavaPlugin implements Listener { getServer().getPluginManager().registerEvents(new PlayerHandler(), this); getServer().getPluginManager().registerEvents(new RespawnHandler(), this); } + + private void updateVersion(){ + Matcher matcher = Pattern.compile("MC: \\d\\.(\\d+)").matcher(Bukkit.getVersion()); + if (matcher.find()) { + version = Integer.parseInt(matcher.group(1)); + } else { + throw new IllegalArgumentException("Failed to parse server version from: " + Bukkit.getVersion()); + } + } public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) { return CommandHandler.handleCommand(sender, args); @@ -173,6 +156,8 @@ public class Main extends JavaPlugin implements Listener { public Disguiser getDisguiser() { return disguiser; } + public EntityHider getEntityHider() { return entityHider; } + public boolean supports(int v){ return version >= v; } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java index c6aaaf5..050faa8 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java @@ -401,6 +401,8 @@ class CustomBoard { hiderTeam.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.NEVER); seekerTeam.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.NEVER); } + hiderTeam.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER); + seekerTeam.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER); } else { if (nameTagsVisible) { hiderTeam.setNameTagVisibility(NameTagVisibility.HIDE_FOR_OTHER_TEAMS); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java index b4f70ad..a8ac441 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java @@ -1,62 +1,69 @@ package net.tylermurphy.hideAndSeek.game; +import net.tylermurphy.hideAndSeek.game.util.Disguise; +import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.BlockVector; +import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; +import java.util.Optional; +import java.util.Vector; public class Disguiser { - private final Map blocks; + private final Map disguises; public Disguiser(){ - this.blocks = new HashMap<>(); + this.disguises = new HashMap<>(); } - public FallingBlock getBlock(Player player){ - return blocks.get(player); + public Disguise getDisguise(Player player){ + return disguises.get(player); } - public boolean contains(FallingBlock block) { return blocks.containsValue(block); } + public boolean disguised(Player player) { return disguises.containsKey(player); } - public boolean disguised(Player player) { return blocks.containsKey(player); } + @Nullable + public Disguise getByEntityID(int ID){ + return disguises.values().stream().filter(disguise -> disguise.getEntityID() == ID).findFirst().orElse(null); + } + + @Nullable + public Disguise getByBlockLocation(BlockVector loc){ + return disguises.values().stream().filter(disguise -> { + if(disguise.getSolidLocation() == null) return false; + return disguise.getSolidLocation().toVector().toBlockVector() == loc; + }).findFirst().orElse(null); + } public void check(){ - for(Map.Entry set : blocks.entrySet()){ + for(Map.Entry set : disguises.entrySet()){ + Disguise disguise = set.getValue(); Player player = set.getKey(); - FallingBlock block = set.getValue(); - if(block.isDead()){ - block.remove(); - FallingBlock replacement = player.getLocation().getWorld().spawnFallingBlock(player.getLocation(), block.getMaterial(), (byte)0); - replacement.setGravity(false); - replacement.setDropItem(false); - blocks.put(player, replacement); + if(!player.isOnline()) { + disguise.remove(); + disguises.remove(player); + } else { + disguise.update(); } } } public void disguise(Player player, Material material){ - if(blocks.containsKey(player)){ - FallingBlock block = blocks.get(player); - block.remove(); + if(disguises.containsKey(player)){ + disguises.get(player).remove(); } - FallingBlock block = player.getLocation().getWorld().spawnFallingBlock(player.getLocation(), material, (byte)0); - block.setGravity(false); - block.setDropItem(false); - blocks.put(player, block); - player.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 1000000, 0,false, false)); + Disguise disguise = new Disguise(player, material); + disguises.put(player, disguise); } public void reveal(Player player){ - if(!blocks.containsKey(player)) return; - FallingBlock block = blocks.get(player); - block.remove(); - blocks.remove(player); - player.removePotionEffect(PotionEffectType.INVISIBILITY); + if(disguises.containsKey(player)) + disguises.get(player).remove(); + disguises.remove(player); } } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/EntityHider.java b/src/main/java/net/tylermurphy/hideAndSeek/game/EntityHider.java new file mode 100644 index 0000000..9dcb0ab --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/EntityHider.java @@ -0,0 +1,282 @@ +package net.tylermurphy.hideAndSeek.game; + +import static com.comphenix.protocol.PacketType.Play.Server.*; + +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.Map; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.plugin.Plugin; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.google.common.base.Preconditions; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; + +public class EntityHider implements Listener { + protected Table observerEntityMap = HashBasedTable.create(); + + private static final PacketType[] ENTITY_PACKETS = { + ENTITY_EQUIPMENT, BED, ANIMATION, NAMED_ENTITY_SPAWN, + COLLECT, SPAWN_ENTITY, SPAWN_ENTITY_LIVING, SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_EXPERIENCE_ORB, + ENTITY_VELOCITY, REL_ENTITY_MOVE, ENTITY_LOOK, ENTITY_MOVE_LOOK, ENTITY_MOVE_LOOK, + ENTITY_TELEPORT, ENTITY_HEAD_ROTATION, ENTITY_STATUS, ATTACH_ENTITY, ENTITY_METADATA, + ENTITY_EFFECT, REMOVE_ENTITY_EFFECT, BLOCK_BREAK_ANIMATION + }; + + public enum Policy { + WHITELIST, + BLACKLIST, + } + + private ProtocolManager manager; + + private final Listener bukkitListener; + private final PacketAdapter protocolListener; + + protected final Policy policy; + + public EntityHider(Plugin plugin, Policy policy) { + Preconditions.checkNotNull(plugin, "plugin cannot be NULL."); + + // Save policy + this.policy = policy; + this.manager = ProtocolLibrary.getProtocolManager(); + + // Register events and packet listener + plugin.getServer().getPluginManager().registerEvents( + bukkitListener = constructBukkit(), plugin); + manager.addPacketListener( + protocolListener = constructProtocol(plugin)); + } + + /** + * Set the visibility status of a given entity for a particular observer. + * @param observer - the observer player. + * @param entityID - ID of the entity that will be hidden or made visible. + * @param visible - TRUE if the entity should be made visible, FALSE if not. + * @return TRUE if the entity was visible before this method call, FALSE otherwise. + */ + protected boolean setVisibility(Player observer, int entityID, boolean visible) { + switch (policy) { + case BLACKLIST: + // Non-membership means they are visible + return !setMembership(observer, entityID, !visible); + case WHITELIST: + return setMembership(observer, entityID, visible); + default : + throw new IllegalArgumentException("Unknown policy: " + policy); + } + } + + /** + * Add or remove the given entity and observer entry from the table. + * @param observer - the player observer. + * @param entityID - ID of the entity. + * @param member - TRUE if they should be present in the table, FALSE otherwise. + * @return TRUE if they already were present, FALSE otherwise. + */ + protected boolean setMembership(Player observer, int entityID, boolean member) { + if (member) { + return observerEntityMap.put(observer.getEntityId(), entityID, true) != null; + } else { + return observerEntityMap.remove(observer.getEntityId(), entityID) != null; + } + } + + /** + * Determine if the given entity and observer is present in the table. + * @param observer - the player observer. + * @param entityID - ID of the entity. + * @return TRUE if they are present, FALSE otherwise. + */ + protected boolean getMembership(Player observer, int entityID) { + return observerEntityMap.contains(observer.getEntityId(), entityID); + } + + /** + * Determine if a given entity is visible for a particular observer. + * @param observer - the observer player. + * @param entityID - ID of the entity that we are testing for visibility. + * @return TRUE if the entity is visible, FALSE otherwise. + */ + protected boolean isVisible(Player observer, int entityID) { + // If we are using a whitelist, presence means visibility - if not, the opposite is the case + boolean presence = getMembership(observer, entityID); + + return (policy == Policy.WHITELIST) == presence; + } + + /** + * Remove the given entity from the underlying map. + * @param entity - the entity to remove. + */ + protected void removeEntity(Entity entity) { + int entityID = entity.getEntityId(); + + for (Map maps : observerEntityMap.rowMap().values()) { + maps.remove(entityID); + } + } + + /** + * Invoked when a player logs out. + * @param player - the player that jused logged out. + */ + protected void removePlayer(Player player) { + // Cleanup + observerEntityMap.rowMap().remove(player.getEntityId()); + } + + /** + * Construct the Bukkit event listener. + * @return Our listener. + */ + private Listener constructBukkit() { + return new Listener() { + @EventHandler + public void onEntityDeath(EntityDeathEvent e) { + removeEntity(e.getEntity()); + } + + @EventHandler + public void onChunkUnload(ChunkUnloadEvent e) { + for (Entity entity : e.getChunk().getEntities()) { + removeEntity(entity); + } + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent e) { + removePlayer(e.getPlayer()); + } + }; + } + + /** + * Construct the packet listener that will be used to intercept every entity-related packet. + * @param plugin - the parent plugin. + * @return The packet listener. + */ + private PacketAdapter constructProtocol(Plugin plugin) { + return new PacketAdapter(plugin, ENTITY_PACKETS) { + @Override + public void onPacketSending(PacketEvent event) { + int entityID = event.getPacket().getIntegers().read(0); + + // See if this packet should be cancelled + if (!isVisible(event.getPlayer(), entityID)) { + event.setCancelled(true); + } + } + }; + } + + /** + * Toggle the visibility status of an entity for a player. + *

+ * If the entity is visible, it will be hidden. If it is hidden, it will become visible. + * @param observer - the player observer. + * @param entity - the entity to toggle. + * @return TRUE if the entity was visible before, FALSE otherwise. + */ + public final boolean toggleEntity(Player observer, Entity entity) { + if (isVisible(observer, entity.getEntityId())) { + return hideEntity(observer, entity); + } else { + return !showEntity(observer, entity); + } + } + + /** + * Allow the observer to see an entity that was previously hidden. + * @param observer - the observer. + * @param entity - the entity to show. + * @return TRUE if the entity was hidden before, FALSE otherwise. + */ + public final boolean showEntity(Player observer, Entity entity) { + validate(observer, entity); + boolean hiddenBefore = !setVisibility(observer, entity.getEntityId(), true); + + // Resend packets + if (manager != null && hiddenBefore) { + manager.updateEntity(entity, Arrays.asList(observer)); + } + return hiddenBefore; + } + + /** + * Prevent the observer from seeing a given entity. + * @param observer - the player observer. + * @param entity - the entity to hide. + * @return TRUE if the entity was previously visible, FALSE otherwise. + */ + public final boolean hideEntity(Player observer, Entity entity) { + validate(observer, entity); + boolean visibleBefore = setVisibility(observer, entity.getEntityId(), false); + + if (visibleBefore) { + PacketContainer destroyEntity = new PacketContainer(ENTITY_DESTROY); + try { + destroyEntity.getIntegerArrays().write(0, new int[]{entity.getEntityId()}); + } catch (Exception e){ return false; } + // Make the entity disappear + try { + manager.sendServerPacket(observer, destroyEntity); + } catch (InvocationTargetException e) { + throw new RuntimeException("Cannot send server packet.", e); + } + } + return visibleBefore; + } + + /** + * Determine if the given entity has been hidden from an observer. + *

+ * Note that the entity may very well be occluded or out of range from the perspective + * of the observer. This method simply checks if an entity has been completely hidden + * for that observer. + * @param observer - the observer. + * @param entity - the entity that may be hidden. + * @return TRUE if the player may see the entity, FALSE if the entity has been hidden. + */ + public final boolean canSee(Player observer, Entity entity) { + validate(observer, entity); + + return isVisible(observer, entity.getEntityId()); + } + + private void validate(Player observer, Entity entity) { + Preconditions.checkNotNull(observer, "observer cannot be NULL."); + Preconditions.checkNotNull(entity, "entity cannot be NULL."); + } + + /** + * Retrieve the current visibility policy. + * @return The current visibility policy. + */ + public Policy getPolicy() { + return policy; + } + + public void close() { + if (manager != null) { + HandlerList.unregisterAll(bukkitListener); + manager.removePacketListener(protocolListener); + manager = null; + } + } +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java b/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java index 2ddfeca..0447111 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java @@ -99,6 +99,7 @@ public class PlayerLoader { public static void unloadPlayer(Player player){ player.setGameMode(GameMode.ADVENTURE); player.getInventory().clear(); + Main.getInstance().getDisguiser().reveal(player); for(PotionEffect effect : player.getActivePotionEffects()) { player.removePotionEffect(effect.getType()); } @@ -135,6 +136,8 @@ public class PlayerLoader { player.setGameMode(GameMode.ADVENTURE); player.getInventory().clear(); for(PotionEffect effect : player.getActivePotionEffects()) { + Main.getInstance().getLogger().severe(player.getName() + " " + effect.getType()); + if(effect.getType().getName().equals("INVISIBILITY") && Main.getInstance().getDisguiser().disguised(player)) continue; player.removePotionEffect(effect.getType()); } player.setFoodLevel(20); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DamageHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DamageHandler.java index f09e112..cb4cba5 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DamageHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DamageHandler.java @@ -25,10 +25,8 @@ public class DamageHandler implements Listener { @EventHandler(priority = EventPriority.HIGHEST) public void onEntityDamage(EntityDamageEvent event) { - Board board = Main.getInstance().getBoard(); Game game = Main.getInstance().getGame(); - // If you are not a player, get out of here if (!(event.getEntity() instanceof Player)) return; // Define variables @@ -46,6 +44,7 @@ public class DamageHandler implements Listener { } // Makes sure that if there was an attacking player, that the event is allowed for the game if (attacker != null) { + System.out.println(event.getFinalDamage() + " " + player.getDisplayName() + " " + attacker.getDisplayName()); // Cancel if one player is in the game but other isn't if ((board.contains(player) && !board.contains(attacker)) || (!board.contains(player) && board.contains(attacker))) { event.setCancelled(true); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java index e3eb341..af58f91 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java @@ -1,78 +1,200 @@ package net.tylermurphy.hideAndSeek.game.listener; -import com.comphenix.protocol.PacketType; +import static com.comphenix.protocol.PacketType.Play.Client.*; + import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.wrappers.BlockPosition; +import com.cryptomorin.xseries.XMaterial; import net.tylermurphy.hideAndSeek.Main; +import net.tylermurphy.hideAndSeek.game.util.Disguise; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.entity.FallingBlock; +import org.bukkit.Material; +import org.bukkit.attribute.Attribute; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.BlockVector; -import java.lang.reflect.InvocationTargetException; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.ArrayList; +import java.util.List; public class DisguiseHandler implements Listener { private static final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + private final PacketAdapter packetListener; - private final Map locations = new HashMap<>(); - private final Map times = new HashMap<>(); + public DisguiseHandler(){ + packetListener = createProtocol(); + protocolManager.addPacketListener(packetListener); + } @EventHandler(priority = EventPriority.HIGHEST) public void onMove(PlayerMoveEvent event) { - checkStandingStill(event.getPlayer()); - FallingBlock block = Main.getInstance().getDisguiser().getBlock(event.getPlayer()); - if(block == null) return; - UUID uuid = event.getPlayer().getUniqueId(); - boolean finalFixLocation = times.containsKey(uuid) && new Date().getTime()-times.get(uuid) > 1000; - Bukkit.getOnlinePlayers().forEach(player -> { - teleportEntity(player, block, event.getPlayer().getLocation(), finalFixLocation); - }); + final Disguise disguise = Main.getInstance().getDisguiser().getDisguise(event.getPlayer()); + if(disguise == null) return; + final Location lastLocation = event.getPlayer().getLocation(); + Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getInstance(), () -> { + final Location currentLocation = event.getPlayer().getLocation(); + if(lastLocation.getWorld() != currentLocation.getWorld()) return; + double distance = lastLocation.distance(currentLocation); + disguise.setSolidify(distance < .1); + }, 40L); + if(event.getFrom().distance(event.getTo()) > .1) + disguise.setSolidify(false); } - private void checkStandingStill(Player player){ - UUID uuid = player.getUniqueId(); - Location lastLoc = locations.get(uuid); - Location currentLoc = player.getLocation(); - if(lastLoc == null) lastLoc = currentLoc; - double distance = lastLoc.distance(currentLoc); - if(distance < .05){ - if(!times.containsKey(uuid)) - times.put(uuid, new Date().getTime()); +// @EventHandler(priority = EventPriority.MONITOR) +// public void onInteract(PlayerInteractEvent event) { +// Action action = event.getAction(); +// Player player = event.getPlayer(); +// Block block = event. +// } + + private PacketAdapter createProtocol(){ + return new PacketAdapter(Main.getInstance(), USE_ITEM, USE_ENTITY) { + + @Override + public void onPacketReceiving(PacketEvent event){ + PacketContainer packet = event.getPacket(); + Player player = event.getPlayer(); +// if(!Main.getInstance().getBoard().isSeeker(player)) return; + if(packet.getType() == USE_ITEM) { + System.out.print("\nUse Item: "); + BlockPosition data; + try { data = packet.getBlockPositionModifier().read(0); } + catch (Exception e) { return; } + System.out.print(data + " "); + BlockVector loc = new BlockVector(data.getX(), data.getY(), data.getZ()); + System.out.print(loc + " "); + Disguise disguise = Main.getInstance().getDisguiser().getByBlockLocation(loc); + System.out.print("FOUND"); + handleAttack(disguise, player); + } else if(packet.getType() == USE_ENTITY) { + System.out.print("\nUse Entity: "); + int id = packet.getIntegers().read(0); + System.out.print(id + " "); + Disguise disguise = Main.getInstance().getDisguiser().getByEntityID(id); + System.out.print("FOUND"); + handleAttack(disguise, player); + } + } + + }; + } + + private final List debounce = new ArrayList<>(); + + private void handleAttack(Disguise disguise, Player seeker){ + + double amount; + if(Main.getInstance().supports(9)) { + amount = seeker.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE).getValue(); } else { - times.remove(uuid); + amount = getItemDamageValue(seeker.getItemInHand(), disguise.getPlayer(), seeker); } - locations.put(uuid, currentLoc); + + if(disguise == null) return; + disguise.setSolidify(false); + if(debounce.contains(disguise.getPlayer())) return; + debounce.add(disguise.getPlayer()); + Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getInstance(), () -> { + EntityDamageByEntityEvent event = + new EntityDamageByEntityEvent(seeker, disguise.getPlayer(), EntityDamageEvent.DamageCause.ENTITY_ATTACK, amount); + event.setDamage(amount); + disguise.getPlayer().setLastDamageCause(event); + Main.getInstance().getServer().getPluginManager().callEvent(event); + if(!event.isCancelled()){ + disguise.getPlayer().damage(amount); + disguise.getPlayer().setVelocity(seeker.getLocation().getDirection().setY(.2).multiply(1)); + } + + }, 0); + Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getInstance(), () -> debounce.remove(disguise.getPlayer()), 10); } - private void teleportEntity(Player player, FallingBlock block, Location location, boolean fixLocation) { - PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.ENTITY_TELEPORT); - packet.getModifier().writeDefaults(); - packet.getIntegers().write(0, block.getEntityId()); - if(fixLocation){ - packet.getDoubles().write(0, Math.round(location.getX()+.5)-.5); - packet.getDoubles().write(1, (double)Math.round(location.getY())); - packet.getDoubles().write(2, Math.round(location.getZ()+.5)-.5); - } else { - packet.getDoubles().write(0, location.getX()); - packet.getDoubles().write(1, location.getY()); - packet.getDoubles().write(2, location.getZ()); + private int getItemDamageValue(ItemStack is, Player damaged, Player attacker) { + double damageValue = 0; + if (is != null) { + if (is.getType() == XMaterial.WOODEN_SWORD.parseMaterial()) { + damageValue = 5; + } else if (is.getType() == Material.STONE_SWORD) { + damageValue = 6; + } else if (is.getType() == Material.IRON_SWORD) { + damageValue = 7; + } else if (is.getType() == Material.DIAMOND_SWORD) { + damageValue = 8; + } else { + damageValue = 1; + } + damageValue += is.getEnchantmentLevel(Enchantment.DAMAGE_ALL); } - try { - protocolManager.sendServerPacket(player, packet); - } catch (InvocationTargetException e) { - e.printStackTrace(); + if (damaged != null) { + Inventory i = damaged.getInventory(); + Material helmet = i.getItem(39).getType(); + Material chestplate = i.getItem(40).getType(); + Material leggings = i.getItem(41).getType(); + Material boots = i.getItem(42).getType(); + if (helmet == Material.LEATHER_HELMET) + damageValue -= (0.5 / 1.5); + // value shown at bar above the health bar / 1.5 + else if (helmet == Material.CHAINMAIL_HELMET + || helmet == Material.IRON_HELMET + || helmet == Material.DIAMOND_HELMET + || helmet == XMaterial.GOLDEN_HELMET.parseMaterial()) + damageValue -= (1 / 1.5); + + if (chestplate == Material.LEATHER_CHESTPLATE) + damageValue -= (1.0); + else if (chestplate == Material.CHAINMAIL_CHESTPLATE + || chestplate == XMaterial.GOLDEN_CHESTPLATE.parseMaterial()) + damageValue -= (2.5 / 1.5); + else if (chestplate == Material.IRON_CHESTPLATE) + damageValue -= (3 / 1.5); + else if (chestplate == Material.DIAMOND_CHESTPLATE) + damageValue -= (4 / 1.5); + + if (leggings == Material.LEATHER_LEGGINGS) + damageValue -= (1 / 1.5); + else if (leggings == XMaterial.GOLDEN_LEGGINGS.parseMaterial()) + damageValue -= (1.0); + else if (leggings == Material.CHAINMAIL_LEGGINGS) + damageValue -= (2 / 1.5); + else if (leggings == Material.IRON_LEGGINGS) + damageValue -= (2.5 / 1.5); + else if (leggings == Material.DIAMOND_LEGGINGS) + damageValue -= (3 / 1.5); + + if (boots == Material.LEATHER_BOOTS + || boots == XMaterial.GOLDEN_BOOTS.parseMaterial() + || boots == Material.CHAINMAIL_BOOTS) + damageValue -= (0.5 / 1.5); + else if (boots == Material.IRON_BOOTS) + damageValue -= (1 / 1.5); + else if (boots == Material.DIAMOND_BOOTS) + damageValue -= (1.0); } + + for (PotionEffect effect : attacker.getActivePotionEffects()){ + if (effect.getType() == PotionEffectType.HARM) { + damageValue += effect.getAmplifier()*1.5; + } + } + + return (int) Math.round(Math.max(damageValue, 0.0)); } - } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java b/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java new file mode 100644 index 0000000..691037b --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java @@ -0,0 +1,143 @@ +package net.tylermurphy.hideAndSeek.game.util; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.BlockPosition; +import com.comphenix.protocol.wrappers.WrappedBlockData; +import net.tylermurphy.hideAndSeek.Main; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.InvocationTargetException; + +public class Disguise { + + private static final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + + final Player hider; + final Material material; + FallingBlock entity; + Location solidLocation; + boolean solid, solidify; + + public Disguise(Player player, Material material){ + this.hider = player; + this.material = material; + this.solid = false; + respawnEntity(); + player.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 1000000, 0,false, false)); + } + + public void remove(){ + if(entity != null) + entity.remove(); + if(solid) + sendBlockUpdate(Material.AIR); + hider.removePotionEffect(PotionEffectType.INVISIBILITY); + } + + @Nullable + public Location getSolidLocation() { + return solidLocation; + } + + public int getEntityID() { + if(entity == null) return -1; + return entity.getEntityId(); + } + + public Player getPlayer() { + return hider; + } + + public boolean isSolid(){ + return solid; + } + + public void update(){ + + if(entity == null || entity.isDead()){ + if(entity != null) entity.remove(); + respawnEntity(); + } + + if(solidify){ + if(!solid) + solidLocation = hider.getLocation().getBlock().getLocation(); + solid = true; + sendBlockUpdate(material); + } else if(solid){ + solid = false; + sendBlockUpdate(Material.AIR); + } + sendToggleFallingBlock(!solid); + sendFallingBlockUpdate(); + } + + public void setSolidify(boolean value){ + this.solidify = value; + } + + private void sendBlockUpdate(Material material){ + final PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.BLOCK_CHANGE); + packet.getModifier().writeDefaults(); + packet.getBlockPositionModifier().write(0, new BlockPosition(solidLocation.toVector())); + packet.getBlockData().write(0, WrappedBlockData.createData(material)); + Bukkit.getOnlinePlayers().forEach(receiver -> { + if(receiver == hider) return; + try { + protocolManager.sendServerPacket(receiver, packet); + } catch (InvocationTargetException ignored) {} + }); + } + + private void sendFallingBlockUpdate() { + if(entity == null || entity.isDead()){ + if(entity != null) entity.remove(); + respawnEntity(); + } + final PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.ENTITY_TELEPORT); + Location location = hider.getLocation(); + packet.getModifier().writeDefaults(); + packet.getIntegers().write(0, entity.getEntityId()); + if(solid){ + packet.getDoubles().write(0, Math.round(location.getX()+.5)-.5); + packet.getDoubles().write(1, (double)Math.round(location.getY())); + packet.getDoubles().write(2, Math.round(location.getZ()+.5)-.5); + } else { + packet.getDoubles().write(0, location.getX()); + packet.getDoubles().write(1, location.getY()); + packet.getDoubles().write(2, location.getZ()); + } + Bukkit.getOnlinePlayers().forEach(receiver -> { + try { + protocolManager.sendServerPacket(receiver, packet); + } catch (InvocationTargetException ignored) {} + }); + } + + private void sendToggleFallingBlock(boolean show){ + Bukkit.getOnlinePlayers().forEach(receiver -> { + if(receiver == hider) return; + if(show) + Main.getInstance().getEntityHider().showEntity(receiver, entity); + else + Main.getInstance().getEntityHider().hideEntity(receiver, entity); + }); + } + + private void respawnEntity(){ + entity = hider.getLocation().getWorld().spawnFallingBlock(hider.getLocation(), material, (byte)0); + entity.setGravity(false); + entity.setDropItem(false); + } + +} \ No newline at end of file From 4d737afc4f7a40e417aea6e046d61c2590a586a7 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Thu, 28 Jul 2022 22:00:31 -0400 Subject: [PATCH 04/11] stop kicking from standing ontop of hidden block --- .../hideAndSeek/game/listener/JoinLeaveHandler.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java index 5233d2e..82369c8 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java @@ -56,6 +56,10 @@ public class JoinLeaveHandler implements Listener { @EventHandler(priority = EventPriority.MONITOR) public void onKick(PlayerKickEvent event) { + if(event.getReason().equals("Flying is not enabled on this server!")){ + event.setCancelled(true); + return; + } handleLeave(event.getPlayer()); } From 055abc11bd0818c80d4c7be36f35cabd7becbebd Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Fri, 29 Jul 2022 21:49:43 -0400 Subject: [PATCH 05/11] better hitboxes for blockhunt --- .../net/tylermurphy/hideAndSeek/Main.java | 1 + .../tylermurphy/hideAndSeek/game/Board.java | 12 ++ .../hideAndSeek/game/Disguiser.java | 15 +-- .../game/listener/DisguiseHandler.java | 32 ++--- .../game/listener/MovementHandler.java | 1 + .../hideAndSeek/game/util/Disguise.java | 115 ++++++++++++------ 6 files changed, 109 insertions(+), 67 deletions(-) diff --git a/src/main/java/net/tylermurphy/hideAndSeek/Main.java b/src/main/java/net/tylermurphy/hideAndSeek/Main.java index 9a589ae..c4666df 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/Main.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/Main.java @@ -96,6 +96,7 @@ public class Main extends JavaPlugin implements Listener { Bukkit.getServer().getMessenger().unregisterOutgoingPluginChannel(this); board.cleanup(); + disguiser.cleanUp(); } private void onTick() { diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java index 050faa8..cf91c23 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java @@ -103,6 +103,9 @@ public class Board { } public void addHider(Player player) { + if(!Main.getInstance().supports(9)){ + player.spigot().setCollidesWithEntities(false); + } Hider.add(player.getUniqueId().toString()); Seeker.remove(player.getUniqueId().toString()); Spectator.remove(player.getUniqueId().toString()); @@ -110,6 +113,9 @@ public class Board { } public void addSeeker(Player player) { + if(!Main.getInstance().supports(9)){ + player.spigot().setCollidesWithEntities(false); + } Hider.remove(player.getUniqueId().toString()); Seeker.add(player.getUniqueId().toString()); Spectator.remove(player.getUniqueId().toString()); @@ -117,6 +123,9 @@ public class Board { } public void addSpectator(Player player) { + if(!Main.getInstance().supports(9)){ + player.spigot().setCollidesWithEntities(false); + } Hider.remove(player.getUniqueId().toString()); Seeker.remove(player.getUniqueId().toString()); Spectator.add(player.getUniqueId().toString()); @@ -124,6 +133,9 @@ public class Board { } public void remove(Player player) { + if(!Main.getInstance().supports(9)){ + player.spigot().setCollidesWithEntities(true); + } Hider.remove(player.getUniqueId().toString()); Seeker.remove(player.getUniqueId().toString()); Spectator.remove(player.getUniqueId().toString()); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java index a8ac441..a14827b 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java @@ -1,16 +1,12 @@ package net.tylermurphy.hideAndSeek.game; import net.tylermurphy.hideAndSeek.game.util.Disguise; -import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.util.BlockVector; import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; -import java.util.Optional; -import java.util.Vector; public class Disguiser { @@ -32,11 +28,8 @@ public class Disguiser { } @Nullable - public Disguise getByBlockLocation(BlockVector loc){ - return disguises.values().stream().filter(disguise -> { - if(disguise.getSolidLocation() == null) return false; - return disguise.getSolidLocation().toVector().toBlockVector() == loc; - }).findFirst().orElse(null); + public Disguise getByHitBoxID(int ID){ + return disguises.values().stream().filter(disguise -> disguise.getHitBoxID() == ID).findFirst().orElse(null); } public void check(){ @@ -66,4 +59,8 @@ public class Disguiser { disguises.remove(player); } + public void cleanUp() { + disguises.values().forEach(Disguise::remove); + } + } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java index af58f91..587fab9 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java @@ -65,34 +65,20 @@ public class DisguiseHandler implements Listener { // } private PacketAdapter createProtocol(){ - return new PacketAdapter(Main.getInstance(), USE_ITEM, USE_ENTITY) { + return new PacketAdapter(Main.getInstance(), USE_ENTITY) { @Override public void onPacketReceiving(PacketEvent event){ PacketContainer packet = event.getPacket(); Player player = event.getPlayer(); // if(!Main.getInstance().getBoard().isSeeker(player)) return; - if(packet.getType() == USE_ITEM) { - System.out.print("\nUse Item: "); - BlockPosition data; - try { data = packet.getBlockPositionModifier().read(0); } - catch (Exception e) { return; } - System.out.print(data + " "); - BlockVector loc = new BlockVector(data.getX(), data.getY(), data.getZ()); - System.out.print(loc + " "); - Disguise disguise = Main.getInstance().getDisguiser().getByBlockLocation(loc); - System.out.print("FOUND"); - handleAttack(disguise, player); - } else if(packet.getType() == USE_ENTITY) { - System.out.print("\nUse Entity: "); - int id = packet.getIntegers().read(0); - System.out.print(id + " "); - Disguise disguise = Main.getInstance().getDisguiser().getByEntityID(id); - System.out.print("FOUND"); - handleAttack(disguise, player); - } + int id = packet.getIntegers().read(0); + Disguise disguise = Main.getInstance().getDisguiser().getByEntityID(id); + if(disguise == null) disguise = Main.getInstance().getDisguiser().getByHitBoxID(id); + if(disguise == null) return; + event.setCancelled(true); + handleAttack(disguise, player); } - }; } @@ -100,6 +86,8 @@ public class DisguiseHandler implements Listener { private void handleAttack(Disguise disguise, Player seeker){ + if(disguise.getPlayer() == seeker) return; + double amount; if(Main.getInstance().supports(9)) { amount = seeker.getAttribute(Attribute.GENERIC_ATTACK_DAMAGE).getValue(); @@ -107,7 +95,6 @@ public class DisguiseHandler implements Listener { amount = getItemDamageValue(seeker.getItemInHand(), disguise.getPlayer(), seeker); } - if(disguise == null) return; disguise.setSolidify(false); if(debounce.contains(disguise.getPlayer())) return; debounce.add(disguise.getPlayer()); @@ -197,4 +184,5 @@ public class DisguiseHandler implements Listener { return (int) Math.round(Math.max(damageValue, 0.0)); } + } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/MovementHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/MovementHandler.java index 7a7e8ae..d38c512 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/MovementHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/MovementHandler.java @@ -22,6 +22,7 @@ public class MovementHandler implements Listener { @EventHandler(priority = EventPriority.HIGHEST) public void onMove(PlayerMoveEvent event) { + if (event.getTo() == null || event.getTo().getWorld() == null) return; checkJumping(event); checkBounds(event); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java b/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java index 691037b..330aefe 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java @@ -10,11 +10,11 @@ import net.tylermurphy.hideAndSeek.Main; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.entity.FallingBlock; -import org.bukkit.entity.Player; +import org.bukkit.entity.*; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; -import org.jetbrains.annotations.Nullable; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; import java.lang.reflect.InvocationTargetException; @@ -24,62 +24,94 @@ public class Disguise { final Player hider; final Material material; - FallingBlock entity; + FallingBlock block; + Horse hitBox; Location solidLocation; boolean solid, solidify; + static Team hidden; + + static { + if(Main.getInstance().supports(9)) { + Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard(); + hidden = board.getTeam("KenshinHideAndSeek_CollisionGroup"); + if (hidden == null) { + hidden = board.registerNewTeam("KenshinHideAndSeek_CollisionGroup"); + } + hidden.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER); + hidden.setCanSeeFriendlyInvisibles(false); + } + } public Disguise(Player player, Material material){ this.hider = player; this.material = material; this.solid = false; - respawnEntity(); + respawnFallingBlock(); player.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 1000000, 0,false, false)); + if(Main.getInstance().supports(9)) { + hidden.addEntry(player.getName()); + } else { + hider.spigot().setCollidesWithEntities(false); + } } public void remove(){ - if(entity != null) - entity.remove(); + if(block != null) + block.remove(); + if(hitBox != null){ + if(Main.getInstance().supports(9)) + hidden.removeEntry(hitBox.getUniqueId().toString()); + hitBox.remove(); + } if(solid) sendBlockUpdate(Material.AIR); hider.removePotionEffect(PotionEffectType.INVISIBILITY); - } - - @Nullable - public Location getSolidLocation() { - return solidLocation; + if(Main.getInstance().supports(9)) { + hidden.removeEntry(hider.getName()); + } else { + hider.spigot().setCollidesWithEntities(true); + } } public int getEntityID() { - if(entity == null) return -1; - return entity.getEntityId(); + if(block == null) return -1; + return block.getEntityId(); + } + + public int getHitBoxID() { + if(hitBox == null) return -1; + return hitBox.getEntityId(); } public Player getPlayer() { return hider; } - public boolean isSolid(){ - return solid; - } - public void update(){ - if(entity == null || entity.isDead()){ - if(entity != null) entity.remove(); - respawnEntity(); + if(block == null || block.isDead()){ + if(block != null) block.remove(); + respawnFallingBlock(); } if(solidify){ - if(!solid) + if(!solid) { + solid = true; solidLocation = hider.getLocation().getBlock().getLocation(); - solid = true; + respawnHotbox(); + teleportEntity(hitBox, false); + } sendBlockUpdate(material); } else if(solid){ solid = false; + if(Main.getInstance().supports(9)) + hidden.removeEntry(hitBox.getUniqueId().toString()); + hitBox.remove(); + hitBox = null; sendBlockUpdate(Material.AIR); } - sendToggleFallingBlock(!solid); - sendFallingBlockUpdate(); + toggleEntityVisibility(block, !solid); + teleportEntity(block, solid); } public void setSolidify(boolean value){ @@ -99,16 +131,12 @@ public class Disguise { }); } - private void sendFallingBlockUpdate() { - if(entity == null || entity.isDead()){ - if(entity != null) entity.remove(); - respawnEntity(); - } + private void teleportEntity(Entity entity, boolean center) { final PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.ENTITY_TELEPORT); Location location = hider.getLocation(); packet.getModifier().writeDefaults(); packet.getIntegers().write(0, entity.getEntityId()); - if(solid){ + if(center){ packet.getDoubles().write(0, Math.round(location.getX()+.5)-.5); packet.getDoubles().write(1, (double)Math.round(location.getY())); packet.getDoubles().write(2, Math.round(location.getZ()+.5)-.5); @@ -124,7 +152,8 @@ public class Disguise { }); } - private void sendToggleFallingBlock(boolean show){ + private void toggleEntityVisibility(Entity entity, boolean show){ + if(entity == null) return; Bukkit.getOnlinePlayers().forEach(receiver -> { if(receiver == hider) return; if(show) @@ -134,10 +163,24 @@ public class Disguise { }); } - private void respawnEntity(){ - entity = hider.getLocation().getWorld().spawnFallingBlock(hider.getLocation(), material, (byte)0); - entity.setGravity(false); - entity.setDropItem(false); + private void respawnFallingBlock(){ + block = hider.getLocation().getWorld().spawnFallingBlock(hider.getLocation(), material, (byte)0); + block.setGravity(false); + block.setDropItem(false); + block.setInvulnerable(true); + } + + private void respawnHotbox(){ + hitBox = (Horse) hider.getLocation().getWorld().spawnEntity(hider.getLocation().add(0, 1000, 0), EntityType.HORSE); + hitBox.setAI(false); + hitBox.setGravity(false); + hitBox.setInvulnerable(true); + hitBox.setCanPickupItems(false); + hitBox.setCollidable(false); + hitBox.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 1000000, 0,false, false)); + if(Main.getInstance().supports(9)){ + hidden.addEntry(hitBox.getUniqueId().toString()); + } } } \ No newline at end of file From a353e29246f2d86ccd771734791f525420c1cf34 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Sat, 30 Jul 2022 18:49:18 -0400 Subject: [PATCH 06/11] refactoring and blockhunt disguise bug fixes --- pom.xml | 117 ++++++++++-------- .../net/tylermurphy/hideAndSeek/Main.java | 2 - .../hideAndSeek/command/Debug.java | 12 +- .../hideAndSeek/command/SetBorder.java | 5 +- .../hideAndSeek/command/SetBounds.java | 33 +++-- .../tylermurphy/hideAndSeek/command/Top.java | 2 - .../hideAndSeek/database/Database.java | 1 + .../hideAndSeek/database/GameDataTable.java | 7 +- .../hideAndSeek/database/InventoryTable.java | 5 +- .../hideAndSeek/database/LegacyTable.java | 3 - .../hideAndSeek/database/NameDataTable.java | 4 +- .../database/util/LegacyPlayerInfo.java | 8 +- .../tylermurphy/hideAndSeek/game/Board.java | 2 + .../hideAndSeek/game/EntityHider.java | 12 +- .../tylermurphy/hideAndSeek/game/Game.java | 4 +- .../hideAndSeek/game/PlayerLoader.java | 7 +- .../game/listener/DisguiseHandler.java | 7 +- .../game/listener/InteractHandler.java | 23 ++-- .../game/listener/JoinLeaveHandler.java | 1 - .../game/listener/MovementHandler.java | 1 - .../hideAndSeek/game/util/Disguise.java | 74 +++++------ .../hideAndSeek/util/PAPIExpansion.java | 1 + .../util/packet/AbstractPacket.java | 31 +++++ .../util/packet/BlockChangePacket.java | 24 ++++ .../util/packet/EntityTeleportPacket.java | 29 +++++ .../hideAndSeek/world/VoidGenerator.java | 4 +- 26 files changed, 241 insertions(+), 178 deletions(-) create mode 100644 src/main/java/net/tylermurphy/hideAndSeek/util/packet/AbstractPacket.java create mode 100644 src/main/java/net/tylermurphy/hideAndSeek/util/packet/BlockChangePacket.java create mode 100644 src/main/java/net/tylermurphy/hideAndSeek/util/packet/EntityTeleportPacket.java diff --git a/pom.xml b/pom.xml index cb6097e..e6ff5de 100644 --- a/pom.xml +++ b/pom.xml @@ -3,71 +3,84 @@ KenshinsHideAndSeek 1.6.0 Hide and Seek Plugin - - UTF-8 - + + clean install + src/main/java + - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 8 - 8 - - org.apache.maven.plugins maven-shade-plugin 3.2.4 - - false - - - com.cryptomorin.xseries - net.tylermurphy.dependencies.xseries - - - - - com.github.cryptomorin:XSeries - org.xerial:sqlite-jdbc - org.mariadb.jdbc:mariadb-java-client - com.zaxxer:HikariCP - - - - - *:* - - META-INF/*.MF - META-INF/*.MD - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - sqlite-jdbc.properties - - - - - - META-INF/services/java.sql.Driver - - - true - package shade + + false + + + com.cryptomorin.xseries + net.tylermurphy.dependencies.xseries + + + com.zaxxer.hikari + net.tylermurphy.dependencies.hikari + + + org.ibex.nestedvm + net.tylermurphy.dependencies.nestedvm + + + org.sqlite + net.tylermurphy.dependencies.sqlite + + + + + com.github.cryptomorin:XSeries + org.xerial:sqlite-jdbc + org.mariadb.jdbc:mariadb-java-client + com.zaxxer:HikariCP + + + + + *:* + + META-INF/** + sqlite-jdbc.properties + mariadb.properties + + + + + + META-INF/services/java.sql.Driver + + + true + + + + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + + + + spigot-repo @@ -87,8 +100,14 @@ org.spigotmc spigot-api 1.13-R0.1-SNAPSHOT - jar provided + + + junit + * + + + jar com.comphenix.protocol diff --git a/src/main/java/net/tylermurphy/hideAndSeek/Main.java b/src/main/java/net/tylermurphy/hideAndSeek/Main.java index c4666df..08f1d3e 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/Main.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/Main.java @@ -34,9 +34,7 @@ import org.bukkit.Location; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.event.Listener; -import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.plugin.java.JavaPluginLoader; import org.jetbrains.annotations.NotNull; import java.io.File; diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/Debug.java b/src/main/java/net/tylermurphy/hideAndSeek/command/Debug.java index 7ddc72c..61d0c46 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/Debug.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/Debug.java @@ -73,16 +73,10 @@ public class Debug implements ICommand { } player.teleport(new Location(Bukkit.getWorld(Main.getInstance().getGame().getGameWorld()), spawnPosition.getX(), spawnPosition.getY(), spawnPosition.getZ())); })); - debugMenu.setItem(7, createOption(7, Material.ENDER_PEARL, "&d&lTeleport: &fLobby", 2, player -> { - player.teleport(new Location(Bukkit.getWorld(lobbyWorld), lobbyPosition.getX(), lobbyPosition.getY(), lobbyPosition.getZ())); - })); - debugMenu.setItem(8, createOption(8, Material.ENDER_PEARL, "&d&lTeleport: &fExit", 3, player -> { - player.teleport(new Location(Bukkit.getWorld(exitWorld), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ())); - })); + debugMenu.setItem(7, createOption(7, Material.ENDER_PEARL, "&d&lTeleport: &fLobby", 2, player -> player.teleport(new Location(Bukkit.getWorld(lobbyWorld), lobbyPosition.getX(), lobbyPosition.getY(), lobbyPosition.getZ())))); + debugMenu.setItem(8, createOption(8, Material.ENDER_PEARL, "&d&lTeleport: &fExit", 3, player -> player.teleport(new Location(Bukkit.getWorld(exitWorld), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ())))); debugMenu.setItem(9, createOption(9, XMaterial.GLASS.parseMaterial(), "&dEnable Disguise", 1, PlayerLoader::openBlockHuntPicker)); - debugMenu.setItem(10, createOption(10, XMaterial.PLAYER_HEAD.parseMaterial(), "&dDisable Disguise", 1, player -> { - Main.getInstance().getDisguiser().reveal(player); - })); + debugMenu.setItem(10, createOption(10, XMaterial.PLAYER_HEAD.parseMaterial(), "&dDisable Disguise", 1, player -> Main.getInstance().getDisguiser().reveal(player))); } private ItemStack createOption(int slow, Material material, String name, int amount, Consumer callback){ diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/SetBorder.java b/src/main/java/net/tylermurphy/hideAndSeek/command/SetBorder.java index 45e66b9..b456e6a 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/SetBorder.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/SetBorder.java @@ -68,10 +68,9 @@ public class SetBorder implements ICommand { return; } Vector vec = new Vector(); - Player player = (Player) sender; - vec.setX(player.getLocation().getBlockX()); + vec.setX(sender.getLocation().getBlockX()); vec.setY(0); - vec.setZ(player.getLocation().getBlockZ()); + vec.setZ(sender.getLocation().getBlockZ()); if (spawnPosition.distance(vec) > 100) { sender.sendMessage(errorPrefix + message("WORLDBORDER_POSITION")); return; diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/SetBounds.java b/src/main/java/net/tylermurphy/hideAndSeek/command/SetBounds.java index 90ecb28..434e4a6 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/SetBounds.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/SetBounds.java @@ -37,12 +37,11 @@ public class SetBounds implements ICommand { sender.sendMessage(errorPrefix + message("ERROR_GAME_SPAWN")); return; } - Player player = (Player) sender; - if (!player.getWorld().getName().equals(spawnWorld)) { + if (!sender.getWorld().getName().equals(spawnWorld)) { sender.sendMessage(errorPrefix + message("BOUNDS_WRONG_WORLD")); return; } - if (player.getLocation().getBlockX() == 0 || player.getLocation().getBlockZ() == 0) { + if (sender.getLocation().getBlockX() == 0 || sender.getLocation().getBlockZ() == 0) { sender.sendMessage(errorPrefix + message("NOT_AT_ZERO")); return; } @@ -51,32 +50,32 @@ public class SetBounds implements ICommand { saveMinX = 0; saveMinZ= 0; saveMaxX = 0; saveMaxZ = 0; } if (saveMaxX == 0) { - addToConfig("bounds.max.x", player.getLocation().getBlockX()); - saveMaxX = player.getLocation().getBlockX(); - } else if (saveMaxX < player.getLocation().getBlockX()) { + addToConfig("bounds.max.x", sender.getLocation().getBlockX()); + saveMaxX = sender.getLocation().getBlockX(); + } else if (saveMaxX < sender.getLocation().getBlockX()) { first = false; - addToConfig("bounds.max.x", player.getLocation().getBlockX()); + addToConfig("bounds.max.x", sender.getLocation().getBlockX()); addToConfig("bounds.min.x", saveMaxX); saveMinX = saveMaxX; - saveMaxX = player.getLocation().getBlockX(); + saveMaxX = sender.getLocation().getBlockX(); } else { first = false; - addToConfig("bounds.min.x", player.getLocation().getBlockX()); - saveMinX = player.getLocation().getBlockX(); + addToConfig("bounds.min.x", sender.getLocation().getBlockX()); + saveMinX = sender.getLocation().getBlockX(); } if (saveMaxZ == 0) { - addToConfig("bounds.max.z", player.getLocation().getBlockZ()); - saveMaxZ = player.getLocation().getBlockZ(); - } else if (saveMaxZ < player.getLocation().getBlockZ()) { + addToConfig("bounds.max.z", sender.getLocation().getBlockZ()); + saveMaxZ = sender.getLocation().getBlockZ(); + } else if (saveMaxZ < sender.getLocation().getBlockZ()) { first = false; - addToConfig("bounds.max.z", player.getLocation().getBlockZ()); + addToConfig("bounds.max.z", sender.getLocation().getBlockZ()); addToConfig("bounds.min.z", saveMaxZ); saveMinZ = saveMaxZ; - saveMaxZ = player.getLocation().getBlockZ(); + saveMaxZ = sender.getLocation().getBlockZ(); } else { first = false; - addToConfig("bounds.min.z", player.getLocation().getBlockZ()); - saveMinZ = player.getLocation().getBlockZ(); + addToConfig("bounds.min.z", sender.getLocation().getBlockZ()); + saveMinZ = sender.getLocation().getBlockZ(); } sender.sendMessage(messagePrefix + message("BOUNDS").addAmount(first ? 1 : 2)); saveConfig(); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/command/Top.java b/src/main/java/net/tylermurphy/hideAndSeek/command/Top.java index 6125a00..72a695c 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/command/Top.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/command/Top.java @@ -21,9 +21,7 @@ package net.tylermurphy.hideAndSeek.command; import net.tylermurphy.hideAndSeek.Main; import net.tylermurphy.hideAndSeek.database.util.PlayerInfo; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import java.util.List; diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/Database.java b/src/main/java/net/tylermurphy/hideAndSeek/database/Database.java index 8afc4ba..e7bfb26 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/database/Database.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/Database.java @@ -104,6 +104,7 @@ public class Database { } } + @SuppressWarnings("UnstableApiUsage") protected UUID decodeUUID(byte[] bytes) { InputStream is = new ByteArrayInputStream(bytes); ByteBuffer buffer = ByteBuffer.allocate(16); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/GameDataTable.java b/src/main/java/net/tylermurphy/hideAndSeek/database/GameDataTable.java index 929356e..8f0ddde 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/database/GameDataTable.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/GameDataTable.java @@ -200,8 +200,7 @@ public class GameDataTable { } } - protected boolean updateInfo(@NotNull byte[] uuid, int hider_wins, int seeker_wins, int hider_games, int seeker_games, int hider_kills, int seeker_kills, int hider_deaths, int seeker_deaths){ - boolean success; + protected void updateInfo(byte[] uuid, int hider_wins, int seeker_wins, int hider_games, int seeker_games, int hider_kills, int seeker_kills, int hider_deaths, int seeker_deaths){ String sql = "INSERT OR REPLACE INTO hs_data (uuid, hider_wins, seeker_wins, hider_games, seeker_games, hider_kills, seeker_kills, hider_deaths, seeker_deaths) VALUES (?,?,?,?,?,?,?,?,?)"; try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { statement.setBytes(1, uuid); @@ -214,16 +213,12 @@ public class GameDataTable { statement.setInt(8, hider_deaths); statement.setInt(9, seeker_deaths); statement.execute(); - statement.close(); - success = true; } catch (SQLException e) { Main.getInstance().getLogger().severe("SQL Error: " + e.getMessage()); e.printStackTrace(); - success = false; } finally { CACHE.remove(database.decodeUUID(uuid)); } - return success; } } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/InventoryTable.java b/src/main/java/net/tylermurphy/hideAndSeek/database/InventoryTable.java index 814ea5e..0ff2225 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/database/InventoryTable.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/InventoryTable.java @@ -58,19 +58,16 @@ public class InventoryTable { return null; } - public boolean saveInventory(@NotNull UUID uuid, @NotNull ItemStack[] itemArray) { + public void saveInventory(@NotNull UUID uuid, @NotNull ItemStack[] itemArray) { String sql = "INSERT OR REPLACE INTO hs_inventory (uuid, inventory) VALUES (?,?)"; String data = itemStackArrayToBase64(itemArray); try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { statement.setBytes(1, database.encodeUUID(uuid)); statement.setString(2, data); statement.execute(); - statement.close(); - return true; } catch (SQLException e) { Main.getInstance().getLogger().severe("SQL Error: " + e.getMessage()); e.printStackTrace(); - return false; } } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/LegacyTable.java b/src/main/java/net/tylermurphy/hideAndSeek/database/LegacyTable.java index 580c2f5..e134c22 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/database/LegacyTable.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/LegacyTable.java @@ -19,8 +19,6 @@ package net.tylermurphy.hideAndSeek.database; -import net.tylermurphy.hideAndSeek.Main; -import net.tylermurphy.hideAndSeek.database.Database; import net.tylermurphy.hideAndSeek.database.util.LegacyPlayerInfo; import java.sql.Connection; @@ -63,7 +61,6 @@ public class LegacyTable { while(resultSet.next()){ legacyPlayerInfoList.add(new LegacyPlayerInfo( resultSet.getBytes("uuid"), - resultSet.getInt("wins"), resultSet.getInt("hider_wins"), resultSet.getInt("seeker_wins"), resultSet.getInt("games_played") diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/NameDataTable.java b/src/main/java/net/tylermurphy/hideAndSeek/database/NameDataTable.java index dd32507..02d90cf 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/database/NameDataTable.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/NameDataTable.java @@ -25,7 +25,6 @@ import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.management.BufferPoolMXBean; import java.sql.*; import java.util.UUID; @@ -66,13 +65,14 @@ public class NameDataTable { e.printStackTrace(); } OfflinePlayer retry = Bukkit.getOfflinePlayer(uuid); - if(retry != null){ + if(retry != null && retry.getName() != null){ this.update(uuid, retry.getName()); return retry.getName(); } return null; } + @SuppressWarnings("deprecation") @Nullable public UUID getUUID(@NotNull String name) { String sql = "SELECT * FROM hs_names WHERE name = ?;"; diff --git a/src/main/java/net/tylermurphy/hideAndSeek/database/util/LegacyPlayerInfo.java b/src/main/java/net/tylermurphy/hideAndSeek/database/util/LegacyPlayerInfo.java index 5b59779..067ab0b 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/database/util/LegacyPlayerInfo.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/database/util/LegacyPlayerInfo.java @@ -19,19 +19,15 @@ package net.tylermurphy.hideAndSeek.database.util; -import java.util.UUID; - public class LegacyPlayerInfo { private final byte[] uniqueId; - private final int totalWins; private final int hiderWins; private final int seekerWins; private final int gamesPlayed; - public LegacyPlayerInfo(byte[] uniqueId, int totalWins, int hiderWins, int seekerWins, int gamesPlayed) { + public LegacyPlayerInfo(byte[] uniqueId, int hiderWins, int seekerWins, int gamesPlayed) { this.uniqueId = uniqueId; - this.totalWins = totalWins; this.hiderWins = hiderWins; this.seekerWins = seekerWins; this.gamesPlayed = gamesPlayed; @@ -41,8 +37,6 @@ public class LegacyPlayerInfo { return uniqueId; } - public int getTotalWins() { return totalWins; } - public int getHiderWins() { return hiderWins; } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java index cf91c23..6bf0bfb 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Board.java @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import static net.tylermurphy.hideAndSeek.configuration.Config.*; import static net.tylermurphy.hideAndSeek.configuration.Localization.message; +@SuppressWarnings("deprecation") public class Board { private final List Hider = new ArrayList<>(), Seeker = new ArrayList<>(), Spectator = new ArrayList<>(); @@ -363,6 +364,7 @@ public class Board { } +@SuppressWarnings("deprecation") class CustomBoard { private final Scoreboard board; diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/EntityHider.java b/src/main/java/net/tylermurphy/hideAndSeek/game/EntityHider.java index 9dcb0ab..8274655 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/EntityHider.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/EntityHider.java @@ -3,7 +3,7 @@ package net.tylermurphy.hideAndSeek.game; import static com.comphenix.protocol.PacketType.Play.Server.*; import java.lang.reflect.InvocationTargetException; -import java.util.Arrays; +import java.util.Collections; import java.util.Map; import org.bukkit.entity.Entity; @@ -30,9 +30,9 @@ public class EntityHider implements Listener { protected Table observerEntityMap = HashBasedTable.create(); private static final PacketType[] ENTITY_PACKETS = { - ENTITY_EQUIPMENT, BED, ANIMATION, NAMED_ENTITY_SPAWN, + ENTITY_EQUIPMENT, ANIMATION, NAMED_ENTITY_SPAWN, COLLECT, SPAWN_ENTITY, SPAWN_ENTITY_LIVING, SPAWN_ENTITY_PAINTING, SPAWN_ENTITY_EXPERIENCE_ORB, - ENTITY_VELOCITY, REL_ENTITY_MOVE, ENTITY_LOOK, ENTITY_MOVE_LOOK, ENTITY_MOVE_LOOK, + ENTITY_VELOCITY, REL_ENTITY_MOVE, ENTITY_LOOK, ENTITY_TELEPORT, ENTITY_HEAD_ROTATION, ENTITY_STATUS, ATTACH_ENTITY, ENTITY_METADATA, ENTITY_EFFECT, REMOVE_ENTITY_EFFECT, BLOCK_BREAK_ANIMATION }; @@ -193,6 +193,7 @@ public class EntityHider implements Listener { * @param entity - the entity to toggle. * @return TRUE if the entity was visible before, FALSE otherwise. */ + @SuppressWarnings("unused") public final boolean toggleEntity(Player observer, Entity entity) { if (isVisible(observer, entity.getEntityId())) { return hideEntity(observer, entity); @@ -213,7 +214,7 @@ public class EntityHider implements Listener { // Resend packets if (manager != null && hiddenBefore) { - manager.updateEntity(entity, Arrays.asList(observer)); + manager.updateEntity(entity, Collections.singletonList(observer)); } return hiddenBefore; } @@ -253,6 +254,7 @@ public class EntityHider implements Listener { * @param entity - the entity that may be hidden. * @return TRUE if the player may see the entity, FALSE if the entity has been hidden. */ + @SuppressWarnings("unused") public final boolean canSee(Player observer, Entity entity) { validate(observer, entity); @@ -268,10 +270,12 @@ public class EntityHider implements Listener { * Retrieve the current visibility policy. * @return The current visibility policy. */ + @SuppressWarnings("unused") public Policy getPolicy() { return policy; } + @SuppressWarnings("unused") public void close() { if (manager != null) { HandlerList.unregisterAll(bukkitListener); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java index 87fa4a2..b3fd457 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Game.java @@ -107,7 +107,8 @@ public class Game { public void start() { try { Optional rand = board.getPlayers().stream().skip(new Random().nextInt(board.size())).findFirst(); - String seekerName = rand.get().getName(); + Player picked = rand.orElse(board.getPlayers().get(0)); + String seekerName = picked.getName(); Player temp = Bukkit.getPlayer(seekerName); Player seeker = board.getPlayer(temp.getUniqueId()); start(seeker); @@ -210,6 +211,7 @@ public class Game { handleBungeeLeave(player); } + @SuppressWarnings("UnstableApiUsage") private void handleBungeeLeave(Player player) { if (bungeeLeave) { ByteArrayDataOutput out = ByteStreams.newDataOutput(); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java b/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java index 0447111..bd35ab5 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/PlayerLoader.java @@ -19,7 +19,6 @@ package net.tylermurphy.hideAndSeek.game; -import com.cryptomorin.xseries.XItemStack; import com.cryptomorin.xseries.messages.Titles; import net.md_5.bungee.api.ChatColor; import net.tylermurphy.hideAndSeek.Main; @@ -27,7 +26,6 @@ import net.tylermurphy.hideAndSeek.configuration.Items; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.entity.Player; @@ -40,6 +38,7 @@ import static net.tylermurphy.hideAndSeek.configuration.Config.*; import static net.tylermurphy.hideAndSeek.configuration.Config.lobbyPosition; import static net.tylermurphy.hideAndSeek.configuration.Localization.message; +@SuppressWarnings("deprecation") public class PlayerLoader { public static void loadHider(Player player, String gameWorld){ @@ -69,9 +68,7 @@ public class PlayerLoader { player.setFallDistance(0.0F); player.getInventory().setItem(flightToggleItemPosition, flightToggleItem); player.getInventory().setItem(teleportItemPosition, teleportItem); - Main.getInstance().getBoard().getPlayers().forEach(otherPlayer -> { - otherPlayer.hidePlayer(player); - }); + Main.getInstance().getBoard().getPlayers().forEach(otherPlayer -> otherPlayer.hidePlayer(player)); Titles.sendTitle(player, 10, 70, 20, ChatColor.GRAY + "" + ChatColor.BOLD + "SPECTATING", ChatColor.WHITE + message("SPECTATOR_SUBTITLE").toString()); } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java index 587fab9..50c45fb 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java @@ -7,7 +7,6 @@ import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketEvent; -import com.comphenix.protocol.wrappers.BlockPosition; import com.cryptomorin.xseries.XMaterial; import net.tylermurphy.hideAndSeek.Main; import net.tylermurphy.hideAndSeek.game.util.Disguise; @@ -27,19 +26,17 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.BlockVector; import java.util.ArrayList; import java.util.List; +@SuppressWarnings("deprecation") public class DisguiseHandler implements Listener { private static final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); - private final PacketAdapter packetListener; public DisguiseHandler(){ - packetListener = createProtocol(); - protocolManager.addPacketListener(packetListener); + protocolManager.addPacketListener(createProtocol()); } @EventHandler(priority = EventPriority.HIGHEST) diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/InteractHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/InteractHandler.java index c8dd488..3440780 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/InteractHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/InteractHandler.java @@ -22,6 +22,7 @@ import static net.tylermurphy.hideAndSeek.configuration.Config.*; import static net.tylermurphy.hideAndSeek.configuration.Config.glowPowerupItem; import static net.tylermurphy.hideAndSeek.configuration.Localization.message; +@SuppressWarnings("deprecation") public class InteractHandler implements Listener { @EventHandler(priority = EventPriority.HIGHEST) @@ -96,25 +97,21 @@ public class InteractHandler implements Listener { int amount = Main.getInstance().getBoard().getHiders().size() + Main.getInstance().getBoard().getSeekers().size(); Inventory teleportMenu = Main.getInstance().getServer().createInventory(null, 9*(((amount-1)/9)+1), ChatColor.stripColor(teleportItem.getItemMeta().getDisplayName())); List hider_lore = new ArrayList<>(); hider_lore.add(message("HIDER_TEAM_NAME").toString()); - Main.getInstance().getBoard().getHiders().forEach(hider -> { - teleportMenu.addItem(getSkull(hider, hider_lore)); - }); + Main.getInstance().getBoard().getHiders().forEach(hider -> teleportMenu.addItem(getSkull(hider, hider_lore))); List seeker_lore = new ArrayList<>(); seeker_lore.add(message("SEEKER_TEAM_NAME").toString()); - Main.getInstance().getBoard().getSeekers().forEach(seeker -> { - teleportMenu.addItem(getSkull(seeker, seeker_lore)); - }); + Main.getInstance().getBoard().getSeekers().forEach(seeker -> teleportMenu.addItem(getSkull(seeker, seeker_lore))); event.getPlayer().openInventory(teleportMenu); } } private ItemStack getSkull(Player player, List lore){ assert XMaterial.PLAYER_HEAD.parseMaterial() != null; - ItemStack playerhead = new ItemStack(XMaterial.PLAYER_HEAD.parseMaterial(), 1, (byte) 3); - SkullMeta playerheadmeta = (SkullMeta) playerhead.getItemMeta(); - playerheadmeta.setOwner(player.getName()); - playerheadmeta.setDisplayName(player.getName()); - playerheadmeta.setLore(lore); - playerhead.setItemMeta(playerheadmeta); - return playerhead; + ItemStack playerHead = new ItemStack(XMaterial.PLAYER_HEAD.parseMaterial(), 1, (byte) 3); + SkullMeta playerHeadMeta = (SkullMeta) playerHead.getItemMeta(); + playerHeadMeta.setOwner(player.getName()); + playerHeadMeta.setDisplayName(player.getName()); + playerHeadMeta.setLore(lore); + playerHead.setItemMeta(playerHeadMeta); + return playerHead; } } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java index 82369c8..6d88ebf 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/JoinLeaveHandler.java @@ -15,7 +15,6 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; import static net.tylermurphy.hideAndSeek.configuration.Config.*; import static net.tylermurphy.hideAndSeek.configuration.Config.exitPosition; diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/MovementHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/MovementHandler.java index d38c512..e6e32f6 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/MovementHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/MovementHandler.java @@ -1,6 +1,5 @@ package net.tylermurphy.hideAndSeek.game.listener; -import com.comphenix.protocol.PacketType; import com.google.common.collect.Sets; import net.tylermurphy.hideAndSeek.Main; import net.tylermurphy.hideAndSeek.game.listener.events.PlayerJumpEvent; diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java b/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java index 330aefe..b0f18a9 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java @@ -1,12 +1,8 @@ package net.tylermurphy.hideAndSeek.game.util; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.BlockPosition; -import com.comphenix.protocol.wrappers.WrappedBlockData; import net.tylermurphy.hideAndSeek.Main; +import net.tylermurphy.hideAndSeek.util.packet.BlockChangePacket; +import net.tylermurphy.hideAndSeek.util.packet.EntityTeleportPacket; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -16,17 +12,14 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Team; -import java.lang.reflect.InvocationTargetException; - +@SuppressWarnings("deprecation") public class Disguise { - private static final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); - final Player hider; final Material material; FallingBlock block; Horse hitBox; - Location solidLocation; + Location blockLocation; boolean solid, solidify; static Team hidden; @@ -64,7 +57,7 @@ public class Disguise { hitBox.remove(); } if(solid) - sendBlockUpdate(Material.AIR); + sendBlockUpdate(blockLocation, Material.AIR); hider.removePotionEffect(PotionEffectType.INVISIBILITY); if(Main.getInstance().supports(9)) { hidden.removeEntry(hider.getName()); @@ -97,18 +90,18 @@ public class Disguise { if(solidify){ if(!solid) { solid = true; - solidLocation = hider.getLocation().getBlock().getLocation(); - respawnHotbox(); - teleportEntity(hitBox, false); + blockLocation = hider.getLocation().getBlock().getLocation(); + respawnHitbox(); + teleportEntity(hitBox, true); } - sendBlockUpdate(material); + sendBlockUpdate(blockLocation, material); } else if(solid){ solid = false; if(Main.getInstance().supports(9)) hidden.removeEntry(hitBox.getUniqueId().toString()); hitBox.remove(); hitBox = null; - sendBlockUpdate(Material.AIR); + sendBlockUpdate(blockLocation, Material.AIR); } toggleEntityVisibility(block, !solid); teleportEntity(block, solid); @@ -118,38 +111,33 @@ public class Disguise { this.solidify = value; } - private void sendBlockUpdate(Material material){ - final PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.BLOCK_CHANGE); - packet.getModifier().writeDefaults(); - packet.getBlockPositionModifier().write(0, new BlockPosition(solidLocation.toVector())); - packet.getBlockData().write(0, WrappedBlockData.createData(material)); + private void sendBlockUpdate(Location location, Material material){ + BlockChangePacket packet = new BlockChangePacket(); + packet.setBlockPosition(location); + packet.setMaterial(material); Bukkit.getOnlinePlayers().forEach(receiver -> { - if(receiver == hider) return; - try { - protocolManager.sendServerPacket(receiver, packet); - } catch (InvocationTargetException ignored) {} + if(receiver.getName().equals(hider.getName())) return; + packet.send(receiver); }); } private void teleportEntity(Entity entity, boolean center) { - final PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.ENTITY_TELEPORT); - Location location = hider.getLocation(); - packet.getModifier().writeDefaults(); - packet.getIntegers().write(0, entity.getEntityId()); + EntityTeleportPacket packet = new EntityTeleportPacket(); + packet.setEntity(entity); + double x,y,z; if(center){ - packet.getDoubles().write(0, Math.round(location.getX()+.5)-.5); - packet.getDoubles().write(1, (double)Math.round(location.getY())); - packet.getDoubles().write(2, Math.round(location.getZ()+.5)-.5); + x = Math.round(hider.getLocation().getX()+.5)-.5; + y = Math.round(hider.getLocation().getY()); + z = Math.round(hider.getLocation().getZ()+.5)-.5; } else { - packet.getDoubles().write(0, location.getX()); - packet.getDoubles().write(1, location.getY()); - packet.getDoubles().write(2, location.getZ()); + x = hider.getLocation().getX(); + y = hider.getLocation().getY(); + z = hider.getLocation().getZ(); } - Bukkit.getOnlinePlayers().forEach(receiver -> { - try { - protocolManager.sendServerPacket(receiver, packet); - } catch (InvocationTargetException ignored) {} - }); + packet.setX(x); + packet.setY(y); + packet.setZ(z); + Bukkit.getOnlinePlayers().forEach(packet::send); } private void toggleEntityVisibility(Entity entity, boolean show){ @@ -164,13 +152,13 @@ public class Disguise { } private void respawnFallingBlock(){ - block = hider.getLocation().getWorld().spawnFallingBlock(hider.getLocation(), material, (byte)0); + block = hider.getLocation().getWorld().spawnFallingBlock(hider.getLocation().add(0, 1000, 0), material, (byte)0); block.setGravity(false); block.setDropItem(false); block.setInvulnerable(true); } - private void respawnHotbox(){ + private void respawnHitbox(){ hitBox = (Horse) hider.getLocation().getWorld().spawnEntity(hider.getLocation().add(0, 1000, 0), EntityType.HORSE); hitBox.setAI(false); hitBox.setGravity(false); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/util/PAPIExpansion.java b/src/main/java/net/tylermurphy/hideAndSeek/util/PAPIExpansion.java index 032deca..8e4078e 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/util/PAPIExpansion.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/util/PAPIExpansion.java @@ -36,6 +36,7 @@ public class PAPIExpansion extends PlaceholderExpansion { return true; } + @SuppressWarnings("ConstantConditions") @Override public String onRequest(OfflinePlayer player, @NotNull String params) { Database database = Main.getInstance().getDatabase(); diff --git a/src/main/java/net/tylermurphy/hideAndSeek/util/packet/AbstractPacket.java b/src/main/java/net/tylermurphy/hideAndSeek/util/packet/AbstractPacket.java new file mode 100644 index 0000000..9293beb --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/util/packet/AbstractPacket.java @@ -0,0 +1,31 @@ +package net.tylermurphy.hideAndSeek.util.packet; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketContainer; +import org.bukkit.entity.Player; + +import java.lang.reflect.InvocationTargetException; + +public class AbstractPacket { + + private static final ProtocolManager protocolManager; + static { + protocolManager = ProtocolLibrary.getProtocolManager(); + } + + protected final PacketContainer packet; + + protected AbstractPacket(PacketType type){ + packet = protocolManager.createPacket(type); + packet.getModifier().writeDefaults(); + } + + public void send(Player player){ + try { + protocolManager.sendServerPacket(player, packet); + } catch (InvocationTargetException ignored) {} + } + +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/util/packet/BlockChangePacket.java b/src/main/java/net/tylermurphy/hideAndSeek/util/packet/BlockChangePacket.java new file mode 100644 index 0000000..53f3f9c --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/util/packet/BlockChangePacket.java @@ -0,0 +1,24 @@ +package net.tylermurphy.hideAndSeek.util.packet; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.wrappers.BlockPosition; +import com.comphenix.protocol.wrappers.WrappedBlockData; +import org.bukkit.Location; +import org.bukkit.Material; +import org.jetbrains.annotations.NotNull; + +public class BlockChangePacket extends AbstractPacket { + + public BlockChangePacket(){ + super(PacketType.Play.Server.BLOCK_CHANGE); + } + + public void setBlockPosition(@NotNull Location location){ + super.packet.getBlockPositionModifier().write(0, new BlockPosition(location.toVector())); + } + + public void setMaterial(Material material){ + super.packet.getBlockData().write(0, WrappedBlockData.createData(material)); + } + +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/util/packet/EntityTeleportPacket.java b/src/main/java/net/tylermurphy/hideAndSeek/util/packet/EntityTeleportPacket.java new file mode 100644 index 0000000..b3c7734 --- /dev/null +++ b/src/main/java/net/tylermurphy/hideAndSeek/util/packet/EntityTeleportPacket.java @@ -0,0 +1,29 @@ +package net.tylermurphy.hideAndSeek.util.packet; + +import com.comphenix.protocol.PacketType; +import org.bukkit.entity.Entity; +import org.jetbrains.annotations.NotNull; + +public class EntityTeleportPacket extends AbstractPacket { + + public EntityTeleportPacket(){ + super(PacketType.Play.Server.ENTITY_TELEPORT); + } + + public void setEntity(@NotNull Entity entity){ + super.packet.getIntegers().write(0, entity.getEntityId()); + } + + public void setX(double x){ + super.packet.getDoubles().write(0, x); + } + + public void setY(double y){ + super.packet.getDoubles().write(1, y); + } + + public void setZ(double z){ + super.packet.getDoubles().write(2, z); + } + +} diff --git a/src/main/java/net/tylermurphy/hideAndSeek/world/VoidGenerator.java b/src/main/java/net/tylermurphy/hideAndSeek/world/VoidGenerator.java index cf4b062..a81aa51 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/world/VoidGenerator.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/world/VoidGenerator.java @@ -28,8 +28,10 @@ import java.util.Collections; import java.util.List; import java.util.Random; +@SuppressWarnings({"unused"}) public class VoidGenerator extends ChunkGenerator{ + // 1.14 And On public @NotNull List getDefaultPopulators(@NotNull World world) { return Collections.emptyList(); } @@ -66,7 +68,7 @@ public class VoidGenerator extends ChunkGenerator{ return true; } - // Backwards compatibility + // 1.13 And Prev public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { return createChunkData(world); } } From 911469c746d127c91e02f14dfaaa96f1d99575c6 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Mon, 1 Aug 2022 17:15:13 -0400 Subject: [PATCH 07/11] creative mode should not be attackable --- .../tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java index 50c45fb..10db324 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/listener/DisguiseHandler.java @@ -11,6 +11,7 @@ import com.cryptomorin.xseries.XMaterial; import net.tylermurphy.hideAndSeek.Main; import net.tylermurphy.hideAndSeek.game.util.Disguise; import org.bukkit.Bukkit; +import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.attribute.Attribute; @@ -73,6 +74,7 @@ public class DisguiseHandler implements Listener { Disguise disguise = Main.getInstance().getDisguiser().getByEntityID(id); if(disguise == null) disguise = Main.getInstance().getDisguiser().getByHitBoxID(id); if(disguise == null) return; + if(disguise.getPlayer().getGameMode() == GameMode.CREATIVE) return; event.setCancelled(true); handleAttack(disguise, player); } From 1a47dc680a25ba6a546fe769f227156090d30e3e Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Wed, 3 Aug 2022 20:19:41 -0400 Subject: [PATCH 08/11] load version number before config --- src/main/java/net/tylermurphy/hideAndSeek/Main.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/tylermurphy/hideAndSeek/Main.java b/src/main/java/net/tylermurphy/hideAndSeek/Main.java index 08f1d3e..4d8581f 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/Main.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/Main.java @@ -58,11 +58,12 @@ public class Main extends JavaPlugin implements Listener { public void onEnable() { Main.instance = this; + this.updateVersion(); + Config.loadConfig(); Localization.loadLocalization(); Items.loadItems(); - this.updateVersion(); this.board = new Board(); this.database = new Database(); this.disguiser = new Disguiser(); From 34ceb9f8b38f4951331deeea6c40db5a4ea8aba5 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Fri, 5 Aug 2022 22:21:51 -0400 Subject: [PATCH 09/11] upload images --- img/banner.png | Bin 0 -> 86077 bytes img/logo.png | Bin 0 -> 55406 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 img/banner.png create mode 100644 img/logo.png diff --git a/img/banner.png b/img/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..9594632a24fcdfe863e575d3eaf14bb7e2831f38 GIT binary patch literal 86077 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 literal 0 HcmV?d00001 diff --git a/img/logo.png b/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..613a6ff4b36ef4dd4ba7aefdee584b2d7df4ce2f GIT binary patch literal 55406 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 Date: Sun, 7 Aug 2022 16:39:31 -0400 Subject: [PATCH 10/11] 1.8 block and disguise hitbox not loading fix --- .../net/tylermurphy/hideAndSeek/configuration/Config.java | 2 +- .../java/net/tylermurphy/hideAndSeek/game/Disguiser.java | 6 ++++++ .../net/tylermurphy/hideAndSeek/game/util/Disguise.java | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java index f988d5a..4130ec7 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/configuration/Config.java @@ -292,7 +292,7 @@ public class Config { } bungeeLeave = config.getString("leaveType") == null || config.getString("leaveType").equalsIgnoreCase("proxy"); leaveServer = config.getString("leaveServer"); - blockhuntEnabled = config.getBoolean("blockhunt.enabled"); + blockhuntEnabled = config.getBoolean("blockhunt.enabled") && Main.getInstance().supports(9); blockhuntBlocks = new ArrayList<>(); tempInteracts = config.getStringList("blockhunt.blocks"); for(String id : tempInteracts) { diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java b/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java index a14827b..2f8cbf6 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/Disguiser.java @@ -1,5 +1,7 @@ package net.tylermurphy.hideAndSeek.game; +import static net.tylermurphy.hideAndSeek.configuration.Config.*; + import net.tylermurphy.hideAndSeek.game.util.Disguise; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -46,6 +48,10 @@ public class Disguiser { } public void disguise(Player player, Material material){ + if(!blockhuntEnabled){ + player.sendMessage(errorPrefix + "Please enable blockhunt in config.yml to enable disguises. Blockhunt does not work on 1.8"); + return; + } if(disguises.containsKey(player)){ disguises.get(player).remove(); } diff --git a/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java b/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java index b0f18a9..e29350b 100644 --- a/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java +++ b/src/main/java/net/tylermurphy/hideAndSeek/game/util/Disguise.java @@ -92,7 +92,6 @@ public class Disguise { solid = true; blockLocation = hider.getLocation().getBlock().getLocation(); respawnHitbox(); - teleportEntity(hitBox, true); } sendBlockUpdate(blockLocation, material); } else if(solid){ @@ -104,6 +103,7 @@ public class Disguise { sendBlockUpdate(blockLocation, Material.AIR); } toggleEntityVisibility(block, !solid); + teleportEntity(hitBox, true); teleportEntity(block, solid); } @@ -122,6 +122,7 @@ public class Disguise { } private void teleportEntity(Entity entity, boolean center) { + if(entity == null) return; EntityTeleportPacket packet = new EntityTeleportPacket(); packet.setEntity(entity); double x,y,z; From 81c1f0e60ba8839eabc3c2c1ccc061e252b0f301 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Sun, 7 Aug 2022 16:41:53 -0400 Subject: [PATCH 11/11] pom fix --- pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pom.xml b/pom.xml index e6ff5de..9b59f1c 100644 --- a/pom.xml +++ b/pom.xml @@ -34,10 +34,6 @@ org.ibex.nestedvm net.tylermurphy.dependencies.nestedvm - - org.sqlite - net.tylermurphy.dependencies.sqlite -