diff --git a/build.gradle b/build.gradle index b2dff2a4..466cc99b 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ println 'Compiling LibsDisguises via Gradle ver. ' + gradle.gradleVersion sourceCompatibility = '1.7' ext.spigotVersion = '1.8.8-R0.1-SNAPSHOT' -ext.disguisesVersion = '8.6.3' +ext.disguisesVersion = '8.6.4' [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java b/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java index 3ac99f1f..b4308618 100644 --- a/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java +++ b/src/main/java/me/libraryaddict/disguise/DisguiseAPI.java @@ -90,7 +90,7 @@ public class DisguiseAPI { int firstCapitalWatcher = firstCapital(watcherMethod.getName()); if (firstCapitalWatcher > 0 && method.getName().substring(firstCapitalMethod) - .equalsIgnoreCase(watcherMethod.getName().substring(firstCapitalWatcher))) { + .equalsIgnoreCase(watcherMethod.getName().substring(firstCapitalWatcher))) { Class methodParam = watcherMethod.getParameterTypes()[0]; if (methodParam == float.class || methodParam == Float.class || methodParam == Double.class) { methodParam = double.class; @@ -143,8 +143,9 @@ public class DisguiseAPI { public static void disguiseEntity(Entity entity, Disguise disguise) { // If they are trying to disguise a null entity or use a null disguise // Just return. - if (entity == null || disguise == null) + if (entity == null || disguise == null) { return; + } // The event wasn't cancelled. // If the disguise entity isn't the same as the one we are disguising if (disguise.getEntity() != entity) { @@ -192,12 +193,14 @@ public class DisguiseAPI { /** * Disguise the next entity to spawn with this disguise. This may not work however if the entity doesn't actually spawn. + * * @param disguise - * @return + * @return */ public static int disguiseNextEntity(Disguise disguise) { - if (disguise == null) + if (disguise == null) { return -1; + } if (disguise.getEntity() != null || DisguiseUtilities.getDisguises().containsValue(disguise)) { disguise = disguise.clone(); } @@ -215,6 +218,7 @@ public class DisguiseAPI { /** * Disguise this entity with this disguise + * * @param entity * @param disguise */ @@ -224,8 +228,9 @@ public class DisguiseAPI { } // You called the disguiseToAll method foolish mortal! Prepare to have your custom settings wiped!!! ((TargetedDisguise) disguise).setDisguiseTarget(TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS); - for (String observer : ((TargetedDisguise) disguise).getObservers()) + for (String observer : ((TargetedDisguise) disguise).getObservers()) { ((TargetedDisguise) disguise).removePlayer(observer); + } disguiseEntity(entity, disguise); } @@ -268,42 +273,49 @@ public class DisguiseAPI { /** * Get the disguise of a entity + * * @param disguised - * @return + * @return */ public static Disguise getDisguise(Entity disguised) { - if (disguised == null) + if (disguised == null) { return null; + } return DisguiseUtilities.getMainDisguise(disguised.getUniqueId()); } /** * Get the disguise of a entity + * * @param observer * @param disguised - * @return + * @return */ public static Disguise getDisguise(Player observer, Entity disguised) { - if (disguised == null || observer == null) + if (disguised == null || observer == null) { return null; + } return DisguiseUtilities.getDisguise(observer, disguised); } /** * Get the disguises of a entity + * * @param disguised - * @return + * @return */ public static Disguise[] getDisguises(Entity disguised) { - if (disguised == null) + if (disguised == null) { return null; + } return DisguiseUtilities.getDisguises(disguised.getUniqueId()); } /** * Get the ID of a fake disguise for a entityplayer + * * @param entityId - * @return + * @return */ @Deprecated public static int getFakeDisguise(UUID entityId) { @@ -316,8 +328,9 @@ public class DisguiseAPI { /** * Is this entity disguised + * * @param disguised - * @return + * @return */ public static boolean isDisguised(Entity disguised) { return getDisguise(disguised) != null; @@ -325,9 +338,10 @@ public class DisguiseAPI { /** * Is this entity disguised + * * @param observer * @param disguised - * @return + * @return */ public static boolean isDisguised(Player observer, Entity disguised) { return getDisguise(observer, disguised) != null; @@ -340,20 +354,20 @@ public class DisguiseAPI { public static boolean isSelfDisguised(Player player) { return DisguiseUtilities.getSelfDisguised().contains(player.getUniqueId()); } - + /** - * Returns true if the entitiy has /disguiseviewself toggled - * on. + * Returns true if the entitiy has /disguiseviewself toggled on. + * * @param entity - * @return + * @return */ public static boolean isViewSelfToggled(Entity entity) { return isDisguised(entity) ? getDisguise(entity).isSelfDisguiseVisible() : Disguise.getViewSelf().contains(entity.getUniqueId()); } /** - * Undisguise the entity. This doesn't let you cancel the UndisguiseEvent if the entity is no longer valid. Aka removed from - * the world. + * Undisguise the entity. This doesn't let you cancel the UndisguiseEvent if the entity is no longer valid. Aka removed from the world. + * * @param entity */ public static void undisguiseToAll(Entity entity) { @@ -362,12 +376,12 @@ public class DisguiseAPI { disguise.removeDisguise(); } } - + /** - * Set whether this player can see his - * own disguise or not. + * Set whether this player can see his own disguise or not. + * * @param entity - * @param toggled + * @param toggled */ public static void setViewDisguiseToggled(Entity entity, boolean toggled) { if (isDisguised(entity)) { @@ -375,8 +389,9 @@ public class DisguiseAPI { disguise.setViewSelfDisguise(toggled); } if (toggled) { - if (!Disguise.getViewSelf().contains(entity.getUniqueId())) + if (!Disguise.getViewSelf().contains(entity.getUniqueId())) { Disguise.getViewSelf().add(entity.getUniqueId()); + } } else { Disguise.getViewSelf().remove(entity.getUniqueId()); } diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java index 2d0859c7..968e10c9 100644 --- a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java +++ b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java @@ -6,6 +6,7 @@ import org.bukkit.ChatColor; import org.bukkit.configuration.ConfigurationSection; public class DisguiseConfig { + private static boolean animationEnabled; private static boolean bedEnabled; private static boolean blowDisguisesOnAttack; @@ -218,7 +219,8 @@ public class DisguiseConfig { /** * Is the velocity packets sent - * @return + * + * @return */ public static boolean isVelocitySent() { return sendVelocity; @@ -226,7 +228,8 @@ public class DisguiseConfig { /** * The default value if a player views his own disguise - * @return + * + * @return */ public static boolean isViewDisguises() { return viewSelfDisguise; @@ -408,6 +411,7 @@ public class DisguiseConfig { /** * Disable velocity packets being sent for w/e reason. Maybe you want every ounce of performance you can get? + * * @param sendVelocityPackets */ public static void setVelocitySent(boolean sendVelocityPackets) { diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseListener.java b/src/main/java/me/libraryaddict/disguise/DisguiseListener.java index e1dda602..d095e518 100644 --- a/src/main/java/me/libraryaddict/disguise/DisguiseListener.java +++ b/src/main/java/me/libraryaddict/disguise/DisguiseListener.java @@ -38,6 +38,7 @@ import org.bukkit.scheduler.BukkitRunnable; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.PacketContainer; +import org.bukkit.entity.Arrow; import org.bukkit.scheduler.BukkitTask; public class DisguiseListener implements Listener { @@ -66,10 +67,12 @@ public class DisguiseListener implements Listener { Bukkit.getScheduler().runTask(plugin, new Runnable() { @Override public void run() { - for (Player p : Bukkit.getOnlinePlayers()) - if (p.hasPermission(DisguiseConfig.getUpdateNotificationPermission())) + for (Player p : Bukkit.getOnlinePlayers()) { + if (p.hasPermission(DisguiseConfig.getUpdateNotificationPermission())) { p.sendMessage(String.format(DisguiseConfig.getUpdateMessage(), currentVersion, latestVersion)); + } + } } }); } @@ -81,7 +84,7 @@ public class DisguiseListener implements Listener { // 20 ticks * 60 seconds * 60 minutes * 6 hours } } - + public void cleanup() { for (BukkitRunnable r : disguiseRunnable.values()) { r.cancel(); @@ -159,6 +162,8 @@ public class DisguiseListener implements Listener { /** * Most likely faster if we don't bother doing checks if he sees a player disguise + * + * @param event */ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onMove(PlayerMoveEvent event) { @@ -266,8 +271,9 @@ public class DisguiseListener implements Listener { if (DisguiseAPI.isDisguised(entity)) { DisguiseAPI.undisguiseToAll(entity); p.sendMessage(ChatColor.RED + "Undisguised " + (entity instanceof Player ? "" : "the ") + entityName); - } else + } else { p.sendMessage(ChatColor.RED + (entity instanceof Player ? "" : "the") + entityName + " isn't disguised!"); + } } } } @@ -278,20 +284,23 @@ public class DisguiseListener implements Listener { if (DisguiseConfig.isMonstersIgnoreDisguises() && event.getTarget() != null && event.getTarget() instanceof Player && DisguiseAPI.isDisguised(event.getTarget())) { switch (event.getReason()) { - case TARGET_ATTACKED_ENTITY: - case TARGET_ATTACKED_OWNER: - case OWNER_ATTACKED_TARGET: - case CUSTOM: - break; - default: - event.setCancelled(true); - break; + case TARGET_ATTACKED_ENTITY: + case TARGET_ATTACKED_OWNER: + case OWNER_ATTACKED_TARGET: + case CUSTOM: + break; + default: + event.setCancelled(true); + break; } } } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onTeleport(final PlayerTeleportEvent event) { + if (!DisguiseAPI.isDisguised(event.getPlayer())) { + return; + } Location to = event.getTo(); Location from = event.getFrom(); if (DisguiseConfig.isBedPacketsEnabled()) { @@ -301,7 +310,7 @@ public class DisguiseListener implements Listener { int z2 = (int) Math.floor(from.getZ() / 16D) - 17; if (x1 - (x1 % 8) != x2 - (x2 % 8) || z1 - (z1 % 8) != z2 - (z2 % 8)) { chunkMove(event.getPlayer(), null, from); - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + Bukkit.getScheduler().runTask(plugin, new Runnable() { @Override public void run() { if (!event.isCancelled()) { @@ -318,6 +327,17 @@ public class DisguiseListener implements Listener { for (Disguise disguise : DisguiseAPI.getDisguises(event.getPlayer())) { disguise.removeDisguise(); } + } else { + //Stupid hack to fix worldswitch invisibility bug + final boolean viewSelfToggled = DisguiseAPI.isViewSelfToggled(event.getPlayer()); + final Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer()); + disguise.setViewSelfDisguise(!viewSelfToggled); + Bukkit.getScheduler().runTaskLater(plugin, new Runnable() { + @Override + public void run() { + disguise.setViewSelfDisguise(viewSelfToggled); + } + }, 20L); //I wish I could use lambdas here, so badly } } @@ -347,6 +367,9 @@ public class DisguiseListener implements Listener { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onWorldSwitch(final PlayerChangedWorldEvent event) { + if (!DisguiseAPI.isDisguised(event.getPlayer())) { + return; + } if (DisguiseConfig.isBedPacketsEnabled()) { chunkMove(event.getPlayer(), event.getPlayer().getLocation(), null); } diff --git a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java index 18c0b5c1..c2353f3f 100644 --- a/src/main/java/me/libraryaddict/disguise/LibsDisguises.java +++ b/src/main/java/me/libraryaddict/disguise/LibsDisguises.java @@ -37,7 +37,7 @@ import me.libraryaddict.disguise.utilities.Metrics; import org.bukkit.event.HandlerList; public class LibsDisguises extends JavaPlugin { - + public static LibsDisguises instance; //I'm sorry Sun MicroSystems and all mighty Java God private DisguiseListener listener; @@ -69,21 +69,21 @@ public class LibsDisguises extends JavaPlugin { try { Metrics metrics = new Metrics(this); metrics.start(); - } catch (IOException e) {} + } catch (IOException e) { + } } - + /** * Reloads the config with new config options. */ public void reload() { HandlerList.unregisterAll(listener); reloadConfig(); - DisguiseConfig.initConfig(getConfig()); + DisguiseConfig.initConfig(getConfig()); } /** - * Here we create a nms entity for each disguise. Then grab their default values in their datawatcher. Then their sound volume - * for mob noises. As well as setting their watcher class and entity size. + * Here we create a nms entity for each disguise. Then grab their default values in their datawatcher. Then their sound volume for mob noises. As well as setting their watcher class and entity size. */ private void registerValues() { for (DisguiseType disguiseType : DisguiseType.values()) { @@ -93,37 +93,37 @@ public class LibsDisguises extends JavaPlugin { Class watcherClass; try { switch (disguiseType) { - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - watcherClass = MinecartWatcher.class; - break; - case DONKEY: - case MULE: - case UNDEAD_HORSE: - case SKELETON_HORSE: - watcherClass = HorseWatcher.class; - break; - case ZOMBIE_VILLAGER: - case PIG_ZOMBIE: - watcherClass = ZombieWatcher.class; - break; - case MAGMA_CUBE: - watcherClass = SlimeWatcher.class; - break; - case ELDER_GUARDIAN: - watcherClass = GuardianWatcher.class; - break; - case ENDERMITE: - watcherClass = LivingWatcher.class; - break; - default: - watcherClass = Class.forName("me.libraryaddict.disguise.disguisetypes.watchers." - + toReadable(disguiseType.name()) + "Watcher"); - break; + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + watcherClass = MinecartWatcher.class; + break; + case DONKEY: + case MULE: + case UNDEAD_HORSE: + case SKELETON_HORSE: + watcherClass = HorseWatcher.class; + break; + case ZOMBIE_VILLAGER: + case PIG_ZOMBIE: + watcherClass = ZombieWatcher.class; + break; + case MAGMA_CUBE: + watcherClass = SlimeWatcher.class; + break; + case ELDER_GUARDIAN: + watcherClass = GuardianWatcher.class; + break; + case ENDERMITE: + watcherClass = LivingWatcher.class; + break; + default: + watcherClass = Class.forName("me.libraryaddict.disguise.disguisetypes.watchers." + + toReadable(disguiseType.name()) + "Watcher"); + break; } } catch (ClassNotFoundException ex) { // There is no explicit watcher for this entity. @@ -148,45 +148,45 @@ public class LibsDisguises extends JavaPlugin { } String nmsEntityName = toReadable(disguiseType.name()); switch (disguiseType) { - case WITHER_SKELETON: - case ZOMBIE_VILLAGER: - case DONKEY: - case MULE: - case UNDEAD_HORSE: - case SKELETON_HORSE: - continue; - case PRIMED_TNT: - nmsEntityName = "TNTPrimed"; - break; - case MINECART_TNT: - nmsEntityName = "MinecartTNT"; - break; - case MINECART: - nmsEntityName = "MinecartRideable"; - break; - case FIREWORK: - nmsEntityName = "Fireworks"; - break; - case SPLASH_POTION: - nmsEntityName = "Potion"; - break; - case GIANT: - nmsEntityName = "GiantZombie"; - break; - case DROPPED_ITEM: - nmsEntityName = "Item"; - break; - case FIREBALL: - nmsEntityName = "LargeFireball"; - break; - case LEASH_HITCH: - nmsEntityName = "Leash"; - break; - case ELDER_GUARDIAN: - nmsEntityName = "Guardian"; - break; - default: - break; + case WITHER_SKELETON: + case ZOMBIE_VILLAGER: + case DONKEY: + case MULE: + case UNDEAD_HORSE: + case SKELETON_HORSE: + continue; + case PRIMED_TNT: + nmsEntityName = "TNTPrimed"; + break; + case MINECART_TNT: + nmsEntityName = "MinecartTNT"; + break; + case MINECART: + nmsEntityName = "MinecartRideable"; + break; + case FIREWORK: + nmsEntityName = "Fireworks"; + break; + case SPLASH_POTION: + nmsEntityName = "Potion"; + break; + case GIANT: + nmsEntityName = "GiantZombie"; + break; + case DROPPED_ITEM: + nmsEntityName = "Item"; + break; + case FIREBALL: + nmsEntityName = "LargeFireball"; + break; + case LEASH_HITCH: + nmsEntityName = "Leash"; + break; + case ELDER_GUARDIAN: + nmsEntityName = "Guardian"; + break; + default: + break; } try { if (nmsEntityName.equalsIgnoreCase("Unknown")) { diff --git a/src/main/java/me/libraryaddict/disguise/commands/DisguiseCloneCommand.java b/src/main/java/me/libraryaddict/disguise/commands/DisguiseCloneCommand.java index b603bb49..2bfb580f 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/DisguiseCloneCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/DisguiseCloneCommand.java @@ -43,7 +43,7 @@ public class DisguiseCloneCommand extends BaseDisguiseCommand { return true; } } - LibsDisguises.instance.getListener().setDisguiseClone(sender.getName(), new Boolean[] { doEquipment, doSneak, doSprint }); + LibsDisguises.instance.getListener().setDisguiseClone(sender.getName(), new Boolean[]{doEquipment, doSneak, doSprint}); sender.sendMessage(ChatColor.RED + "Right click a entity in the next " + DisguiseConfig.getDisguiseCloneExpire() + " seconds to grab the disguise reference!"); } else { diff --git a/src/main/java/me/libraryaddict/disguise/commands/DisguiseCommand.java b/src/main/java/me/libraryaddict/disguise/commands/DisguiseCommand.java index 9089d00d..c17eb9bc 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/DisguiseCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/DisguiseCommand.java @@ -62,10 +62,12 @@ public class DisguiseCommand extends BaseDisguiseCommand { sender.sendMessage(ChatColor.DARK_GREEN + "Choose a disguise to become the disguise!"); sender.sendMessage(ChatColor.DARK_GREEN + "You can use the disguises: " + ChatColor.GREEN + StringUtils.join(allowedDisguises, ChatColor.RED + ", " + ChatColor.GREEN)); - if (allowedDisguises.contains("player")) + if (allowedDisguises.contains("player")) { sender.sendMessage(ChatColor.DARK_GREEN + "/disguise player "); + } sender.sendMessage(ChatColor.DARK_GREEN + "/disguise "); - if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block")) + if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block")) { sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseplayer "); + } } } diff --git a/src/main/java/me/libraryaddict/disguise/commands/DisguiseEntityCommand.java b/src/main/java/me/libraryaddict/disguise/commands/DisguiseEntityCommand.java index f225200c..429ec01f 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/DisguiseEntityCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/DisguiseEntityCommand.java @@ -42,6 +42,7 @@ public class DisguiseEntityCommand extends BaseDisguiseCommand { /** * Send the player the information + * * @param sender * @param map */ @@ -51,11 +52,13 @@ public class DisguiseEntityCommand extends BaseDisguiseCommand { sender.sendMessage(ChatColor.DARK_GREEN + "Choose a disguise then right click a entity to disguise it!"); sender.sendMessage(ChatColor.DARK_GREEN + "You can use the disguises: " + ChatColor.GREEN + StringUtils.join(allowedDisguises, ChatColor.RED + ", " + ChatColor.GREEN)); - if (allowedDisguises.contains("player")) + if (allowedDisguises.contains("player")) { sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseentity player "); + } sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseentity "); - if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block")) + if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block")) { sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseentity "); + } } } diff --git a/src/main/java/me/libraryaddict/disguise/commands/DisguiseHelpCommand.java b/src/main/java/me/libraryaddict/disguise/commands/DisguiseHelpCommand.java index 25b7c2a8..ddb2479f 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/DisguiseHelpCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/DisguiseHelpCommand.java @@ -22,7 +22,9 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; public class DisguiseHelpCommand extends BaseDisguiseCommand { + private class EnumHelp { + private String enumDescription; private String enumName; private String[] enums; @@ -81,38 +83,39 @@ public class DisguiseHelpCommand extends BaseDisguiseCommand { try { enumHelp.add(new EnumHelp("HorseColor", "Horse colors", ChatColor.RED + "/disguisehelp HorseColors " + ChatColor.GREEN + "- View all the colors you can use for a horses color", (Enum[]) Class.forName( - "org.bukkit.entity.Horse$Color").getEnumConstants())); + "org.bukkit.entity.Horse$Color").getEnumConstants())); } catch (Exception ex) { } try { enumHelp.add(new EnumHelp("HorseStyle", "Horse styles", ChatColor.RED + "/disguisehelp HorseStyles " + ChatColor.GREEN + "- View all the styles you can use for a horses style", (Enum[]) Class.forName( - "org.bukkit.entity.Horse$Style").getEnumConstants())); + "org.bukkit.entity.Horse$Style").getEnumConstants())); } catch (Exception ex) { } try { enumHelp.add(new EnumHelp("OcelotType", "Ocelot types", ChatColor.RED + "/disguisehelp OcelotTypes " + ChatColor.GREEN + "- View all the ocelot types you can use for ocelots", (Enum[]) Class.forName( - "org.bukkit.entity.Ocelot$Type").getEnumConstants())); + "org.bukkit.entity.Ocelot$Type").getEnumConstants())); } catch (Exception ex) { } try { ArrayList enumReturns = new ArrayList<>(); for (PotionEffectType potionType : PotionEffectType.values()) { - if (potionType != null) + if (potionType != null) { enumReturns.add(toReadable(potionType.getName()) + ChatColor.RED + "(" + ChatColor.GREEN + potionType.getId() + ChatColor.RED + ")"); + } } enumHelp.add(new EnumHelp("PotionEffect", "PotionEffect", ChatColor.RED + "/disguisehelp PotionEffect " + ChatColor.GREEN + "- View all the potion effects you can set", enumReturns.toArray(new String[enumReturns - .size()]))); + .size()]))); } catch (Exception ex) { ex.printStackTrace(System.out); } try { enumHelp.add(new EnumHelp("Profession", "Villager professions", ChatColor.RED + "/disguisehelp Professions " + ChatColor.GREEN + "- View all the professions you can set on a villager", (Enum[]) Class.forName( - "org.bukkit.entity.Villager$Profession").getEnumConstants())); + "org.bukkit.entity.Villager$Profession").getEnumConstants())); } catch (Exception ex) { } enumHelp.add(new EnumHelp("Direction", "Directions", ChatColor.RED + "/disguisehelp Directions " + ChatColor.GREEN @@ -123,7 +126,7 @@ public class DisguiseHelpCommand extends BaseDisguiseCommand { @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { - for (String node : new String[] { "disguise", "disguiseradius", "disguiseentity", "disguiseplayer" }) { + for (String node : new String[]{"disguise", "disguiseradius", "disguiseentity", "disguiseplayer"}) { HashMap, Boolean>> permMap = getPermissions(sender, "libsdisguises." + node + "."); if (!permMap.isEmpty()) { @@ -273,8 +276,9 @@ public class DisguiseHelpCommand extends BaseDisguiseCommand { public String toReadable(String string) { String[] split = string.split("_"); - for (int i = 0; i < split.length; i++) + for (int i = 0; i < split.length; i++) { split[i] = split[i].substring(0, 1) + split[i].substring(1).toLowerCase(); + } return StringUtils.join(split, "_"); } } diff --git a/src/main/java/me/libraryaddict/disguise/commands/DisguisePlayerCommand.java b/src/main/java/me/libraryaddict/disguise/commands/DisguisePlayerCommand.java index f6de152f..e4ebb7f9 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/DisguisePlayerCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/DisguisePlayerCommand.java @@ -85,11 +85,13 @@ public class DisguisePlayerCommand extends BaseDisguiseCommand { sender.sendMessage(ChatColor.DARK_GREEN + "Disguise another player!"); sender.sendMessage(ChatColor.DARK_GREEN + "You can use the disguises: " + ChatColor.GREEN + StringUtils.join(allowedDisguises, ChatColor.RED + ", " + ChatColor.GREEN)); - if (allowedDisguises.contains("player")) + if (allowedDisguises.contains("player")) { sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseplayer player "); + } sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseplayer "); - if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block")) + if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block")) { sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseplayer "); + } } } diff --git a/src/main/java/me/libraryaddict/disguise/commands/DisguiseRadiusCommand.java b/src/main/java/me/libraryaddict/disguise/commands/DisguiseRadiusCommand.java index 065df282..acc26f71 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/DisguiseRadiusCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/DisguiseRadiusCommand.java @@ -21,6 +21,7 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; public class DisguiseRadiusCommand extends BaseDisguiseCommand { + private int maxRadius = 30; private ArrayList validClasses = new ArrayList<>(); @@ -111,8 +112,9 @@ public class DisguiseRadiusCommand extends BaseDisguiseCommand { int disguisedEntitys = 0; int miscDisguises = 0; for (Entity entity : ((Player) sender).getNearbyEntities(radius, radius, radius)) { - if (entity == sender) + if (entity == sender) { continue; + } if (type != null ? entity.getType() == type : entityClass.isAssignableFrom(entity.getClass())) { if (disguise.isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled() && entity instanceof LivingEntity) { @@ -165,7 +167,7 @@ public class DisguiseRadiusCommand extends BaseDisguiseCommand { if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block")) { sender.sendMessage((ChatColor.DARK_GREEN + "/disguiseradius ").replace("<", - "<" + ChatColor.GREEN).replace(">", ChatColor.DARK_GREEN + ">")); + "<" + ChatColor.GREEN).replace(">", ChatColor.DARK_GREEN + ">")); } sender.sendMessage(ChatColor.DARK_GREEN + "See the EntityType's usable by " + ChatColor.GREEN + "/disguiseradius EntityTypes"); diff --git a/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java b/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java index 969c2ddd..293dd2aa 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/LibsDisguisesCommand.java @@ -11,26 +11,26 @@ public class LibsDisguisesCommand implements CommandExecutor { @Override public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { - if (args.length == 0) { - sender.sendMessage(ChatColor.DARK_GREEN - + "This server is running " - + "Lib's Disguises v." - + Bukkit.getPluginManager().getPlugin("LibsDisguises").getDescription().getVersion() - + " by libraryaddict, maintained by NavidK0.\n" - + "Use /libsdisguises reload to reload the config. All disguises will be blown by doing this."); - } else if (args.length > 0) { - if (!sender.hasPermission("libsdisguises.reload")) { - if (args[0].equalsIgnoreCase("reload")) { - LibsDisguises.instance.reload(); - sender.sendMessage(ChatColor.GREEN + "[LibsDisguises] Reloaded config."); - return true; - } else { - sender.sendMessage(ChatColor.RED + "[LibsDisguises] That command doesn't exist!"); - } + if (args.length == 0) { + sender.sendMessage(ChatColor.DARK_GREEN + + "This server is running " + + "Lib's Disguises v." + + Bukkit.getPluginManager().getPlugin("LibsDisguises").getDescription().getVersion() + + " by libraryaddict, maintained by NavidK0.\n" + + "Use /libsdisguises reload to reload the config. All disguises will be blown by doing this."); + } else if (args.length > 0) { + if (sender.hasPermission("libsdisguises.reload")) { + if (args[0].equalsIgnoreCase("reload")) { + LibsDisguises.instance.reload(); + sender.sendMessage(ChatColor.GREEN + "[LibsDisguises] Reloaded config."); + return true; } else { - sender.sendMessage(ChatColor.RED + "You are forbidden to use this command."); + sender.sendMessage(ChatColor.RED + "[LibsDisguises] That command doesn't exist!"); } + } else { + sender.sendMessage(ChatColor.RED + "You are forbidden to use this command."); } + } return true; } } diff --git a/src/main/java/me/libraryaddict/disguise/commands/UndisguiseCommand.java b/src/main/java/me/libraryaddict/disguise/commands/UndisguiseCommand.java index 38550724..25fe14c4 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/UndisguiseCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/UndisguiseCommand.java @@ -21,10 +21,12 @@ public class UndisguiseCommand implements CommandExecutor { if (DisguiseAPI.isDisguised((Entity) sender)) { DisguiseAPI.undisguiseToAll((Player) sender); sender.sendMessage(ChatColor.RED + "You are no longer disguised"); - } else + } else { sender.sendMessage(ChatColor.RED + "You are not disguised!"); - } else + } + } else { sender.sendMessage(ChatColor.RED + "You are forbidden to use this command."); + } return true; } } diff --git a/src/main/java/me/libraryaddict/disguise/commands/UndisguiseEntityCommand.java b/src/main/java/me/libraryaddict/disguise/commands/UndisguiseEntityCommand.java index 8bc52e65..7a182cb8 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/UndisguiseEntityCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/UndisguiseEntityCommand.java @@ -19,8 +19,9 @@ public class UndisguiseEntityCommand implements CommandExecutor { if (sender.hasPermission("libsdisguises.undisguiseentity")) { LibsDisguises.instance.getListener().setDisguiseEntity(sender.getName(), null); sender.sendMessage(ChatColor.RED + "Right click a disguised entity to undisguise them!"); - } else + } else { sender.sendMessage(ChatColor.RED + "You are forbidden to use this command."); + } return true; } } diff --git a/src/main/java/me/libraryaddict/disguise/commands/UndisguisePlayerCommand.java b/src/main/java/me/libraryaddict/disguise/commands/UndisguisePlayerCommand.java index 73524691..82b9a6b0 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/UndisguisePlayerCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/UndisguisePlayerCommand.java @@ -20,14 +20,18 @@ public class UndisguisePlayerCommand implements CommandExecutor { if (DisguiseAPI.isDisguised(p)) { DisguiseAPI.undisguiseToAll(p); sender.sendMessage(ChatColor.RED + "The player is no longer disguised"); - } else + } else { sender.sendMessage(ChatColor.RED + "The player is not disguised!"); - } else + } + } else { sender.sendMessage(ChatColor.RED + "Player not found"); - } else + } + } else { sender.sendMessage(ChatColor.RED + "/undisguiseplayer "); - } else + } + } else { sender.sendMessage(ChatColor.RED + "You are forbidden to use this command."); + } return true; } } diff --git a/src/main/java/me/libraryaddict/disguise/commands/UndisguiseRadiusCommand.java b/src/main/java/me/libraryaddict/disguise/commands/UndisguiseRadiusCommand.java index 5eb40ac7..a22269c6 100644 --- a/src/main/java/me/libraryaddict/disguise/commands/UndisguiseRadiusCommand.java +++ b/src/main/java/me/libraryaddict/disguise/commands/UndisguiseRadiusCommand.java @@ -10,6 +10,7 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; public class UndisguiseRadiusCommand implements CommandExecutor { + private int maxRadius = 30; public UndisguiseRadiusCommand(int maxRadius) { @@ -48,16 +49,18 @@ public class UndisguiseRadiusCommand implements CommandExecutor { } int disguisedEntitys = 0; for (Entity entity : ((Player) sender).getNearbyEntities(radius, radius, radius)) { - if (entity == sender) + if (entity == sender) { continue; + } if (DisguiseAPI.isDisguised(entity)) { DisguiseAPI.undisguiseToAll(entity); disguisedEntitys++; } } sender.sendMessage(ChatColor.RED + "Successfully undisguised " + disguisedEntitys + " entities!"); - } else + } else { sender.sendMessage(ChatColor.RED + "You are forbidden to use this command."); + } return true; } } diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/AnimalColor.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/AnimalColor.java index bf208a70..17ca6ee1 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/AnimalColor.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/AnimalColor.java @@ -1,6 +1,7 @@ package me.libraryaddict.disguise.disguisetypes; public enum AnimalColor { + BLACK(15), BLUE(11), BROWN(12), CYAN(9), GRAY(7), GREEN(13), LIGHT_BLUE(3), LIME(5), MAGENTA(2), ORANGE(1), PINK(6), PURPLE( 10), RED(14), SILVER(8), WHITE(0), YELLOW(4); diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java index 0942b7b8..f5616fd6 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java @@ -39,6 +39,7 @@ import java.util.Map; import me.libraryaddict.disguise.LibsDisguises; public abstract class Disguise { + private boolean disguiseInUse; private DisguiseType disguiseType; private Entity entity; @@ -56,24 +57,26 @@ public abstract class Disguise { private boolean viewSelfDisguise = DisguiseConfig.isViewDisguises(); private FlagWatcher watcher; private boolean showName = false; - + private static List viewSelf = new ArrayList<>(); - + @Override public abstract Disguise clone(); /** * Seems I do this method so I can make cleaner constructors on disguises.. + * * @param newType */ protected void createDisguise(DisguiseType newType) { - if (getWatcher() != null) + if (getWatcher() != null) { return; + } if (newType.getEntityType() == null) { throw new RuntimeException( "DisguiseType " - + newType - + " was used in a futile attempt to construct a disguise, but this version of craftbukkit does not have that entity"); + + newType + + " was used in a futile attempt to construct a disguise, but this version of craftbukkit does not have that entity"); } // Set the disguise type disguiseType = newType; @@ -99,16 +102,12 @@ public abstract class Disguise { // If the disguise type is a wither, set the flagwatcher value for the skeleton to a wither skeleton if (getType() == DisguiseType.WITHER_SKELETON) { getWatcher().setValue(13, (byte) 1); - } - // Else if its a zombie, but the disguise type is a zombie villager. Set the value. + } // Else if its a zombie, but the disguise type is a zombie villager. Set the value. else if (getType() == DisguiseType.ZOMBIE_VILLAGER) { getWatcher().setValue(13, (byte) 1); - } - - else if (getType() == DisguiseType.ELDER_GUARDIAN) { + } else if (getType() == DisguiseType.ELDER_GUARDIAN) { getWatcher().setValue(16, 0 | 4); - } - // Else if its a horse. Set the horse watcher type + } // Else if its a horse. Set the horse watcher type else if (getWatcher() instanceof HorseWatcher) { try { // Don't mess with this because Varient is something like ZombieHorse and so on. @@ -121,65 +120,65 @@ public abstract class Disguise { } final boolean alwaysSendVelocity; switch (getType()) { - case EGG: - case ENDER_PEARL: - case BAT: - case EXPERIENCE_ORB: - case FIREBALL: - case SMALL_FIREBALL: - case SNOWBALL: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case WITHER_SKULL: - case FIREWORK: - alwaysSendVelocity = true; - break; - default: - alwaysSendVelocity = false; - break; + case EGG: + case ENDER_PEARL: + case BAT: + case EXPERIENCE_ORB: + case FIREBALL: + case SMALL_FIREBALL: + case SNOWBALL: + case SPLASH_POTION: + case THROWN_EXP_BOTTLE: + case WITHER_SKULL: + case FIREWORK: + alwaysSendVelocity = true; + break; + default: + alwaysSendVelocity = false; + break; } double velocitySpeed = 0.0005; switch (getType()) { - case FIREWORK: - velocitySpeed = -0.040; - break; - case WITHER_SKULL: - velocitySpeed = 0.000001D; - break; - case ARROW: - case BOAT: - case ENDER_CRYSTAL: - case ENDER_DRAGON: - case GHAST: - case ITEM_FRAME: - case MINECART: - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - case PAINTING: - case PLAYER: - case SQUID: - velocitySpeed = 0; - break; - case DROPPED_ITEM: - case PRIMED_TNT: - case WITHER: - case FALLING_BLOCK: - velocitySpeed = 0.04; - break; - case EXPERIENCE_ORB: - velocitySpeed = 0.0221; - break; - case SPIDER: - case BAT: - case CAVE_SPIDER: - velocitySpeed = 0.004; - break; - default: - break; + case FIREWORK: + velocitySpeed = -0.040; + break; + case WITHER_SKULL: + velocitySpeed = 0.000001D; + break; + case ARROW: + case BOAT: + case ENDER_CRYSTAL: + case ENDER_DRAGON: + case GHAST: + case ITEM_FRAME: + case MINECART: + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + case PAINTING: + case PLAYER: + case SQUID: + velocitySpeed = 0; + break; + case DROPPED_ITEM: + case PRIMED_TNT: + case WITHER: + case FALLING_BLOCK: + velocitySpeed = 0.04; + break; + case EXPERIENCE_ORB: + velocitySpeed = 0.0221; + break; + case SPIDER: + case BAT: + case CAVE_SPIDER: + velocitySpeed = 0.004; + break; + default: + break; } final double vectorY = velocitySpeed; final TargetedDisguise disguise = (TargetedDisguise) this; @@ -328,7 +327,8 @@ public abstract class Disguise { /** * Get the disguised entity - * @return + * + * @return */ public Entity getEntity() { return entity; @@ -336,7 +336,8 @@ public abstract class Disguise { /** * Get the disguise type - * @return + * + * @return */ public DisguiseType getType() { return disguiseType; @@ -344,16 +345,17 @@ public abstract class Disguise { /** * Get the flag watcher - * @return + * + * @return */ public FlagWatcher getWatcher() { return watcher; } /** - * In use doesn't mean that this disguise is active. It means that Lib's Disguises still stores a reference to the disguise. - * getEntity() can still return null if this disguise is active after despawn, logout, etc. - * @return + * In use doesn't mean that this disguise is active. It means that Lib's Disguises still stores a reference to the disguise. getEntity() can still return null if this disguise is active after despawn, logout, etc. + * + * @return */ public boolean isDisguiseInUse() { return disguiseInUse; @@ -397,17 +399,16 @@ public abstract class Disguise { /** * Internal use - * @return + * + * @return */ public boolean isRemoveDisguiseOnDeath() { - if (getEntity() == null) return true; - return getEntity() instanceof Player ? - - (!((Player) getEntity()).isOnline() ? !isKeepDisguiseOnPlayerLogout() : !isKeepDisguiseOnPlayerDeath()) - - : - - (!isKeepDisguiseOnEntityDespawn() || getEntity().isDead()); + if (getEntity() == null) { + return true; + } + return getEntity() instanceof Player + ? (!((Player) getEntity()).isOnline() ? !isKeepDisguiseOnPlayerLogout() : !isKeepDisguiseOnPlayerDeath()) + : (!isKeepDisguiseOnEntityDespawn() || getEntity().isDead()); } public boolean isSelfDisguiseSoundsReplaced() { @@ -416,7 +417,8 @@ public abstract class Disguise { /** * Can the disguised view himself as the disguise - * @return + * + * @return */ public boolean isSelfDisguiseVisible() { return viewSelfDisguise; @@ -432,7 +434,8 @@ public abstract class Disguise { /** * Returns true if the entity's name is showing through the disguise - * @return + * + * @return */ public boolean isShowName() { return showName; @@ -440,7 +443,7 @@ public abstract class Disguise { /** * Removes the disguise and undisguises the entity if its using this disguise. - * + * * @return */ public boolean removeDisguise() { @@ -503,13 +506,15 @@ public abstract class Disguise { /** * Set the entity of the disguise. Only used for internal things. + * * @param entity - * @return + * @return */ public Disguise setEntity(Entity entity) { if (this.getEntity() != null) { - if (getEntity() == entity) + if (getEntity() == entity) { return this; + } throw new RuntimeException("This disguise is already in use! Try .clone()"); } if (isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled() && entity instanceof LivingEntity) { @@ -582,8 +587,7 @@ public abstract class Disguise { } /** - * Sets up the FlagWatcher with the entityclass, it creates all the data it needs to prevent conflicts when sending the - * datawatcher. + * Sets up the FlagWatcher with the entityclass, it creates all the data it needs to prevent conflicts when sending the datawatcher. */ private void setupWatcher() { HashMap disguiseValues = DisguiseValues.getMetaValues(getType()); @@ -611,8 +615,9 @@ public abstract class Disguise { } // STEP 2. As the watcher has not set data on it, check if I need to set the default data. // If neither of them touch it - if (!entityValues.containsKey(dataNo) && !disguiseValues.containsKey(dataNo)) + if (!entityValues.containsKey(dataNo) && !disguiseValues.containsKey(dataNo)) { continue; + } // If the disguise has this, but not the entity. Then better set it! if (!entityValues.containsKey(dataNo) && disguiseValues.containsKey(dataNo)) { getWatcher().setBackupValue(dataNo, disguiseValues.get(dataNo)); @@ -626,9 +631,9 @@ public abstract class Disguise { Object eObj = entityValues.get(dataNo); Object dObj = disguiseValues.get(dataNo); if (eObj == null || dObj == null) { - if (eObj == null && dObj == null) + if (eObj == null && dObj == null) { continue; - else { + } else { getWatcher().setBackupValue(dataNo, dObj); continue; } @@ -645,40 +650,41 @@ public abstract class Disguise { // EntityInsentient is 10 & 11 // EntityZombie is 12 & 13 & 14 - But it overrides other values and another check already does this. // EntityLiving is 6 & 7 & 8 & 9 - // Lets use switch Class baseClass = null; switch (dataNo) { - case 6: - case 7: - case 8: - case 9: - baseClass = ReflectionManager.getNmsClass("EntityLiving"); - break; - case 10: - case 11: - baseClass = ReflectionManager.getNmsClass("EntityInsentient"); - break; - case 16: - baseClass = ReflectionManager.getNmsClass("EntityAgeable"); - break; - default: - break; + case 6: + case 7: + case 8: + case 9: + baseClass = ReflectionManager.getNmsClass("EntityLiving"); + break; + case 10: + case 11: + baseClass = ReflectionManager.getNmsClass("EntityInsentient"); + break; + case 16: + baseClass = ReflectionManager.getNmsClass("EntityAgeable"); + break; + default: + break; } Class nmsEntityClass = ReflectionManager.getNmsEntity(getEntity()).getClass(); Class nmsDisguiseClass = DisguiseValues.getNmsEntityClass(getType()); if (nmsDisguiseClass != null) { // If they both extend the same base class. They OBVIOUSLY share the same datavalue. Right..? if (baseClass != null && baseClass.isAssignableFrom(nmsDisguiseClass) - && baseClass.isAssignableFrom(nmsEntityClass)) + && baseClass.isAssignableFrom(nmsEntityClass)) { continue; + } // So they don't extend a basic class. // Maybe if I check that they extend each other.. // Seeing as I only store the finished forms of entitys. This should raise no problems and allow for more shared // datawatchers. - if (nmsEntityClass.isAssignableFrom(nmsDisguiseClass) || nmsDisguiseClass.isAssignableFrom(nmsEntityClass)) + if (nmsEntityClass.isAssignableFrom(nmsDisguiseClass) || nmsDisguiseClass.isAssignableFrom(nmsEntityClass)) { continue; + } } // Well I can't find a reason I should leave it alone. They will probably conflict. // Time to set the value to the disguises value so no conflicts! @@ -693,7 +699,7 @@ public abstract class Disguise { /** * Can the disguised view himself as the disguise - * + * * @param viewSelfDisguise * @return */ @@ -704,8 +710,9 @@ public abstract class Disguise { if (DisguiseAPI.getDisguise((Player) getEntity(), getEntity()) == this) { if (isSelfDisguiseVisible()) { DisguiseUtilities.setupFakeDisguise(this); - } else + } else { DisguiseUtilities.removeSelfDisguise((Player) getEntity()); + } } } } @@ -762,9 +769,9 @@ public abstract class Disguise { } /** - * Returns the list of people who have /disguiseViewSelf - * toggled on - * @return + * Returns the list of people who have /disguiseViewSelf toggled on + * + * @return */ public static List getViewSelf() { return viewSelf; diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java index df695ae7..fb40321f 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/DisguiseType.java @@ -11,146 +11,78 @@ import org.bukkit.entity.Skeleton; import org.bukkit.entity.Zombie; public enum DisguiseType { + ARMOR_STAND(78), - ARROW(60), - BAT, - BLAZE, - BOAT(1), - CAVE_SPIDER, - CHICKEN, - COW, - CREEPER, - DONKEY, - DROPPED_ITEM(2, 1), - EGG(62), - ELDER_GUARDIAN, - ENDER_CRYSTAL(51), - ENDER_DRAGON, - ENDER_PEARL(65), - ENDER_SIGNAL(72), - ENDERMAN, - ENDERMITE, - EXPERIENCE_ORB, - FALLING_BLOCK(70, 1), - FIREBALL(63, 0), - FIREWORK(76), - FISHING_HOOK(90), - GHAST, - GIANT, - GUARDIAN, - HORSE, - IRON_GOLEM, - ITEM_FRAME(71), - LEASH_HITCH(77), - MAGMA_CUBE, - MINECART(10, 0), - MINECART_CHEST(10, 1), - MINECART_COMMAND(10, 6), - MINECART_FURNACE(10, 2), - MINECART_HOPPER(10, 5), - MINECART_MOB_SPAWNER(10, 4), - MINECART_TNT(10, 3), - MULE, - MUSHROOM_COW, - OCELOT, - PAINTING, - PIG, - PIG_ZOMBIE, - PLAYER, - PRIMED_TNT(50), - RABBIT, - SHEEP, - SILVERFISH, - SKELETON, - SKELETON_HORSE, - SLIME, - SMALL_FIREBALL(64, 0), - SNOWBALL(61), - SNOWMAN, - SPIDER, - SPLASH_POTION(73), - SQUID, - THROWN_EXP_BOTTLE(75), - UNDEAD_HORSE, - VILLAGER, - WITCH, - WITHER, - WITHER_SKELETON, - WITHER_SKULL(66), - WOLF, - ZOMBIE, - ZOMBIE_VILLAGER, - UNKNOWN; - + private static Method isVillager, getVariant, getSkeletonType, isElder; static { @@ -160,27 +92,27 @@ public enum DisguiseType { try { DisguiseType toUse = type; switch (type) { - // Disguise item frame isn't supported. So we don't give it a entity type which should prevent it from being.. - // Usable. - case ITEM_FRAME: - break; - case DONKEY: - case MULE: - case UNDEAD_HORSE: - case SKELETON_HORSE: - toUse = DisguiseType.HORSE; - break; - case ZOMBIE_VILLAGER: - toUse = DisguiseType.ZOMBIE; - break; - case WITHER_SKELETON: - toUse = DisguiseType.SKELETON; - break; - case ELDER_GUARDIAN: - toUse = DisguiseType.GUARDIAN; - break; - default: - break; + // Disguise item frame isn't supported. So we don't give it a entity type which should prevent it from being.. + // Usable. + case ITEM_FRAME: + break; + case DONKEY: + case MULE: + case UNDEAD_HORSE: + case SKELETON_HORSE: + toUse = DisguiseType.HORSE; + break; + case ZOMBIE_VILLAGER: + toUse = DisguiseType.ZOMBIE; + break; + case WITHER_SKELETON: + toUse = DisguiseType.SKELETON; + break; + case ELDER_GUARDIAN: + toUse = DisguiseType.GUARDIAN; + break; + default: + break; } type.setEntityType(EntityType.valueOf(toUse.name())); } catch (Throwable ex) { @@ -209,44 +141,44 @@ public enum DisguiseType { public static DisguiseType getType(Entity entity) { DisguiseType disguiseType = getType(entity.getType()); switch (disguiseType) { - case ZOMBIE: - try { - if ((Boolean) isVillager.invoke(entity)) { - disguiseType = DisguiseType.ZOMBIE_VILLAGER; + case ZOMBIE: + try { + if ((Boolean) isVillager.invoke(entity)) { + disguiseType = DisguiseType.ZOMBIE_VILLAGER; + } + } catch (Exception ex) { + ex.printStackTrace(System.out); } - } catch (Exception ex) { - ex.printStackTrace(System.out); - } - break; - case HORSE: - try { - Object variant = getVariant.invoke(entity); - disguiseType = DisguiseType.valueOf(((Enum) variant).name()); - } catch (Exception ex) { - ex.printStackTrace(System.out); - } - break; - case SKELETON: - try { - Object type = getSkeletonType.invoke(entity); - if (type == Skeleton.SkeletonType.WITHER) { - disguiseType = DisguiseType.WITHER_SKELETON; + break; + case HORSE: + try { + Object variant = getVariant.invoke(entity); + disguiseType = DisguiseType.valueOf(((Enum) variant).name()); + } catch (Exception ex) { + ex.printStackTrace(System.out); } - } catch (Exception ex) { - ex.printStackTrace(System.out); - } - break; - case GUARDIAN: - try { - if ((Boolean) isElder.invoke(entity)) { - disguiseType = DisguiseType.ELDER_GUARDIAN; + break; + case SKELETON: + try { + Object type = getSkeletonType.invoke(entity); + if (type == Skeleton.SkeletonType.WITHER) { + disguiseType = DisguiseType.WITHER_SKELETON; + } + } catch (Exception ex) { + ex.printStackTrace(System.out); } - } catch (Exception ex) { - ex.printStackTrace(System.out); - } - break; - default: - break; + break; + case GUARDIAN: + try { + if ((Boolean) isElder.invoke(entity)) { + disguiseType = DisguiseType.ELDER_GUARDIAN; + } + } catch (Exception ex) { + ex.printStackTrace(System.out); + } + break; + default: + break; } return disguiseType; } @@ -267,14 +199,14 @@ public enum DisguiseType { for (int i = 0; i < ints.length; i++) { int value = ints[i]; switch (i) { - case 0: - entityId = value; - break; - case 1: - defaultId = value; - break; - default: - break; + case 0: + entityId = value; + break; + case 1: + defaultId = value; + break; + default: + break; } } } @@ -317,7 +249,7 @@ public enum DisguiseType { public boolean isPlayer() { return this == DisguiseType.PLAYER; } - + public boolean isUnknown() { return this == DisguiseType.UNKNOWN; } @@ -332,8 +264,9 @@ public enum DisguiseType { public String toReadable() { String[] split = name().split("_"); - for (int i = 0; i < split.length; i++) + for (int i = 0; i < split.length; i++) { split[i] = split[i].substring(0, 1) + split[i].substring(1).toLowerCase(); + } return StringUtils.join(split, " "); } } diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java index cee5c6c3..2c2b2b02 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java @@ -24,7 +24,9 @@ import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.ReflectionManager; public class FlagWatcher { + public enum SlotType { + BOOTS(0), CHESTPLATE(2), HELD_ITEM(4), HELMET(3), LEGGINGS(1); // The ints is for bukkit. Not nms slots. private int slotNo = 0; @@ -89,16 +91,19 @@ public class FlagWatcher { sentValues.add(dataType); // Its sending the air metadata. This is the least commonly sent metadata which all entitys still share. // I send my custom values if I see this! - if (dataType == 1) + if (dataType == 1) { sendAllCustom = true; + } Object value = null; if (entityValues.containsKey(dataType)) { - if (entityValues.get(dataType) == null) + if (entityValues.get(dataType) == null) { continue; + } value = entityValues.get(dataType); } else if (backupEntityValues.containsKey(dataType)) { - if (backupEntityValues.get(dataType) == null) + if (backupEntityValues.get(dataType) == null) { continue; + } value = backupEntityValues.get(dataType); } if (value != null) { @@ -107,24 +112,28 @@ public class FlagWatcher { } boolean isDirty = watch.getDirtyState(); watch = new WrappedWatchableObject(dataType, value); - if (!isDirty) + if (!isDirty) { watch.setDirtyState(false); + } } else { boolean isDirty = watch.getDirtyState(); watch = new WrappedWatchableObject(dataType, watch.getValue()); - if (!isDirty) + if (!isDirty) { watch.setDirtyState(false); + } } newList.add(watch); } if (sendAllCustom) { // Its sending the entire meta data. Better add the custom meta for (int value : entityValues.keySet()) { - if (sentValues.contains(value)) + if (sentValues.contains(value)) { continue; + } Object obj = entityValues.get(value); - if (obj == null) + if (obj == null) { continue; + } WrappedWatchableObject watch = new WrappedWatchableObject(value, obj); newList.add(watch); } @@ -182,8 +191,9 @@ public class FlagWatcher { } protected Object getValue(int no, Object backup) { - if (entityValues.containsKey(no)) + if (entityValues.containsKey(no)) { return entityValues.get(no); + } return backup; } @@ -246,12 +256,14 @@ public class FlagWatcher { } protected void sendData(int... dataValues) { - if (!DisguiseAPI.isDisguiseInUse(getDisguise()) || getDisguise().getWatcher() != this) + if (!DisguiseAPI.isDisguiseInUse(getDisguise()) || getDisguise().getWatcher() != this) { return; + } List list = new ArrayList<>(); for (int data : dataValues) { - if (!entityValues.containsKey(data) || entityValues.get(data) == null) + if (!entityValues.containsKey(data) || entityValues.get(data) == null) { continue; + } Object value = entityValues.get(data); if (isEntityAnimationsAdded() && DisguiseConfig.isMetadataPacketsEnabled() && data == 0) { value = addEntityAnimations((Byte) value, WrappedDataWatcher.getEntityWatcher(disguise.getEntity()).getByte(0)); @@ -348,8 +360,9 @@ public class FlagWatcher { items[slot] = itemStack; if (DisguiseAPI.isDisguiseInUse(getDisguise()) && getDisguise().getWatcher() == this) { slot++; - if (slot > 4) + if (slot > 4) { slot = 0; + } PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT); StructureModifier mods = packet.getModifier(); mods.write(0, getDisguise().getEntity().getEntityId()); diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java index 1c1228e1..5964ce7a 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/MiscDisguise.java @@ -14,6 +14,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; public class MiscDisguise extends TargetedDisguise { + private int id = -1, data = 0; public MiscDisguise(DisguiseType disguiseType) { @@ -52,31 +53,31 @@ public class MiscDisguise extends TargetedDisguise { this.id = getType().getEntityId(); this.data = getType().getDefaultId(); switch (disguiseType) { - // The only disguises which should use a custom data. - case PAINTING: - ((PaintingWatcher) getWatcher()).setArt(Art.values()[Math.max(0, firstParam) % Art.values().length]); - break; - case FALLING_BLOCK: - ((FallingBlockWatcher) getWatcher()).setBlock(new ItemStack(Math.max(1, firstParam), 1, (short) Math.max(0, - secondParam))); - break; - case SPLASH_POTION: - ((SplashPotionWatcher) getWatcher()).setPotionId(Math.max(0, firstParam)); - break; - case DROPPED_ITEM: - if (firstParam > 0) { - ((DroppedItemWatcher) getWatcher()).setItemStack(new ItemStack(firstParam, Math.max(0, secondParam))); - } - break; - case FISHING_HOOK: // Entity ID of whoever is holding fishing rod - case ARROW: // Entity ID of shooter. Used for "Is he on this scoreboard team and do I render it moving through his body?" - case SMALL_FIREBALL: // Unknown. Uses entity id of shooter. 0 if no shooter - case FIREBALL: // Unknown. Uses entity id of shooter. 0 if no shooter - case WITHER_SKULL: // Unknown. Uses entity id of shooter. 0 if no shooter - this.data = firstParam; - break; - default: - break; + // The only disguises which should use a custom data. + case PAINTING: + ((PaintingWatcher) getWatcher()).setArt(Art.values()[Math.max(0, firstParam) % Art.values().length]); + break; + case FALLING_BLOCK: + ((FallingBlockWatcher) getWatcher()).setBlock(new ItemStack(Math.max(1, firstParam), 1, (short) Math.max(0, + secondParam))); + break; + case SPLASH_POTION: + ((SplashPotionWatcher) getWatcher()).setPotionId(Math.max(0, firstParam)); + break; + case DROPPED_ITEM: + if (firstParam > 0) { + ((DroppedItemWatcher) getWatcher()).setItemStack(new ItemStack(firstParam, Math.max(0, secondParam))); + } + break; + case FISHING_HOOK: // Entity ID of whoever is holding fishing rod + case ARROW: // Entity ID of shooter. Used for "Is he on this scoreboard team and do I render it moving through his body?" + case SMALL_FIREBALL: // Unknown. Uses entity id of shooter. 0 if no shooter + case FIREBALL: // Unknown. Uses entity id of shooter. 0 if no shooter + case WITHER_SKULL: // Unknown. Uses entity id of shooter. 0 if no shooter + this.data = firstParam; + break; + default: + break; } } @@ -134,14 +135,14 @@ public class MiscDisguise extends TargetedDisguise { */ public int getData() { switch (getType()) { - case FALLING_BLOCK: - return (int) ((FallingBlockWatcher) getWatcher()).getBlock().getDurability(); - case PAINTING: - return ((PaintingWatcher) getWatcher()).getArt().getId(); - case SPLASH_POTION: - return ((SplashPotionWatcher) getWatcher()).getPotionId(); - default: - return data; + case FALLING_BLOCK: + return (int) ((FallingBlockWatcher) getWatcher()).getBlock().getDurability(); + case PAINTING: + return ((PaintingWatcher) getWatcher()).getArt().getId(); + case SPLASH_POTION: + return ((SplashPotionWatcher) getWatcher()).getPotionId(); + default: + return data; } } @@ -245,4 +246,4 @@ public class MiscDisguise extends TargetedDisguise { return (MiscDisguise) super.silentlyRemovePlayer(playername); } -} \ No newline at end of file +} diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/MobDisguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/MobDisguise.java index a14161a5..7c430d99 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/MobDisguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/MobDisguise.java @@ -184,4 +184,4 @@ public class MobDisguise extends TargetedDisguise { public MobDisguise silentlyRemovePlayer(String playername) { return (MobDisguise) super.silentlyRemovePlayer(playername); } -} \ No newline at end of file +} diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java index 76005b26..06e42779 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/PlayerDisguise.java @@ -13,14 +13,16 @@ import me.libraryaddict.disguise.utilities.LibsProfileLookup; import me.libraryaddict.disguise.utilities.ReflectionManager; public class PlayerDisguise extends TargetedDisguise { + private LibsProfileLookup currentLookup; private WrappedGameProfile gameProfile; private String playerName; private String skinToUse; public PlayerDisguise(String name) { - if (name.length() > 16) + if (name.length() > 16) { name = name.substring(0, 16); + } playerName = name; createDisguise(DisguiseType.PLAYER); } @@ -198,9 +200,8 @@ public class PlayerDisguise extends TargetedDisguise { /** * Set the GameProfile, without tampering. - * - * @param gameProfile - * GameProfile + * + * @param gameProfile GameProfile * @return */ public PlayerDisguise setSkin(WrappedGameProfile gameProfile) { diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/RabbitType.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/RabbitType.java index b07e4f87..a9b8cfcb 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/RabbitType.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/RabbitType.java @@ -1,6 +1,7 @@ package me.libraryaddict.disguise.disguisetypes; public enum RabbitType { + BLACK(2), BROWN(0), GOLD(4), KILLER_BUNNY(99), PATCHES(3), PEPPER(5), WHITE(1); public static RabbitType getType(int id) { diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java index 71486f5e..a2eb278b 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/TargetedDisguise.java @@ -10,7 +10,9 @@ import me.libraryaddict.disguise.utilities.ReflectionManager; import org.bukkit.entity.Player; public abstract class TargetedDisguise extends Disguise { + public enum TargetType { + HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS, SHOW_TO_EVERYONE_BUT_THESE_PLAYERS; } diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/ArmorStandWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/ArmorStandWatcher.java index 49c764b9..982e8528 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/ArmorStandWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/ArmorStandWatcher.java @@ -30,9 +30,9 @@ public class ArmorStandWatcher extends LivingWatcher { private void set10(int value, boolean isTrue) { byte b1 = (Byte) getValue(10, (byte) 0); - if (isTrue) + if (isTrue) { b1 = (byte) (b1 | value); - else { + } else { b1 = (byte) (b1 & value); } setValue(10, b1); diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/FallingBlockWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/FallingBlockWatcher.java index 12648745..b71ab1ab 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/FallingBlockWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/FallingBlockWatcher.java @@ -9,6 +9,7 @@ import me.libraryaddict.disguise.disguisetypes.FlagWatcher; import me.libraryaddict.disguise.utilities.DisguiseUtilities; public class FallingBlockWatcher extends FlagWatcher { + private ItemStack block; public FallingBlockWatcher(Disguise disguise) { diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/HorseWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/HorseWatcher.java index 53b7738d..f4e6ec06 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/HorseWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/HorseWatcher.java @@ -23,14 +23,14 @@ public class HorseWatcher extends AgeableWatcher { public ItemStack getHorseArmor() { int horseValue = getHorseArmorAsInt(); switch (horseValue) { - case 1: - return new ItemStack(Material.getMaterial("IRON_BARDING")); - case 2: - return new ItemStack(Material.getMaterial("GOLD_BARDING")); - case 3: - return new ItemStack(Material.getMaterial("DIAMOND_BARDING")); - default: - break; + case 1: + return new ItemStack(Material.getMaterial("IRON_BARDING")); + case 2: + return new ItemStack(Material.getMaterial("GOLD_BARDING")); + case 3: + return new ItemStack(Material.getMaterial("DIAMOND_BARDING")); + default: + break; } return null; } diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/ItemFrameWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/ItemFrameWatcher.java index e50d6cb4..e44cd921 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/ItemFrameWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/ItemFrameWatcher.java @@ -11,8 +11,9 @@ public class ItemFrameWatcher extends FlagWatcher { } public ItemStack getItem() { - if (getValue(2, null) == null) + if (getValue(2, null) == null) { return new ItemStack(0); + } return (ItemStack) getValue(8, null); } @@ -21,8 +22,9 @@ public class ItemFrameWatcher extends FlagWatcher { } public void setItem(ItemStack newItem) { - if (newItem == null) + if (newItem == null) { newItem = new ItemStack(0); + } newItem = newItem.clone(); newItem.setAmount(1); setValue(8, newItem); diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/LivingWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/LivingWatcher.java index b1b5fff0..fa419c49 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/LivingWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/LivingWatcher.java @@ -23,8 +23,10 @@ import com.comphenix.protocol.wrappers.WrappedAttribute; import com.comphenix.protocol.wrappers.WrappedAttribute.Builder; public class LivingWatcher extends FlagWatcher { + static Object[] list; static Method potionNo; + static { try { list = (Object[]) ReflectionManager.getNmsField("MobEffectList", "byId").get(null); diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PaintingWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PaintingWatcher.java index 7fc6313f..98f42c17 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PaintingWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PaintingWatcher.java @@ -6,6 +6,7 @@ import me.libraryaddict.disguise.disguisetypes.FlagWatcher; import me.libraryaddict.disguise.utilities.DisguiseUtilities; public class PaintingWatcher extends FlagWatcher { + private Art painting; public PaintingWatcher(Disguise disguise) { diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PlayerWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PlayerWatcher.java index e7f2edf4..70e7a9d9 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PlayerWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/PlayerWatcher.java @@ -16,6 +16,7 @@ import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.ReflectionManager.LibVersion; public class PlayerWatcher extends LivingWatcher { + private boolean isInBed; private BlockFace sleepingDirection; @@ -82,6 +83,7 @@ public class PlayerWatcher extends LivingWatcher { /** * If no BlockFace is supplied. It grabs it from the entities facing direction if applicable. + * * @param sleeping * @param sleepingDirection */ diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SplashPotionWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SplashPotionWatcher.java index 21ff5919..09c28318 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SplashPotionWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/SplashPotionWatcher.java @@ -5,6 +5,7 @@ import me.libraryaddict.disguise.disguisetypes.FlagWatcher; import me.libraryaddict.disguise.utilities.DisguiseUtilities; public class SplashPotionWatcher extends FlagWatcher { + private int potionId; public SplashPotionWatcher(Disguise disguise) { diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/VillagerWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/VillagerWatcher.java index 7eaa2866..97ed639b 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/VillagerWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/VillagerWatcher.java @@ -17,11 +17,11 @@ public class VillagerWatcher extends AgeableWatcher { return Profession.values()[(Integer) getValue(16, 0)]; } - public void setProfession(int professionId){ + public void setProfession(int professionId) { setValue(16, professionId % 6); sendData(16); } - + public void setProfession(Profession newProfession) { setProfession(newProfession.getId()); } diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/WitherWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/WitherWatcher.java index 95abb4f3..d80603e1 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/WitherWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/WitherWatcher.java @@ -21,7 +21,7 @@ public class WitherWatcher extends LivingWatcher { } public int[] getTargets() { - return new int[] { (Integer) getValue(17, 0), (Integer) getValue(18, 0), (Integer) getValue(19, 0) }; + return new int[]{(Integer) getValue(17, 0), (Integer) getValue(18, 0), (Integer) getValue(19, 0)}; } public void setInvul(int invulnerability) { diff --git a/src/main/java/me/libraryaddict/disguise/events/DisguiseEvent.java b/src/main/java/me/libraryaddict/disguise/events/DisguiseEvent.java index fecd1427..1f6ea041 100644 --- a/src/main/java/me/libraryaddict/disguise/events/DisguiseEvent.java +++ b/src/main/java/me/libraryaddict/disguise/events/DisguiseEvent.java @@ -8,6 +8,7 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; public class DisguiseEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); public static HandlerList getHandlerList() { @@ -45,4 +46,4 @@ public class DisguiseEvent extends Event implements Cancellable { public void setCancelled(boolean cancelled) { isCancelled = cancelled; } -} \ No newline at end of file +} diff --git a/src/main/java/me/libraryaddict/disguise/events/UndisguiseEvent.java b/src/main/java/me/libraryaddict/disguise/events/UndisguiseEvent.java index d0829389..1ae228d6 100644 --- a/src/main/java/me/libraryaddict/disguise/events/UndisguiseEvent.java +++ b/src/main/java/me/libraryaddict/disguise/events/UndisguiseEvent.java @@ -8,6 +8,7 @@ import org.bukkit.event.Event; import org.bukkit.event.HandlerList; public class UndisguiseEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); public static HandlerList getHandlerList() { @@ -45,4 +46,4 @@ public class UndisguiseEvent extends Event implements Cancellable { public void setCancelled(boolean cancelled) { isCancelled = cancelled; } -} \ No newline at end of file +} diff --git a/src/main/java/me/libraryaddict/disguise/utilities/BaseDisguiseCommand.java b/src/main/java/me/libraryaddict/disguise/utilities/BaseDisguiseCommand.java index 8ba12058..cd4be2b0 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/BaseDisguiseCommand.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/BaseDisguiseCommand.java @@ -35,6 +35,7 @@ import org.bukkit.potion.PotionEffectType; public abstract class BaseDisguiseCommand implements CommandExecutor { public class DisguiseParseException extends Exception { + private static final long serialVersionUID = 1276971370793124510L; public DisguiseParseException() { @@ -45,7 +46,7 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { super(string); } } - + protected ArrayList getAllowedDisguises(HashMap, Boolean>> hashMap) { ArrayList allowedDisguises = new ArrayList<>(); for (DisguiseType type : hashMap.keySet()) { @@ -61,30 +62,30 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { protected HashMap getDisguisePermission(CommandSender sender, DisguiseType type) { switch (type) { - case PLAYER: - case FALLING_BLOCK: - case PAINTING: - case SPLASH_POTION: - case FISHING_HOOK: - case DROPPED_ITEM: - HashMap returns = new HashMap<>(); - String beginning = "libsdisguises.options." + getClass().getSimpleName().toLowerCase().replace("command", "") + "."; - for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) { - String lowerPerm = permission.getPermission().toLowerCase(); - if (lowerPerm.startsWith(beginning)) { - String[] split = lowerPerm.substring(beginning.length()).split("\\."); - if (split.length > 1) { - if (split[0].replace("_", "").equals(type.name().toLowerCase().replace("_", ""))) { - for (int i = 1; i < split.length; i++) { - returns.put(split[i], permission.getValue()); + case PLAYER: + case FALLING_BLOCK: + case PAINTING: + case SPLASH_POTION: + case FISHING_HOOK: + case DROPPED_ITEM: + HashMap returns = new HashMap<>(); + String beginning = "libsdisguises.options." + getClass().getSimpleName().toLowerCase().replace("command", "") + "."; + for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) { + String lowerPerm = permission.getPermission().toLowerCase(); + if (lowerPerm.startsWith(beginning)) { + String[] split = lowerPerm.substring(beginning.length()).split("\\."); + if (split.length > 1) { + if (split[0].replace("_", "").equals(type.name().toLowerCase().replace("_", ""))) { + for (int i = 1; i < split.length; i++) { + returns.put(split[i], permission.getValue()); + } } } } } - } - return returns; - default: - return new HashMap<>(); + return returns; + default: + return new HashMap<>(); } } @@ -92,8 +93,8 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { Method[] methods = watcherClass.getMethods(); methods = Arrays.copyOf(methods, methods.length + 4); int i = 4; - for (String methodName : new String[] { "setViewSelfDisguise", "setHideHeldItemFromSelf", "setHideArmorFromSelf", - "setHearSelfDisguise" }) { + for (String methodName : new String[]{"setViewSelfDisguise", "setHideHeldItemFromSelf", "setHideArmorFromSelf", + "setHearSelfDisguise"}) { try { methods[methods.length - i--] = Disguise.class.getMethod(methodName, boolean.class); } catch (Exception ex) { @@ -105,9 +106,10 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { /** * Get perms for the node. Returns a hashmap of allowed disguisetypes and their options + * * @param sender * @param permissionNode - * @return + * @return */ protected HashMap, Boolean>> getPermissions(CommandSender sender, String permissionNode) { HashMap, Boolean>> singleDisguises = new HashMap<>(); @@ -265,8 +267,9 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { option = option.substring(1); isRemove = false; } - if (option.equals("baby")) + if (option.equals("baby")) { option = "setbaby"; + } list.add(option); } HashMap, Boolean> options = new HashMap<>(); @@ -293,16 +296,15 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { } /** - * Returns the disguise if it all parsed correctly. Returns a exception with a complete message if it didn't. The - * commandsender is purely used for checking permissions. Would defeat the purpose otherwise. To reach this point, the - * disguise has been feed a proper disguisetype. + * Returns the disguise if it all parsed correctly. Returns a exception with a complete message if it didn't. The commandsender is purely used for checking permissions. Would defeat the purpose otherwise. To reach this point, the disguise has been feed a proper disguisetype. + * * @param sender * @param args * @param map - * @return - * @throws me.libraryaddict.disguise.utilities.BaseDisguiseCommand.DisguiseParseException - * @throws java.lang.IllegalAccessException - * @throws java.lang.reflect.InvocationTargetException + * @return + * @throws me.libraryaddict.disguise.utilities.BaseDisguiseCommand.DisguiseParseException + * @throws java.lang.IllegalAccessException + * @throws java.lang.reflect.InvocationTargetException */ protected Disguise parseDisguise(CommandSender sender, String[] args, HashMap, Boolean>> map) throws DisguiseParseException, IllegalAccessException, InvocationTargetException { @@ -366,7 +368,7 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { } else { if (!disguiseOptions.isEmpty() && (!disguiseOptions.containsKey(args[1].toLowerCase()) || !disguiseOptions - .get(args[1].toLowerCase()))) { + .get(args[1].toLowerCase()))) { throw new DisguiseParseException(ChatColor.RED + "Error! You don't have permission to use that name!"); } args[1] = args[1].replace("\\_", " "); @@ -415,19 +417,19 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { } if (miscId != -1) { switch (disguiseType) { - case PAINTING: - case FALLING_BLOCK: - case SPLASH_POTION: - case DROPPED_ITEM: - case FISHING_HOOK: - case ARROW: - case SMALL_FIREBALL: - case FIREBALL: - case WITHER_SKULL: - break; - default: - throw new DisguiseParseException(ChatColor.RED + "Error! " + disguiseType.toReadable() - + " doesn't know what to do with " + args[1] + "!"); + case PAINTING: + case FALLING_BLOCK: + case SPLASH_POTION: + case DROPPED_ITEM: + case FISHING_HOOK: + case ARROW: + case SMALL_FIREBALL: + case FIREBALL: + case WITHER_SKULL: + break; + default: + throw new DisguiseParseException(ChatColor.RED + "Error! " + disguiseType.toReadable() + + " doesn't know what to do with " + args[1] + "!"); } toSkip++; // If they also defined a data value @@ -577,8 +579,9 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { if (potionType == null && isNumeric(valueString)) { potionType = PotionEffectType.getById(Integer.parseInt(valueString)); } - if (potionType == null) + if (potionType == null) { throw new DisguiseParseException(); + } value = potionType; } catch (Exception ex) { throw parseToException("a potioneffect type", valueString, methodName); @@ -597,8 +600,9 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { } else if (param == BlockFace.class) { try { BlockFace face = BlockFace.valueOf(valueString.toUpperCase()); - if (face.ordinal() > 4) + if (face.ordinal() > 4) { throw new DisguiseParseException(); + } value = face; } catch (Exception ex) { throw parseToException("a direction (north, east, south, west, up)", valueString, methodName); @@ -661,10 +665,11 @@ public abstract class BaseDisguiseCommand implements CommandExecutor { usedOptions.add(methodName.toLowerCase()); } doCheck(optionPermissions, usedOptions); - if (FlagWatcher.class.isAssignableFrom(methodToUse.getDeclaringClass())) + if (FlagWatcher.class.isAssignableFrom(methodToUse.getDeclaringClass())) { methodToUse.invoke(disguise.getWatcher(), value); - else + } else { methodToUse.invoke(disguise, value); + } } // Alright. We've constructed our disguise. return disguise; diff --git a/src/main/java/me/libraryaddict/disguise/utilities/ClassGetter.java b/src/main/java/me/libraryaddict/disguise/utilities/ClassGetter.java index d86c2d43..a05dd781 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/ClassGetter.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/ClassGetter.java @@ -13,7 +13,6 @@ import java.util.jar.JarFile; /** * User: Austin Date: 4/22/13 Time: 11:47 PM (c) lazertester */ - // Code for this taken and slightly modified from // https://github.com/ddopson/java-class-enumerator public class ClassGetter { @@ -59,8 +58,9 @@ public class ClassGetter { } if (className != null) { Class c = loadClass(className); - if (c != null) + if (c != null) { classes.add(c); + } } } } catch (Exception ex) { diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java index 5a7ba40e..6b0aa8d8 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseSound.java @@ -11,107 +11,69 @@ import org.bukkit.Sound; * Only living disguises go in here! */ public enum DisguiseSound { - ARROW(null, null, null, null, "random.bowhit"), + ARROW(null, null, null, null, "random.bowhit"), BAT("mob.bat.hurt", null, "mob.bat.death", "mob.bat.idle", "damage.fallsmall", "mob.bat.loop", "damage.fallbig", "mob.bat.takeoff"), - BLAZE("mob.blaze.hit", null, "mob.blaze.death", "mob.blaze.breathe", "damage.fallsmall", "damage.fallbig"), - CAVE_SPIDER("mob.spider.say", "mob.spider.step", "mob.spider.death", "mob.spider.say"), - CHICKEN("mob.chicken.hurt", "mob.chicken.step", "mob.chicken.hurt", "mob.chicken.say", "damage.fallsmall", "mob.chicken.plop", "damage.fallbig"), - COW("mob.cow.hurt", "mob.cow.step", "mob.cow.hurt", "mob.cow.say"), - CREEPER("mob.creeper.say", "step.grass", "mob.creeper.death", null), - DONKEY("mob.horse.donkey.hit", "step.grass", "mob.horse.donkey.death", "mob.horse.donkey.idle", "mob.horse.gallop", "mob.horse.leather", "mob.horse.donkey.angry", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land", "mob.horse.jump", "mob.horse.angry"), - ELDER_GUARDIAN("mob.guardian.elder.hit", null, "mob.guardian.elder.death", "mob.guardian.elder.death"), - ENDER_DRAGON("mob.enderdragon.hit", null, "mob.enderdragon.end", "mob.enderdragon.growl", "damage.fallsmall", "mob.enderdragon.wings", "damage.fallbig"), - ENDERMAN("mob.endermen.hit", "step.grass", "mob.endermen.death", "mob.endermen.idle", "mob.endermen.scream", "mob.endermen.portal", "mob.endermen.stare"), - ENDERMITE("mob.silverfish.hit", "mob.silverfish.step", "mob.silverfish.kill", "mob.silverfish.say"), - GHAST("mob.ghast.scream", null, "mob.ghast.death", "mob.ghast.moan", "damage.fallsmall", "mob.ghast.fireball", "damage.fallbig", "mob.ghast.affectionate_scream", "mob.ghast.charge"), - GIANT("damage.hit", "step.grass", null, null), - GUARDIAN("mob.guardian.hit", null, "mob.guardian.death", "mob.guardian.death"), - HORSE("mob.horse.hit", "step.grass", "mob.horse.death", "mob.horse.idle", "mob.horse.gallop", "mob.horse.leather", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land", "mob.horse.jump", "mob.horse.angry", "mob.horse.leather"), - IRON_GOLEM("mob.irongolem.hit", "mob.irongolem.walk", "mob.irongolem.death", "mob.irongolem.throw"), - MAGMA_CUBE("mob.slime.attack", "mob.slime.big", null, null, "mob.slime.small"), - MULE("mob.horse.donkey.hit", "step.grass", "mob.horse.donkey.death", "mob.horse.donkey.idle"), - MUSHROOM_COW("mob.cow.hurt", "mob.cow.step", "mob.cow.hurt", "mob.cow.say"), - OCELOT("mob.cat.hitt", "step.grass", "mob.cat.hitt", "mob.cat.meow", "mob.cat.purreow", "mob.cat.purr"), - PIG("mob.pig.say", "mob.pig.step", "mob.pig.death", "mob.pig.say"), - PIG_ZOMBIE("mob.zombiepig.zpighurt", null, "mob.zombiepig.zpigdeath", "mob.zombiepig.zpig", "mob.zombiepig.zpigangry"), - PLAYER("game.player.hurt", "step.grass", "game.player.hurt", null), - RABBIT("mob.rabbit.hurt", "mob.rabbit.hop", "mob.rabbit.death", "mob.rabbit.idle"), - SHEEP("mob.sheep.say", "mob.sheep.step", null, "mob.sheep.say", "mob.sheep.shear"), - SILVERFISH("mob.silverfish.hit", "mob.silverfish.step", "mob.silverfish.kill", "mob.silverfish.say"), - SKELETON("mob.skeleton.hurt", "mob.skeleton.step", "mob.skeleton.death", "mob.skeleton.say"), - SKELETON_HORSE("mob.horse.skeleton.hit", "step.grass", "mob.horse.skeleton.death", "mob.horse.skeleton.idle", "mob.horse.gallop", "mob.horse.leather", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land", "mob.horse.jump", "mob.horse.angry"), - SLIME("mob.slime.attack", "mob.slime.big", null, null, "mob.slime.small"), - SNOWMAN(), - SPIDER("mob.spider.say", "mob.spider.step", "mob.spider.death", "mob.spider.say"), - SQUID(), - UNDEAD_HORSE("mob.horse.zombie.hit", "step.grass", "mob.horse.zombie.death", "mob.horse.zombie.idle", "mob.horse.gallop", "mob.horse.leather", "mob.horse.wood", "mob.horse.armor", "mob.horse.soft", "mob.horse.land", "mob.horse.jump", "mob.horse.angry"), - VILLAGER("mob.villager.hit", null, "mob.villager.death", "mob.villager.idle", "mob.villager.haggle", "mob.villager.no", "mob.villager.yes"), - WITCH("mob.witch.hurt", null, "mob.witch.death", "mob.witch.idle"), - WITHER("mob.wither.hurt", null, "mob.wither.death", "mob.wither.idle", "damage.fallsmall", "mob.wither.spawn", "damage.fallbig", "mob.wither.shoot"), - WITHER_SKELETON("mob.skeleton.hurt", "mob.skeleton.step", "mob.skeleton.death", "mob.skeleton.say"), - WOLF("mob.wolf.hurt", "mob.wolf.step", "mob.wolf.death", "mob.wolf.bark", "mob.wolf.panting", "mob.wolf.whine", "mob.wolf.howl", "mob.wolf.growl", "mob.wolf.shake"), - ZOMBIE("mob.zombie.hurt", "mob.zombie.step", "mob.zombie.death", "mob.zombie.say", "mob.zombie.infect", "mob.zombie.woodbreak", "mob.zombie.metal", "mob.zombie.wood"), - ZOMBIE_VILLAGER("mob.zombie.hurt", "mob.zombie.step", "mob.zombie.death", "mob.zombie.say", "mob.zombie.infect", "mob.zombie.woodbreak", "mob.zombie.metal", "mob.zombie.wood"); public enum SoundType { + CANCEL, DEATH, HURT, IDLE, STEP; } @@ -131,9 +93,9 @@ public enum DisguiseSound { for (int i = 0; i < sounds.length; i++) { Object obj = sounds[i]; String s; - if (obj == null) + if (obj == null) { continue; - else if (obj instanceof String) { + } else if (obj instanceof String) { s = (String) obj; } else if (obj instanceof Sound) { s = ReflectionManager.getCraftSound((Sound) obj); @@ -142,21 +104,21 @@ public enum DisguiseSound { throw new RuntimeException("Was given a unknown object " + obj); } switch (i) { - case 0: - disguiseSounds.put(SoundType.HURT, s); - break; - case 1: - disguiseSounds.put(SoundType.STEP, s); - break; - case 2: - disguiseSounds.put(SoundType.DEATH, s); - break; - case 3: - disguiseSounds.put(SoundType.IDLE, s); - break; - default: - cancelSounds.add(s); - break; + case 0: + disguiseSounds.put(SoundType.HURT, s); + break; + case 1: + disguiseSounds.put(SoundType.STEP, s); + break; + case 2: + disguiseSounds.put(SoundType.DEATH, s); + break; + case 3: + disguiseSounds.put(SoundType.IDLE, s); + break; + default: + cancelSounds.add(s); + break; } } } @@ -166,8 +128,9 @@ public enum DisguiseSound { } public String getSound(SoundType type) { - if (type == null || !disguiseSounds.containsKey(type)) + if (type == null || !disguiseSounds.containsKey(type)) { return null; + } return disguiseSounds.get(type); } @@ -179,18 +142,22 @@ public enum DisguiseSound { * Used to check if this sound name is owned by this disguise sound. */ public SoundType getType(String sound, boolean ignoreDamage) { - if (isCancelSound(sound)) + if (isCancelSound(sound)) { return SoundType.CANCEL; + } if (disguiseSounds.containsKey(SoundType.STEP) && disguiseSounds.get(SoundType.STEP).startsWith("step.") - && sound.startsWith("step.")) + && sound.startsWith("step.")) { return SoundType.STEP; + } for (SoundType type : SoundType.values()) { - if (!disguiseSounds.containsKey(type) || type == SoundType.DEATH || (ignoreDamage && type == SoundType.HURT)) + if (!disguiseSounds.containsKey(type) || type == SoundType.DEATH || (ignoreDamage && type == SoundType.HURT)) { continue; + } String s = disguiseSounds.get(type); if (s != null) { - if (s.equals(sound)) + if (s.equals(sound)) { return type; + } } } return null; @@ -205,9 +172,9 @@ public enum DisguiseSound { } public void removeSound(SoundType type, String sound) { - if (type == SoundType.CANCEL) + if (type == SoundType.CANCEL) { cancelSounds.remove(sound); - else { + } else { disguiseSounds.remove(type); } } @@ -221,9 +188,9 @@ public enum DisguiseSound { } public void setSound(SoundType type, String sound) { - if (type == SoundType.CANCEL) + if (type == SoundType.CANCEL) { cancelSounds.add(sound); - else { + } else { disguiseSounds.put(type, sound); } } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index adb1095b..89e2a3ff 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -51,20 +51,20 @@ import com.comphenix.protocol.wrappers.WrappedGameProfile; import com.comphenix.protocol.wrappers.WrappedWatchableObject; public class DisguiseUtilities { + /** - * This is a list of names which was called by other plugins. As such, don't remove from the gameProfiles as its the duty of - * the plugin to do that. + * This is a list of names which was called by other plugins. As such, don't remove from the gameProfiles as its the duty of the plugin to do that. */ private static HashSet addedByPlugins = new HashSet<>(); private static Object bedChunk; private static LinkedHashMap clonedDisguises = new LinkedHashMap<>(); /** * A hashmap of the uuid's of entitys, alive and dead. And their disguises in use - **/ + * + */ private static HashMap> disguisesInUse = new HashMap<>(); /** - * Disguises which are stored ready for a entity to be seen by a player Preferably, disguises in this should only stay in for - * a max of a second. + * Disguises which are stored ready for a entity to be seen by a player Preferably, disguises in this should only stay in for a max of a second. */ private static HashMap> futureDisguises = new HashMap<>(); /** @@ -99,7 +99,7 @@ public class DisguiseUtilities { ReflectionManager.getNmsClass("IBlockData")); Method setSky = chunkSection.getClass().getMethod("a", int.class, int.class, int.class, int.class); Method setEmitted = chunkSection.getClass().getMethod("b", int.class, int.class, int.class, int.class); - for (BlockFace face : new BlockFace[] { BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH }) { + for (BlockFace face : new BlockFace[]{BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH}) { setType.invoke(chunkSection, 1 + face.getModX(), 0, 1 + face.getModZ(), fromLegacyData.invoke(block, face.ordinal())); setSky.invoke(chunkSection, 1 + face.getModX(), 0, 1 + face.getModZ(), 0); setEmitted.invoke(chunkSection, 1 + face.getModX(), 0, 1 + face.getModZ(), 0); @@ -179,8 +179,7 @@ public class DisguiseUtilities { } /** - * If name isn't null. Make sure that the name doesn't see any other disguise. Else if name is null. Make sure that the - * observers in the disguise don't see any other disguise. + * If name isn't null. Make sure that the name doesn't see any other disguise. Else if name is null. Make sure that the observers in the disguise don't see any other disguise. */ public static void checkConflicts(TargetedDisguise disguise, String name) { // If the disguise is being used.. Else we may accidentally undisguise something else @@ -237,7 +236,6 @@ public class DisguiseUtilities { // System.out.print("Cannot set more than one " + TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS // + " on a entity. Removed the old disguise."); - disguiseItel.remove(); d.removeDisguise(); } @@ -258,7 +256,7 @@ public class DisguiseUtilities { entityTrackerEntry); HashSet cloned = (HashSet) trackedPlayers.clone(); PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY); - destroyPacket.getIntegerArrays().write(0, new int[] { disguise.getEntity().getEntityId() }); + destroyPacket.getIntegerArrays().write(0, new int[]{disguise.getEntity().getEntityId()}); for (Object p : cloned) { Player player = (Player) ReflectionManager.getBukkitEntity(p); if (player == disguise.getEntity() || disguise.canSee(player)) { @@ -281,7 +279,7 @@ public class DisguiseUtilities { if (disguiseValues.getBabyBox() != null) { if ((disguise.getWatcher() instanceof AgeableWatcher && ((AgeableWatcher) disguise.getWatcher()).isBaby()) || (disguise.getWatcher() instanceof ZombieWatcher && ((ZombieWatcher) disguise.getWatcher()) - .isBaby())) { + .isBaby())) { disguiseBox = disguiseValues.getBabyBox(); } } @@ -307,7 +305,7 @@ public class DisguiseUtilities { public static PacketContainer[] getBedChunkPacket(Player player, Location newLoc, Location oldLoc) { int i = 0; PacketContainer[] packets = new PacketContainer[newLoc != null ? 2 + (oldLoc != null ? 1 : 0) : 1]; - for (Location loc : new Location[] { oldLoc, newLoc }) { + for (Location loc : new Location[]{oldLoc, newLoc}) { if (loc == null) { continue; } @@ -360,7 +358,7 @@ public class DisguiseUtilities { ints.write(1, (int) Math.floor(loc.getX() * 32)); ints.write(2, (int) Math.floor((PacketsManager.getYModifier(disguise.getEntity(), disguise) + loc.getY()) * 32)); ints.write(3, (int) Math.floor(loc.getZ() * 32)); - return new PacketContainer[] { setBed, teleport }; + return new PacketContainer[]{setBed, teleport}; } @@ -433,8 +431,9 @@ public class DisguiseUtilities { /** * Get all EntityPlayers who have this entity in their Entity Tracker And they are in the targetted disguise. + * * @param disguise - * @return + * @return */ public static ArrayList getPerverts(Disguise disguise) { ArrayList players = new ArrayList<>(); @@ -469,7 +468,7 @@ public class DisguiseUtilities { if (DisguiseAPI.isDisguiseInUse(disguise) && (!gameProfile.getName().equals( disguise.getSkin() != null ? disguise.getSkin() : disguise.getName()) - || !gameProfile.getProperties().isEmpty())) { + || !gameProfile.getProperties().isEmpty())) { disguise.setGameProfile(gameProfile); DisguiseUtilities.refreshTrackers(disguise); } @@ -478,8 +477,7 @@ public class DisguiseUtilities { } /** - * Thread safe to use. This returns a GameProfile. And if its GameProfile doesn't have a skin blob. Then it does a lookup - * using schedulers. The runnable is run once the GameProfile has been successfully dealt with + * Thread safe to use. This returns a GameProfile. And if its GameProfile doesn't have a skin blob. Then it does a lookup using schedulers. The runnable is run once the GameProfile has been successfully dealt with */ public static WrappedGameProfile getProfileFromMojang(String playerName, LibsProfileLookup runnableIfCantReturn) { return getProfileFromMojang(playerName, (Object) runnableIfCantReturn); @@ -550,8 +548,7 @@ public class DisguiseUtilities { } /** - * Thread safe to use. This returns a GameProfile. And if its GameProfile doesn't have a skin blob. Then it does a lookup - * using schedulers. The runnable is run once the GameProfile has been successfully dealt with + * Thread safe to use. This returns a GameProfile. And if its GameProfile doesn't have a skin blob. Then it does a lookup using schedulers. The runnable is run once the GameProfile has been successfully dealt with */ public static WrappedGameProfile getProfileFromMojang(String playerName, Runnable runnableIfCantReturn) { return getProfileFromMojang(playerName, (Object) runnableIfCantReturn); @@ -582,14 +579,14 @@ public class DisguiseUtilities { } /** - * Please note that in the future when 'DualInt' and the like are removed. This should break.. However, that should be negated - * in the future as I'd be able to set the watcher index's as per the spigot version. Instead of checking on the player's - * version every single packet.. + * Please note that in the future when 'DualInt' and the like are removed. This should break.. However, that should be negated in the future as I'd be able to set the watcher index's as per the spigot version. Instead of checking on the player's version every single packet.. */ public static List rebuildForVersion(Player player, FlagWatcher watcher, List list) { if (true) // Use for future protocol compatibility + { return list; + } ArrayList rebuiltList = new ArrayList<>(); ArrayList backups = new ArrayList<>(); for (WrappedWatchableObject obj : list) { @@ -598,7 +595,7 @@ public class DisguiseUtilities { continue; } switch (obj.getIndex()) { - // TODO: Future version support + // TODO: Future version support } } Iterator itel = backups.iterator(); @@ -625,8 +622,9 @@ public class DisguiseUtilities { if (disguise.isDisguiseInUse() && disguise.getEntity() instanceof Player && ((Player) disguise.getEntity()).getName().equalsIgnoreCase(player)) { removeSelfDisguise((Player) disguise.getEntity()); - if (disguise.isSelfDisguiseVisible()) + if (disguise.isSelfDisguiseVisible()) { selfDisguised.add(disguise.getEntity().getUniqueId()); + } ProtocolLibrary.getProtocolManager().sendServerPacket((Player) disguise.getEntity(), destroyPacket); Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() { @Override @@ -820,10 +818,10 @@ public class DisguiseUtilities { ProtocolLibrary.getProtocolManager().sendServerPacket( player, ProtocolLibrary - .getProtocolManager() - .createPacketConstructor(PacketType.Play.Server.ENTITY_METADATA, player.getEntityId(), - WrappedDataWatcher.getEntityWatcher(player), true) - .createPacket(player.getEntityId(), WrappedDataWatcher.getEntityWatcher(player), true)); + .getProtocolManager() + .createPacketConstructor(PacketType.Play.Server.ENTITY_METADATA, player.getEntityId(), + WrappedDataWatcher.getEntityWatcher(player), true) + .createPacket(player.getEntityId(), WrappedDataWatcher.getEntityWatcher(player), true)); } catch (Exception ex) { ex.printStackTrace(System.out); } @@ -891,11 +889,11 @@ public class DisguiseUtilities { if (player.getVehicle() != null && player.getEntityId() > player.getVehicle().getEntityId()) { sendSelfPacket(player, manager.createPacketConstructor(PacketType.Play.Server.ATTACH_ENTITY, 0, player, player.getVehicle()) - .createPacket(0, player, player.getVehicle())); + .createPacket(0, player, player.getVehicle())); } else if (player.getPassenger() != null && player.getEntityId() > player.getPassenger().getEntityId()) { sendSelfPacket(player, manager.createPacketConstructor(PacketType.Play.Server.ATTACH_ENTITY, 0, player.getPassenger(), player) - .createPacket(0, player.getPassenger(), player)); + .createPacket(0, player.getPassenger(), player)); } // Resend the armor @@ -928,7 +926,7 @@ public class DisguiseUtilities { Object mobEffect = ReflectionManager.createMobEffect(potionEffect); sendSelfPacket(player, manager.createPacketConstructor(PacketType.Play.Server.ENTITY_EFFECT, player.getEntityId(), mobEffect) - .createPacket(player.getEntityId(), mobEffect)); + .createPacket(player.getEntityId(), mobEffect)); } } catch (Exception ex) { ex.printStackTrace(System.out); @@ -944,7 +942,7 @@ public class DisguiseUtilities { final PacketContainer[] delayed = transformed == null ? null : transformed[1]; try { if (packets == null) { - packets = new PacketContainer[] { packet }; + packets = new PacketContainer[]{packet}; } for (PacketContainer p : packets) { p = p.deepClone(); @@ -972,6 +970,7 @@ public class DisguiseUtilities { /** * Setup it so he can see himself when disguised + * * @param disguise */ public static void setupFakeDisguise(final Disguise disguise) { diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseValues.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseValues.java index bcee1f1d..a2ee51aa 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseValues.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseValues.java @@ -10,28 +10,28 @@ public class DisguiseValues { public static DisguiseValues getDisguiseValues(DisguiseType type) { switch (type) { - case DONKEY: - case MULE: - case UNDEAD_HORSE: - case SKELETON_HORSE: - type = DisguiseType.HORSE; - break; - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_TNT: - case MINECART_MOB_SPAWNER: - type = DisguiseType.MINECART; - break; - case WITHER_SKELETON: - type = DisguiseType.SKELETON; - break; - case ZOMBIE_VILLAGER: - type = DisguiseType.ZOMBIE; - break; - default: - break; + case DONKEY: + case MULE: + case UNDEAD_HORSE: + case SKELETON_HORSE: + type = DisguiseType.HORSE; + break; + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_TNT: + case MINECART_MOB_SPAWNER: + type = DisguiseType.MINECART; + break; + case WITHER_SKELETON: + type = DisguiseType.SKELETON; + break; + case ZOMBIE_VILLAGER: + type = DisguiseType.ZOMBIE; + break; + default: + break; } return values.get(type); } @@ -76,38 +76,38 @@ public class DisguiseValues { double d = paramDouble - (((int) Math.floor(paramDouble)) + 0.5D); switch (enumEntitySize) { - case 1: - if (d < 0.0D ? d < -0.3125D : d < 0.3125D) { + case 1: + if (d < 0.0D ? d < -0.3125D : d < 0.3125D) { + return (int) Math.ceil(paramDouble * 32.0D); + } + + return (int) Math.floor(paramDouble * 32.0D); + case 2: + if (d < 0.0D ? d < -0.3125D : d < 0.3125D) { + return (int) Math.floor(paramDouble * 32.0D); + } + return (int) Math.ceil(paramDouble * 32.0D); - } + case 3: + if (d > 0.0D) { + return (int) Math.floor(paramDouble * 32.0D); + } - return (int) Math.floor(paramDouble * 32.0D); - case 2: - if (d < 0.0D ? d < -0.3125D : d < 0.3125D) { - return (int) Math.floor(paramDouble * 32.0D); - } - - return (int) Math.ceil(paramDouble * 32.0D); - case 3: - if (d > 0.0D) { - return (int) Math.floor(paramDouble * 32.0D); - } - - return (int) Math.ceil(paramDouble * 32.0D); - case 4: - if (d < 0.0D ? d < -0.1875D : d < 0.1875D) { return (int) Math.ceil(paramDouble * 32.0D); - } + case 4: + if (d < 0.0D ? d < -0.1875D : d < 0.1875D) { + return (int) Math.ceil(paramDouble * 32.0D); + } - return (int) Math.floor(paramDouble * 32.0D); - case 5: - if (d < 0.0D ? d < -0.1875D : d < 0.1875D) { return (int) Math.floor(paramDouble * 32.0D); - } + case 5: + if (d < 0.0D ? d < -0.1875D : d < 0.1875D) { + return (int) Math.floor(paramDouble * 32.0D); + } - return (int) Math.ceil(paramDouble * 32.0D); - default: - break; + return (int) Math.ceil(paramDouble * 32.0D); + default: + break; } if (d > 0.0D) { return (int) Math.ceil(paramDouble * 32.0D); diff --git a/src/main/java/me/libraryaddict/disguise/utilities/FakeBoundingBox.java b/src/main/java/me/libraryaddict/disguise/utilities/FakeBoundingBox.java index 8f92890c..781ea698 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/FakeBoundingBox.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/FakeBoundingBox.java @@ -1,6 +1,7 @@ package me.libraryaddict.disguise.utilities; public class FakeBoundingBox { + private double xMod; private double yMod; private double zMod; diff --git a/src/main/java/me/libraryaddict/disguise/utilities/LibsProfileLookup.java b/src/main/java/me/libraryaddict/disguise/utilities/LibsProfileLookup.java index 24bd17cb..9c725159 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/LibsProfileLookup.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/LibsProfileLookup.java @@ -3,6 +3,7 @@ package me.libraryaddict.disguise.utilities; import com.comphenix.protocol.wrappers.WrappedGameProfile; public interface LibsProfileLookup { + public void onLookup(WrappedGameProfile gameProfile); } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/LibsProfileLookupCaller.java b/src/main/java/me/libraryaddict/disguise/utilities/LibsProfileLookupCaller.java index 49c9213f..cee46e8d 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/LibsProfileLookupCaller.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/LibsProfileLookupCaller.java @@ -6,6 +6,7 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.ProfileLookupCallback; public class LibsProfileLookupCaller implements ProfileLookupCallback { + private WrappedGameProfile gameProfile; public WrappedGameProfile getGameProfile() { diff --git a/src/main/java/me/libraryaddict/disguise/utilities/Metrics.java b/src/main/java/me/libraryaddict/disguise/utilities/Metrics.java index 196c2c0e..86e5ca95 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/Metrics.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/Metrics.java @@ -54,625 +54,623 @@ import java.util.logging.Level; import java.util.zip.GZIPOutputStream; public class Metrics { - /** - * The current revision number - */ - private final static int REVISION = 7; - /** - * The base url of the metrics domain - */ - private static final String BASE_URL = "http://report.mcstats.org"; - /** - * The url used to report a server's status - */ - private static final String REPORT_URL = "/plugin/%s"; - /** - * Interval of time to ping (in minutes) - */ - private static final int PING_INTERVAL = 15; - /** - * The plugin this metrics submits for - */ - private final Plugin plugin; - /** - * All of the custom graphs to submit to metrics - */ - private final Set graphs = Collections.synchronizedSet(new HashSet()); - /** - * The plugin configuration file - */ - private final YamlConfiguration configuration; - /** - * The plugin configuration file - */ - private final File configurationFile; - /** - * Unique server id - */ - private final String guid; - /** - * Debug mode - */ - private final boolean debug; - /** - * Lock for synchronization - */ - private final Object optOutLock = new Object(); - /** - * The scheduled task - */ - private volatile BukkitTask task = null; - public Metrics(final Plugin plugin) throws IOException { - if (plugin == null) { - throw new IllegalArgumentException("Plugin cannot be null"); - } - this.plugin = plugin; - // load the config - configurationFile = getConfigFile(); - configuration = YamlConfiguration.loadConfiguration(configurationFile); - // add some defaults - configuration.addDefault("opt-out", false); - configuration.addDefault("guid", UUID.randomUUID().toString()); - configuration.addDefault("debug", false); - // Do we need to create the file? - if (configuration.get("guid", null) == null) { - configuration.options().header("http://mcstats.org").copyDefaults(true); - configuration.save(configurationFile); - } - // Load the guid then - guid = configuration.getString("guid"); - debug = configuration.getBoolean("debug", false); - } + /** + * The current revision number + */ + private final static int REVISION = 7; + /** + * The base url of the metrics domain + */ + private static final String BASE_URL = "http://report.mcstats.org"; + /** + * The url used to report a server's status + */ + private static final String REPORT_URL = "/plugin/%s"; + /** + * Interval of time to ping (in minutes) + */ + private static final int PING_INTERVAL = 15; + /** + * The plugin this metrics submits for + */ + private final Plugin plugin; + /** + * All of the custom graphs to submit to metrics + */ + private final Set graphs = Collections.synchronizedSet(new HashSet()); + /** + * The plugin configuration file + */ + private final YamlConfiguration configuration; + /** + * The plugin configuration file + */ + private final File configurationFile; + /** + * Unique server id + */ + private final String guid; + /** + * Debug mode + */ + private final boolean debug; + /** + * Lock for synchronization + */ + private final Object optOutLock = new Object(); + /** + * The scheduled task + */ + private volatile BukkitTask task = null; - /** - * Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics website. Plotters can be added to the graph object returned. - * - * @param name - * The name of the graph - * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given - */ - public Graph createGraph(final String name) { - if (name == null) { - throw new IllegalArgumentException("Graph name cannot be null"); - } - // Construct the graph object - final Graph graph = new Graph(name); - // Now we can add our graph - graphs.add(graph); - // and return back - return graph; - } + public Metrics(final Plugin plugin) throws IOException { + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } + this.plugin = plugin; + // load the config + configurationFile = getConfigFile(); + configuration = YamlConfiguration.loadConfiguration(configurationFile); + // add some defaults + configuration.addDefault("opt-out", false); + configuration.addDefault("guid", UUID.randomUUID().toString()); + configuration.addDefault("debug", false); + // Do we need to create the file? + if (configuration.get("guid", null) == null) { + configuration.options().header("http://mcstats.org").copyDefaults(true); + configuration.save(configurationFile); + } + // Load the guid then + guid = configuration.getString("guid"); + debug = configuration.getBoolean("debug", false); + } - /** - * Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend - * - * @param graph - * The name of the graph - */ - public void addGraph(final Graph graph) { - if (graph == null) { - throw new IllegalArgumentException("Graph cannot be null"); - } - graphs.add(graph); - } + /** + * Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics website. Plotters can be added to the graph object returned. + * + * @param name The name of the graph + * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given + */ + public Graph createGraph(final String name) { + if (name == null) { + throw new IllegalArgumentException("Graph name cannot be null"); + } + // Construct the graph object + final Graph graph = new Graph(name); + // Now we can add our graph + graphs.add(graph); + // and return back + return graph; + } - /** - * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200 ticks. - * - * @return True if statistics measuring is running, otherwise false. - */ - public boolean start() { - synchronized (optOutLock) { - // Did we opt out? - if (isOptOut()) { - return false; - } - // Is metrics already running? - if (task != null) { - return true; - } - // Begin hitting the server with glorious data - task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { - private boolean firstPost = true; + /** + * Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend + * + * @param graph The name of the graph + */ + public void addGraph(final Graph graph) { + if (graph == null) { + throw new IllegalArgumentException("Graph cannot be null"); + } + graphs.add(graph); + } - @Override - public void run() { - try { - // This has to be synchronized or it can collide with the disable method. - synchronized (optOutLock) { - // Disable Task, if it is running and the server owner decided to opt-out - if (isOptOut() && task != null) { - task.cancel(); - task = null; - // Tell all plotters to stop gathering information. - for (Graph graph : graphs) { - graph.onOptOut(); - } - } - } - // We use the inverse of firstPost because if it is the first time we are posting, - // it is not a interval ping, so it evaluates to FALSE - // Each time thereafter it will evaluate to TRUE, i.e PING! - postPlugin(!firstPost); - // After the first post we set firstPost to false - // Each post thereafter will be a ping - firstPost = false; - } catch (IOException e) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); - } - } - } - }, 0, PING_INTERVAL * 1200); - return true; - } - } - - /** - * Has the server owner denied plugin metrics? - * - * @return true if metrics should be opted out of it - */ - public boolean isOptOut() { - synchronized (optOutLock) { - try { - // Reload the metrics file - configuration.load(getConfigFile()); - } catch (IOException | InvalidConfigurationException ex) { - if (debug) { - Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); - } - return true; - } - return configuration.getBoolean("opt-out", false); - } - } - - /** - * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. - * - * @throws java.io.IOException - */ - public void enable() throws IOException { - // This has to be synchronized or it can collide with the check in the task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set it. - if (isOptOut()) { - configuration.set("opt-out", false); - configuration.save(configurationFile); - } - // Enable Task, if it is not running - if (task == null) { - start(); - } - } - } - - /** - * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. - * - * @throws java.io.IOException - */ - public void disable() throws IOException { - // This has to be synchronized or it can collide with the check in the task. - synchronized (optOutLock) { - // Check if the server owner has already set opt-out, if not, set it. - if (!isOptOut()) { - configuration.set("opt-out", true); - configuration.save(configurationFile); - } - // Disable Task, if it is running - if (task != null) { - task.cancel(); - task = null; - } - } - } - - /** - * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status - * - * @return the File object for the config file - */ - public File getConfigFile() { - // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use - // is to abuse the plugin object we already have - // plugin.getDataFolder() => base/plugins/PluginA/ - // pluginsFolder => base/plugins/ - // The base is not necessarily relative to the startup directory. - File pluginsFolder = plugin.getDataFolder().getParentFile(); - // return => base/plugins/PluginMetrics/config.yml - return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); - } - - /** - * Generic method that posts a plugin to the metrics website - */ - private void postPlugin(final boolean isPing) throws IOException { - // Server software specific section - PluginDescriptionFile description = plugin.getDescription(); - String pluginName = description.getName(); - boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled - String pluginVersion = description.getVersion(); - String serverVersion = Bukkit.getVersion(); - int playersOnline = Bukkit.getServer().getOnlinePlayers().size(); - // END server software specific section -- all code below does not use any code outside of this class / Java - // Construct the post data - StringBuilder json = new StringBuilder(1024); - json.append('{'); - // The plugin's description file containg all of the plugin data such as name, version, author, etc - appendJSONPair(json, "guid", guid); - appendJSONPair(json, "plugin_version", pluginVersion); - appendJSONPair(json, "server_version", serverVersion); - appendJSONPair(json, "players_online", Integer.toString(playersOnline)); - // New data as of R6 - String osname = System.getProperty("os.name"); - String osarch = System.getProperty("os.arch"); - String osversion = System.getProperty("os.version"); - String java_version = System.getProperty("java.version"); - int coreCount = Runtime.getRuntime().availableProcessors(); - // normalize os arch .. amd64 -> x86_64 - if (osarch.equals("amd64")) { - osarch = "x86_64"; - } - appendJSONPair(json, "osname", osname); - appendJSONPair(json, "osarch", osarch); - appendJSONPair(json, "osversion", osversion); - appendJSONPair(json, "cores", Integer.toString(coreCount)); - appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); - appendJSONPair(json, "java_version", java_version); - // If we're pinging, append it - if (isPing) { - appendJSONPair(json, "ping", "1"); - } - if (graphs.size() > 0) { - synchronized (graphs) { - json.append(','); - json.append('"'); - json.append("graphs"); - json.append('"'); - json.append(':'); - json.append('{'); - boolean firstGraph = true; - final Iterator iter = graphs.iterator(); - while (iter.hasNext()) { - Graph graph = iter.next(); - StringBuilder graphJson = new StringBuilder(); - graphJson.append('{'); - for (Plotter plotter : graph.getPlotters()) { - appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue())); - } - graphJson.append('}'); - if (!firstGraph) { - json.append(','); - } - json.append(escapeJSON(graph.getName())); - json.append(':'); - json.append(graphJson); - firstGraph = false; - } - json.append('}'); - } - } - // close json - json.append('}'); - // Create the url - URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); - // Connect to the website - URLConnection connection; - // Mineshafter creates a socks proxy, so we can safely bypass it - // It does not reroute POST requests so we need to go around it - if (isMineshafterPresent()) { - connection = url.openConnection(Proxy.NO_PROXY); - } else { - connection = url.openConnection(); - } - byte[] uncompressed = json.toString().getBytes(); - byte[] compressed = gzip(json.toString()); - // Headers - connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); - connection.addRequestProperty("Content-Type", "application/json"); - connection.addRequestProperty("Content-Encoding", "gzip"); - connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - connection.setDoOutput(true); - if (debug) { - System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); - } - // Write the data - OutputStream os = connection.getOutputStream(); - os.write(compressed); - os.flush(); - String response; - try ( // Now read the response - BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { - response = reader.readLine(); - // close resources - os.close(); + /** + * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200 ticks. + * + * @return True if statistics measuring is running, otherwise false. + */ + public boolean start() { + synchronized (optOutLock) { + // Did we opt out? + if (isOptOut()) { + return false; } - if (response == null || response.startsWith("ERR") || response.startsWith("7")) { - if (response == null) { - response = "null"; - } else if (response.startsWith("7")) { - response = response.substring(response.startsWith("7,") ? 2 : 1); - } - throw new IOException(response); - } else { - // Is this the first update this hour? - if (response.equals("1") || response.contains("This is your first update this hour")) { - synchronized (graphs) { - final Iterator iter = graphs.iterator(); - while (iter.hasNext()) { - final Graph graph = iter.next(); - for (Plotter plotter : graph.getPlotters()) { - plotter.reset(); - } - } - } - } - } - } + // Is metrics already running? + if (task != null) { + return true; + } + // Begin hitting the server with glorious data + task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { + private boolean firstPost = true; - /** - * GZip compress a string of bytes - * - * @param input - * @return - */ - public static byte[] gzip(String input) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - GZIPOutputStream gzos = null; - try { - gzos = new GZIPOutputStream(baos); - gzos.write(input.getBytes("UTF-8")); - } catch (IOException e) { - e.printStackTrace(System.out); - } finally { - if (gzos != null) - try { - gzos.close(); - } catch (IOException ignore) { - } - } - return baos.toByteArray(); - } + @Override + public void run() { + try { + // This has to be synchronized or it can collide with the disable method. + synchronized (optOutLock) { + // Disable Task, if it is running and the server owner decided to opt-out + if (isOptOut() && task != null) { + task.cancel(); + task = null; + // Tell all plotters to stop gathering information. + for (Graph graph : graphs) { + graph.onOptOut(); + } + } + } + // We use the inverse of firstPost because if it is the first time we are posting, + // it is not a interval ping, so it evaluates to FALSE + // Each time thereafter it will evaluate to TRUE, i.e PING! + postPlugin(!firstPost); + // After the first post we set firstPost to false + // Each post thereafter will be a ping + firstPost = false; + } catch (IOException e) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); + } + } + } + }, 0, PING_INTERVAL * 1200); + return true; + } + } - /** - * Check if mineshafter is present. If it is, we need to bypass it to send POST requests - * - * @return true if mineshafter is installed on the server - */ - private boolean isMineshafterPresent() { - try { - Class.forName("mineshafter.MineServer"); - return true; - } catch (Exception e) { - return false; - } - } + /** + * Has the server owner denied plugin metrics? + * + * @return true if metrics should be opted out of it + */ + public boolean isOptOut() { + synchronized (optOutLock) { + try { + // Reload the metrics file + configuration.load(getConfigFile()); + } catch (IOException | InvalidConfigurationException ex) { + if (debug) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + } + return true; + } + return configuration.getBoolean("opt-out", false); + } + } - /** - * Appends a json encoded key/value pair to the given string builder. - * - * @param json - * @param key - * @param value - * @throws UnsupportedEncodingException - */ - private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { - boolean isValueNumeric = false; - try { - if (value.equals("0") || !value.endsWith("0")) { - Double.parseDouble(value); - isValueNumeric = true; - } - } catch (NumberFormatException e) { - isValueNumeric = false; - } - if (json.charAt(json.length() - 1) != '{') { - json.append(','); - } - json.append(escapeJSON(key)); - json.append(':'); - if (isValueNumeric) { - json.append(value); - } else { - json.append(escapeJSON(value)); - } - } + /** + * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. + * + * @throws java.io.IOException + */ + public void enable() throws IOException { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { + // Check if the server owner has already set opt-out, if not, set it. + if (isOptOut()) { + configuration.set("opt-out", false); + configuration.save(configurationFile); + } + // Enable Task, if it is not running + if (task == null) { + start(); + } + } + } - /** - * Escape a string to create a valid JSON string - * - * @param text - * @return - */ - private static String escapeJSON(String text) { - StringBuilder builder = new StringBuilder(); - builder.append('"'); - for (int index = 0; index < text.length(); index++) { - char chr = text.charAt(index); - switch (chr) { - case '"': - case '\\': - builder.append('\\'); - builder.append(chr); - break; - case '\b': - builder.append("\\b"); - break; - case '\t': - builder.append("\\t"); - break; - case '\n': - builder.append("\\n"); - break; - case '\r': - builder.append("\\r"); - break; - default: - if (chr < ' ') { - String t = "000" + Integer.toHexString(chr); - builder.append("\\u" + t.substring(t.length() - 4)); - } else { - builder.append(chr); - } - break; - } - } - builder.append('"'); - return builder.toString(); - } + /** + * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. + * + * @throws java.io.IOException + */ + public void disable() throws IOException { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { + // Check if the server owner has already set opt-out, if not, set it. + if (!isOptOut()) { + configuration.set("opt-out", true); + configuration.save(configurationFile); + } + // Disable Task, if it is running + if (task != null) { + task.cancel(); + task = null; + } + } + } - /** - * Encode text as UTF-8 - * - * @param text - * the text to encode - * @return the encoded text, as UTF-8 - */ - private static String urlEncode(final String text) throws UnsupportedEncodingException { - return URLEncoder.encode(text, "UTF-8"); - } + /** + * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status + * + * @return the File object for the config file + */ + public File getConfigFile() { + // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use + // is to abuse the plugin object we already have + // plugin.getDataFolder() => base/plugins/PluginA/ + // pluginsFolder => base/plugins/ + // The base is not necessarily relative to the startup directory. + File pluginsFolder = plugin.getDataFolder().getParentFile(); + // return => base/plugins/PluginMetrics/config.yml + return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); + } - /** - * Represents a custom graph on the website - */ - public static class Graph { - /** - * The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is rejected - */ - private final String name; - /** - * The set of plotters that are contained within this graph - */ - private final Set plotters = new LinkedHashSet<>(); + /** + * Generic method that posts a plugin to the metrics website + */ + private void postPlugin(final boolean isPing) throws IOException { + // Server software specific section + PluginDescriptionFile description = plugin.getDescription(); + String pluginName = description.getName(); + boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled + String pluginVersion = description.getVersion(); + String serverVersion = Bukkit.getVersion(); + int playersOnline = Bukkit.getServer().getOnlinePlayers().size(); + // END server software specific section -- all code below does not use any code outside of this class / Java + // Construct the post data + StringBuilder json = new StringBuilder(1024); + json.append('{'); + // The plugin's description file containg all of the plugin data such as name, version, author, etc + appendJSONPair(json, "guid", guid); + appendJSONPair(json, "plugin_version", pluginVersion); + appendJSONPair(json, "server_version", serverVersion); + appendJSONPair(json, "players_online", Integer.toString(playersOnline)); + // New data as of R6 + String osname = System.getProperty("os.name"); + String osarch = System.getProperty("os.arch"); + String osversion = System.getProperty("os.version"); + String java_version = System.getProperty("java.version"); + int coreCount = Runtime.getRuntime().availableProcessors(); + // normalize os arch .. amd64 -> x86_64 + if (osarch.equals("amd64")) { + osarch = "x86_64"; + } + appendJSONPair(json, "osname", osname); + appendJSONPair(json, "osarch", osarch); + appendJSONPair(json, "osversion", osversion); + appendJSONPair(json, "cores", Integer.toString(coreCount)); + appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); + appendJSONPair(json, "java_version", java_version); + // If we're pinging, append it + if (isPing) { + appendJSONPair(json, "ping", "1"); + } + if (graphs.size() > 0) { + synchronized (graphs) { + json.append(','); + json.append('"'); + json.append("graphs"); + json.append('"'); + json.append(':'); + json.append('{'); + boolean firstGraph = true; + final Iterator iter = graphs.iterator(); + while (iter.hasNext()) { + Graph graph = iter.next(); + StringBuilder graphJson = new StringBuilder(); + graphJson.append('{'); + for (Plotter plotter : graph.getPlotters()) { + appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue())); + } + graphJson.append('}'); + if (!firstGraph) { + json.append(','); + } + json.append(escapeJSON(graph.getName())); + json.append(':'); + json.append(graphJson); + firstGraph = false; + } + json.append('}'); + } + } + // close json + json.append('}'); + // Create the url + URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); + // Connect to the website + URLConnection connection; + // Mineshafter creates a socks proxy, so we can safely bypass it + // It does not reroute POST requests so we need to go around it + if (isMineshafterPresent()) { + connection = url.openConnection(Proxy.NO_PROXY); + } else { + connection = url.openConnection(); + } + byte[] uncompressed = json.toString().getBytes(); + byte[] compressed = gzip(json.toString()); + // Headers + connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); + connection.addRequestProperty("Content-Type", "application/json"); + connection.addRequestProperty("Content-Encoding", "gzip"); + connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + connection.setDoOutput(true); + if (debug) { + System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); + } + // Write the data + OutputStream os = connection.getOutputStream(); + os.write(compressed); + os.flush(); + String response; + try ( // Now read the response + BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + response = reader.readLine(); + // close resources + os.close(); + } + if (response == null || response.startsWith("ERR") || response.startsWith("7")) { + if (response == null) { + response = "null"; + } else if (response.startsWith("7")) { + response = response.substring(response.startsWith("7,") ? 2 : 1); + } + throw new IOException(response); + } else { + // Is this the first update this hour? + if (response.equals("1") || response.contains("This is your first update this hour")) { + synchronized (graphs) { + final Iterator iter = graphs.iterator(); + while (iter.hasNext()) { + final Graph graph = iter.next(); + for (Plotter plotter : graph.getPlotters()) { + plotter.reset(); + } + } + } + } + } + } - private Graph(final String name) { - this.name = name; - } + /** + * GZip compress a string of bytes + * + * @param input + * @return + */ + public static byte[] gzip(String input) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPOutputStream gzos = null; + try { + gzos = new GZIPOutputStream(baos); + gzos.write(input.getBytes("UTF-8")); + } catch (IOException e) { + e.printStackTrace(System.out); + } finally { + if (gzos != null) { + try { + gzos.close(); + } catch (IOException ignore) { + } + } + } + return baos.toByteArray(); + } - /** - * Gets the graph's name - * - * @return the Graph's name - */ - public String getName() { - return name; - } + /** + * Check if mineshafter is present. If it is, we need to bypass it to send POST requests + * + * @return true if mineshafter is installed on the server + */ + private boolean isMineshafterPresent() { + try { + Class.forName("mineshafter.MineServer"); + return true; + } catch (Exception e) { + return false; + } + } - /** - * Add a plotter to the graph, which will be used to plot entries - * - * @param plotter - * the plotter to add to the graph - */ - public void addPlotter(final Plotter plotter) { - plotters.add(plotter); - } + /** + * Appends a json encoded key/value pair to the given string builder. + * + * @param json + * @param key + * @param value + * @throws UnsupportedEncodingException + */ + private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { + boolean isValueNumeric = false; + try { + if (value.equals("0") || !value.endsWith("0")) { + Double.parseDouble(value); + isValueNumeric = true; + } + } catch (NumberFormatException e) { + isValueNumeric = false; + } + if (json.charAt(json.length() - 1) != '{') { + json.append(','); + } + json.append(escapeJSON(key)); + json.append(':'); + if (isValueNumeric) { + json.append(value); + } else { + json.append(escapeJSON(value)); + } + } - /** - * Remove a plotter from the graph - * - * @param plotter - * the plotter to remove from the graph - */ - public void removePlotter(final Plotter plotter) { - plotters.remove(plotter); - } + /** + * Escape a string to create a valid JSON string + * + * @param text + * @return + */ + private static String escapeJSON(String text) { + StringBuilder builder = new StringBuilder(); + builder.append('"'); + for (int index = 0; index < text.length(); index++) { + char chr = text.charAt(index); + switch (chr) { + case '"': + case '\\': + builder.append('\\'); + builder.append(chr); + break; + case '\b': + builder.append("\\b"); + break; + case '\t': + builder.append("\\t"); + break; + case '\n': + builder.append("\\n"); + break; + case '\r': + builder.append("\\r"); + break; + default: + if (chr < ' ') { + String t = "000" + Integer.toHexString(chr); + builder.append("\\u" + t.substring(t.length() - 4)); + } else { + builder.append(chr); + } + break; + } + } + builder.append('"'); + return builder.toString(); + } - /** - * Gets an unmodifiable set of the plotter objects in the graph - * - * @return an unmodifiable {@link java.util.Set} of the plotter objects - */ - public Set getPlotters() { - return Collections.unmodifiableSet(plotters); - } + /** + * Encode text as UTF-8 + * + * @param text the text to encode + * @return the encoded text, as UTF-8 + */ + private static String urlEncode(final String text) throws UnsupportedEncodingException { + return URLEncoder.encode(text, "UTF-8"); + } - @Override - public int hashCode() { - return name.hashCode(); - } + /** + * Represents a custom graph on the website + */ + public static class Graph { - @Override - public boolean equals(final Object object) { - if (!(object instanceof Graph)) { - return false; - } - final Graph graph = (Graph) object; - return graph.name.equals(name); - } + /** + * The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is rejected + */ + private final String name; + /** + * The set of plotters that are contained within this graph + */ + private final Set plotters = new LinkedHashSet<>(); - /** - * Called when the server owner decides to opt-out of BukkitMetrics while the server is running. - */ - protected void onOptOut() { - } - } + private Graph(final String name) { + this.name = name; + } - /** - * Interface used to collect custom data for a plugin - */ - public static abstract class Plotter { - /** - * The plot's name - */ - private final String name; + /** + * Gets the graph's name + * + * @return the Graph's name + */ + public String getName() { + return name; + } - /** - * Construct a plotter with the default plot name - */ - public Plotter() { - this("Default"); - } + /** + * Add a plotter to the graph, which will be used to plot entries + * + * @param plotter the plotter to add to the graph + */ + public void addPlotter(final Plotter plotter) { + plotters.add(plotter); + } - /** - * Construct a plotter with a specific plot name - * - * @param name - * the name of the plotter to use, which will show up on the website - */ - public Plotter(final String name) { - this.name = name; - } + /** + * Remove a plotter from the graph + * + * @param plotter the plotter to remove from the graph + */ + public void removePlotter(final Plotter plotter) { + plotters.remove(plotter); + } - /** - * Get the current value for the plotted point. Since this function defers to an external function it may or may not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called from any thread so care should be taken when accessing resources that need to be synchronized. - * - * @return the current value for the point to be plotted. - */ - public abstract int getValue(); + /** + * Gets an unmodifiable set of the plotter objects in the graph + * + * @return an unmodifiable {@link java.util.Set} of the plotter objects + */ + public Set getPlotters() { + return Collections.unmodifiableSet(plotters); + } - /** - * Get the column name for the plotted point - * - * @return the plotted point's column name - */ - public String getColumnName() { - return name; - } + @Override + public int hashCode() { + return name.hashCode(); + } - /** - * Called after the website graphs have been updated - */ - public void reset() { - } + @Override + public boolean equals(final Object object) { + if (!(object instanceof Graph)) { + return false; + } + final Graph graph = (Graph) object; + return graph.name.equals(name); + } - @Override - public int hashCode() { - return getColumnName().hashCode(); - } + /** + * Called when the server owner decides to opt-out of BukkitMetrics while the server is running. + */ + protected void onOptOut() { + } + } - @Override - public boolean equals(final Object object) { - if (!(object instanceof Plotter)) { - return false; - } - final Plotter plotter = (Plotter) object; - return plotter.name.equals(name) && plotter.getValue() == getValue(); - } - } + /** + * Interface used to collect custom data for a plugin + */ + public static abstract class Plotter { + + /** + * The plot's name + */ + private final String name; + + /** + * Construct a plotter with the default plot name + */ + public Plotter() { + this("Default"); + } + + /** + * Construct a plotter with a specific plot name + * + * @param name the name of the plotter to use, which will show up on the website + */ + public Plotter(final String name) { + this.name = name; + } + + /** + * Get the current value for the plotted point. Since this function defers to an external function it may or may not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called from any thread so care should be taken when accessing resources that need to be synchronized. + * + * @return the current value for the point to be plotted. + */ + public abstract int getValue(); + + /** + * Get the column name for the plotted point + * + * @return the plotted point's column name + */ + public String getColumnName() { + return name; + } + + /** + * Called after the website graphs have been updated + */ + public void reset() { + } + + @Override + public int hashCode() { + return getColumnName().hashCode(); + } + + @Override + public boolean equals(final Object object) { + if (!(object instanceof Plotter)) { + return false; + } + final Plotter plotter = (Plotter) object; + return plotter.name.equals(name) && plotter.getValue() == getValue(); + } + } } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java b/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java index 7928aee1..f4138656 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/PacketsManager.java @@ -58,9 +58,9 @@ import com.comphenix.protocol.wrappers.WrappedWatchableObject; import net.minecraft.server.v1_8_R3.DamageSource; public class PacketsManager { + /** - * This is a fix for the stupidity that is - * "I can't separate the sounds from the sounds the player heard, and the sounds of the entity tracker heard" + * This is a fix for the stupidity that is "I can't separate the sounds from the sounds the player heard, and the sounds of the entity tracker heard" */ private static boolean cancelSound; private static PacketListener clientInteractEntityListener; @@ -79,53 +79,56 @@ public class PacketsManager { // Because it kicks you for hacking. clientInteractEntityListener = new PacketAdapter(libsDisguises, ListenerPriority.NORMAL, PacketType.Play.Client.USE_ENTITY) { - @Override - public void onPacketReceiving(PacketEvent event) { - if (event.isCancelled()) - return; - try { - Player observer = event.getPlayer(); - StructureModifier entityModifer = event.getPacket().getEntityModifier(observer.getWorld()); - Entity entity = entityModifer.read(0); - if (entity instanceof ExperienceOrb || entity instanceof Item || entity instanceof Arrow + @Override + public void onPacketReceiving(PacketEvent event) { + if (event.isCancelled()) { + return; + } + try { + Player observer = event.getPlayer(); + StructureModifier entityModifer = event.getPacket().getEntityModifier(observer.getWorld()); + Entity entity = entityModifer.read(0); + if (entity instanceof ExperienceOrb || entity instanceof Item || entity instanceof Arrow || entity == observer) { - event.setCancelled(true); - } - ItemStack item = observer.getItemInHand(); - if (item != null && item.getType() == Material.INK_SACK) { - Disguise disguise = DisguiseAPI.getDisguise(observer, entity); - if (disguise != null - && (disguise.getType() == DisguiseType.SHEEP || disguise.getType() == DisguiseType.WOLF)) { - AnimalColor color = AnimalColor.getColor(item.getDurability()); - if (disguise.getType() == DisguiseType.SHEEP) { - SheepWatcher watcher = (SheepWatcher) disguise.getWatcher(); - watcher.setColor(DisguiseConfig.isSheepDyeable() ? color : watcher.getColor()); - } else { - WolfWatcher watcher = (WolfWatcher) disguise.getWatcher(); - watcher.setCollarColor(DisguiseConfig.isWolfDyeable() ? color : watcher.getCollarColor()); + event.setCancelled(true); } + ItemStack item = observer.getItemInHand(); + if (item != null && item.getType() == Material.INK_SACK) { + Disguise disguise = DisguiseAPI.getDisguise(observer, entity); + if (disguise != null + && (disguise.getType() == DisguiseType.SHEEP || disguise.getType() == DisguiseType.WOLF)) { + AnimalColor color = AnimalColor.getColor(item.getDurability()); + if (disguise.getType() == DisguiseType.SHEEP) { + SheepWatcher watcher = (SheepWatcher) disguise.getWatcher(); + watcher.setColor(DisguiseConfig.isSheepDyeable() ? color : watcher.getColor()); + } else { + WolfWatcher watcher = (WolfWatcher) disguise.getWatcher(); + watcher.setCollarColor(DisguiseConfig.isWolfDyeable() ? color : watcher.getCollarColor()); + } + } + } + } catch (Exception e) { + e.printStackTrace(System.out); } } - } catch (Exception e) { - e.printStackTrace(System.out); - } - } - }; + }; ProtocolLibrary.getProtocolManager().addPacketListener(clientInteractEntityListener); // Now I call this and the main listener is registered! setupMainPacketsListener(); } - + /** * Construct the packets I need to spawn in the disguise + * * @param player * @param disguise * @param disguisedEntity - * @return + * @return */ public static PacketContainer[][] constructSpawnPackets(final Player player, Disguise disguise, Entity disguisedEntity) { - if (disguise.getEntity() == null) + if (disguise.getEntity() == null) { disguise.setEntity(disguisedEntity); + } Object nmsEntity = ReflectionManager.getNmsEntity(disguisedEntity); ArrayList packets = new ArrayList<>(); // This sends the armor packets so that the player isn't naked. @@ -133,8 +136,9 @@ public class PacketsManager { if (DisguiseConfig.isEquipmentPacketsEnabled()) { for (int nmsSlot = 0; nmsSlot < 5; nmsSlot++) { int armorSlot = nmsSlot - 1; - if (armorSlot < 0) + if (armorSlot < 0) { armorSlot = 4; + } ItemStack itemstack = disguise.getWatcher().getItemStack(armorSlot); if (itemstack != null && itemstack.getTypeId() != 0) { ItemStack item = null; @@ -286,7 +290,7 @@ public class PacketsManager { spawnPackets[0].getModifier().write(1, playerList); PacketContainer delayedPacket = spawnPackets[0].shallowClone(); delayedPacket.getModifier().write(0, ReflectionManager.getEnumPlayerInfoAction(4)); - delayedPackets = new PacketContainer[] { delayedPacket }; + delayedPackets = new PacketContainer[]{delayedPacket}; } else if (disguise.getType().isMob() || disguise.getType() == DisguiseType.ARMOR_STAND) { DisguiseValues values = DisguiseValues.getDisguiseValues(disguise.getType()); @@ -299,18 +303,24 @@ public class PacketsManager { double d2 = vec.getX(); double d3 = vec.getY(); double d4 = vec.getZ(); - if (d2 < -d1) + if (d2 < -d1) { d2 = -d1; - if (d3 < -d1) + } + if (d3 < -d1) { d3 = -d1; - if (d4 < -d1) + } + if (d4 < -d1) { d4 = -d1; - if (d2 > d1) + } + if (d2 > d1) { d2 = d1; - if (d3 > d1) + } + if (d3 > d1) { d3 = d1; - if (d4 > d1) + } + if (d4 > d1) { d4 = d1; + } mods.write(2, values.getEntitySize(loc.getX())); mods.write(3, (int) Math.floor(loc.getY() * 32D)); mods.write(4, values.getEntitySize(loc.getZ())); @@ -322,11 +332,11 @@ public class PacketsManager { spawnPackets[0].getDataWatcherModifier().write(0, createDataWatcher(player, WrappedDataWatcher.getEntityWatcher(disguisedEntity), disguise.getWatcher())); } else if (disguise.getType().isMisc()) { - MiscDisguise msc = (MiscDisguise)disguise; + MiscDisguise msc = (MiscDisguise) disguise; int id = disguise.getType().getEntityId(); int data = msc.getData(); if (disguise.getType() == DisguiseType.FALLING_BLOCK) { - data = msc.getId() + (msc.getData() << 12); + data = msc.getId() + (msc.getData() << 12); } else if (disguise.getType() == DisguiseType.FISHING_HOOK && data == 0) { // If the MiscDisguise data isn't set. Then no entity id was provided, so default to the owners entity id data = disguisedEntity.getEntityId(); @@ -359,7 +369,7 @@ public class PacketsManager { mods.write(0, disguisedEntity.getEntityId()); mods.write(1, yaw); } - return new PacketContainer[][] { spawnPackets, delayedPackets }; + return new PacketContainer[][]{spawnPackets, delayedPackets}; } /** @@ -382,29 +392,29 @@ public class PacketsManager { public static byte getPitch(DisguiseType disguiseType, DisguiseType entityType, byte value) { switch (disguiseType) { - case MINECART: - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - value = (byte) -value; - break; - default: - break; + case MINECART: + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + value = (byte) -value; + break; + default: + break; } switch (entityType) { - case MINECART: - case MINECART_CHEST: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - value = (byte) -value; - break; - default: - break; + case MINECART: + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + value = (byte) -value; + break; + default: + break; } return value; } @@ -414,57 +424,57 @@ public class PacketsManager { */ public static byte getYaw(DisguiseType disguiseType, EntityType entityType, byte value) { switch (disguiseType) { - case MINECART: - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - value += 64; - break; - case ENDER_DRAGON: - case WITHER_SKULL: - value -= 128; - break; - case ARROW: - value = (byte) -value; - break; - case PAINTING: - case ITEM_FRAME: - value = (byte) -(value + 128); - break; - default: - if (disguiseType.isMisc() && disguiseType != DisguiseType.ARMOR_STAND) { - value -= 64; - } - break; + case MINECART: + case MINECART_CHEST: + case MINECART_COMMAND: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + value += 64; + break; + case ENDER_DRAGON: + case WITHER_SKULL: + value -= 128; + break; + case ARROW: + value = (byte) -value; + break; + case PAINTING: + case ITEM_FRAME: + value = (byte) -(value + 128); + break; + default: + if (disguiseType.isMisc() && disguiseType != DisguiseType.ARMOR_STAND) { + value -= 64; + } + break; } switch (entityType) { - case MINECART: - case MINECART_CHEST: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - value -= 64; - break; - case ENDER_DRAGON: - case WITHER_SKULL: - value += 128; - break; - case ARROW: - value = (byte) -value; - break; - case PAINTING: - case ITEM_FRAME: - value = (byte) -(value - 128); - break; - default: - if (!entityType.isAlive()) { - value += 64; - } - break; + case MINECART: + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + value -= 64; + break; + case ENDER_DRAGON: + case WITHER_SKULL: + value += 128; + break; + case ARROW: + value = (byte) -value; + break; + case PAINTING: + case ITEM_FRAME: + value = (byte) -(value - 128); + break; + default: + if (!entityType.isAlive()) { + value += 64; + } + break; } return value; } @@ -479,94 +489,235 @@ public class PacketsManager { yMod -= 0.13; } switch (disguise.getType()) { - case BAT: - if (entity instanceof LivingEntity) - return yMod + ((LivingEntity) entity).getEyeHeight(); - case MINECART: - case MINECART_COMMAND: - case MINECART_CHEST: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - switch (entity.getType()) { + case BAT: + if (entity instanceof LivingEntity) { + return yMod + ((LivingEntity) entity).getEyeHeight(); + } case MINECART: + case MINECART_COMMAND: case MINECART_CHEST: case MINECART_FURNACE: case MINECART_HOPPER: case MINECART_MOB_SPAWNER: case MINECART_TNT: - return yMod; + switch (entity.getType()) { + case MINECART: + case MINECART_CHEST: + case MINECART_FURNACE: + case MINECART_HOPPER: + case MINECART_MOB_SPAWNER: + case MINECART_TNT: + return yMod; + default: + return yMod + 0.4; + } + case ARROW: + case BOAT: + case EGG: + case ENDER_PEARL: + case ENDER_SIGNAL: + case FIREWORK: + case PAINTING: + case SMALL_FIREBALL: + case SNOWBALL: + case SPLASH_POTION: + case THROWN_EXP_BOTTLE: + case WITHER_SKULL: + return yMod + 0.7; + case PLAYER: + if (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise.getWatcher()).isSleeping()) { + return yMod + 0.35; + } + break; + case DROPPED_ITEM: + return yMod + 0.13; default: - return yMod + 0.4; - } - case ARROW: - case BOAT: - case EGG: - case ENDER_PEARL: - case ENDER_SIGNAL: - case FIREWORK: - case PAINTING: - case SMALL_FIREBALL: - case SNOWBALL: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case WITHER_SKULL: - return yMod + 0.7; - case PLAYER: - if (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise.getWatcher()).isSleeping()) { - return yMod + 0.35; - } - break; - case DROPPED_ITEM: - return yMod + 0.13; - default: - break; + break; } return yMod; } /** * Creates the packet listeners + * * @param plugin */ public static void init(LibsDisguises plugin) { libsDisguises = plugin; soundsListener = new PacketAdapter(libsDisguises, ListenerPriority.NORMAL, PacketType.Play.Server.NAMED_SOUND_EFFECT, PacketType.Play.Server.ENTITY_STATUS) { - @Override - public void onPacketSending(PacketEvent event) { - if (event.isCancelled()) { - return; - } - event.setPacket(event.getPacket().deepClone()); - StructureModifier mods = event.getPacket().getModifier(); - Player observer = event.getPlayer(); - if (event.getPacketType() == PacketType.Play.Server.NAMED_SOUND_EFFECT) { - if (event.isAsync()) { - return; - } - String soundName = (String) mods.read(0); - SoundType soundType = null; - Location soundLoc = new Location(observer.getWorld(), ((Integer) mods.read(1)) / 8D, - ((Integer) mods.read(2)) / 8D, ((Integer) mods.read(3)) / 8D); - Entity disguisedEntity = null; - DisguiseSound entitySound = null; - Disguise disguise = null; - Entity[] entities = soundLoc.getChunk().getEntities(); - for (Entity entity : entities) { - Disguise entityDisguise = DisguiseAPI.getDisguise(observer, entity); - if (entityDisguise != null) { - Location loc = entity.getLocation(); - loc = new Location(observer.getWorld(), ((int) (loc.getX() * 8)) / 8D, ((int) (loc.getY() * 8)) / 8D, - ((int) (loc.getZ() * 8)) / 8D); - if (loc.equals(soundLoc)) { - entitySound = DisguiseSound.getType(entity.getType().name()); - if (entitySound != null) { + @Override + public void onPacketSending(PacketEvent event) { + if (event.isCancelled()) { + return; + } + event.setPacket(event.getPacket().deepClone()); + StructureModifier mods = event.getPacket().getModifier(); + Player observer = event.getPlayer(); + if (event.getPacketType() == PacketType.Play.Server.NAMED_SOUND_EFFECT) { + if (event.isAsync()) { + return; + } + String soundName = (String) mods.read(0); + SoundType soundType = null; + Location soundLoc = new Location(observer.getWorld(), ((Integer) mods.read(1)) / 8D, + ((Integer) mods.read(2)) / 8D, ((Integer) mods.read(3)) / 8D); + Entity disguisedEntity = null; + DisguiseSound entitySound = null; + Disguise disguise = null; + Entity[] entities = soundLoc.getChunk().getEntities(); + for (Entity entity : entities) { + Disguise entityDisguise = DisguiseAPI.getDisguise(observer, entity); + if (entityDisguise != null) { + Location loc = entity.getLocation(); + loc = new Location(observer.getWorld(), ((int) (loc.getX() * 8)) / 8D, ((int) (loc.getY() * 8)) / 8D, + ((int) (loc.getZ() * 8)) / 8D); + if (loc.equals(soundLoc)) { + entitySound = DisguiseSound.getType(entity.getType().name()); + if (entitySound != null) { + Object obj = null; + if (entity instanceof LivingEntity) { + try { + // Use reflection so that this works for either int or double methods + obj = LivingEntity.class.getMethod("getHealth").invoke(entity); + if (obj instanceof Double ? (Double) obj == 0 : (Integer) obj == 0) { + soundType = SoundType.DEATH; + } else { + obj = null; + } + } catch (Exception e) { + e.printStackTrace(System.out); + } + } + if (obj == null) { + boolean hasInvun = false; + Object nmsEntity = ReflectionManager.getNmsEntity(entity); + try { + if (entity instanceof LivingEntity) { + hasInvun = ReflectionManager.getNmsField("Entity", "noDamageTicks").getInt( + nmsEntity) == ReflectionManager.getNmsField("EntityLiving", + "maxNoDamageTicks").getInt(nmsEntity); + } else { + hasInvun = (Boolean) ReflectionManager.getNmsMethod("Entity", "isInvulnerable", DamageSource.class) + .invoke(nmsEntity, DamageSource.GENERIC); + } + } catch (Exception ex) { + ex.printStackTrace(System.out); + } + soundType = entitySound.getType(soundName, !hasInvun); + } + if (soundType != null) { + disguise = entityDisguise; + disguisedEntity = entity; + break; + } + } + } + } + } + if (disguise != null) { + if (disguise.isSelfDisguiseSoundsReplaced() || disguisedEntity != event.getPlayer()) { + if (disguise.isSoundsReplaced()) { + String sound = null; + DisguiseSound dSound = DisguiseSound.getType(disguise.getType().name()); + if (dSound != null) { + sound = dSound.getSound(soundType); + } + + if (sound == null) { + event.setCancelled(true); + } else { + if (sound.equals("step.grass")) { + try { + int typeId = soundLoc.getWorld().getBlockTypeIdAt(soundLoc.getBlockX(), + soundLoc.getBlockY() - 1, soundLoc.getBlockZ()); + Object block = ReflectionManager.getNmsMethod("RegistryMaterials", "a", int.class) + .invoke(ReflectionManager.getNmsField("Block", "REGISTRY").get(null), + typeId); + if (block != null) { + Object step = ReflectionManager.getNmsField("Block", "stepSound").get(block); + mods.write(0, ReflectionManager.getNmsMethod(step.getClass(), "getStepSound") + .invoke(step)); + } + } catch (Exception ex) { + ex.printStackTrace(System.out); + } + // There is no else statement. Because seriously. This should never be null. Unless + // someone is + // sending fake sounds. In which case. Why cancel it. + } else { + mods.write(0, sound); + // Time to change the pitch and volume + if (soundType == SoundType.HURT || soundType == SoundType.DEATH + || soundType == SoundType.IDLE) { + // If the volume is the default + if (mods.read(4).equals(entitySound.getDamageAndIdleSoundVolume())) { + mods.write(4, dSound.getDamageAndIdleSoundVolume()); + } + // Here I assume its the default pitch as I can't calculate if its real. + if (disguise instanceof MobDisguise && disguisedEntity instanceof LivingEntity + && ((MobDisguise) disguise).doesDisguiseAge()) { + boolean baby = false; + if (disguisedEntity instanceof Zombie) { + baby = ((Zombie) disguisedEntity).isBaby(); + } else if (disguisedEntity instanceof Ageable) { + baby = !((Ageable) disguisedEntity).isAdult(); + } + if (((MobDisguise) disguise).isAdult() == baby) { + + float pitch = (Integer) mods.read(5); + if (baby) { + // If the pitch is not the expected + if (pitch > 97 || pitch < 111) { + return; + } + pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.5F; + // Min = 1.5 + // Cap = 97.5 + // Max = 1.7 + // Cap = 110.5 + } else { + // If the pitch is not the expected + if (pitch >= 63 || pitch <= 76) { + return; + } + pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.0F; + // Min = 1 + // Cap = 63 + // Max = 1.2 + // Cap = 75.6 + } + pitch *= 63; + if (pitch < 0) { + pitch = 0; + } + if (pitch > 255) { + pitch = 255; + } + mods.write(5, (int) pitch); + } + } + } + } + } + } + } + } + } else if (event.getPacketType() == PacketType.Play.Server.ENTITY_STATUS) { + if ((Byte) mods.read(1) == 2) { + // It made a damage animation + Entity entity = event.getPacket().getEntityModifier(observer.getWorld()).read(0); + Disguise disguise = DisguiseAPI.getDisguise(observer, entity); + if (disguise != null && !disguise.getType().isPlayer() + && (disguise.isSelfDisguiseSoundsReplaced() || entity != event.getPlayer())) { + DisguiseSound disSound = DisguiseSound.getType(entity.getType().name()); + if (disSound == null) { + return; + } + SoundType soundType = null; Object obj = null; if (entity instanceof LivingEntity) { try { - // Use reflection so that this works for either int or double methods obj = LivingEntity.class.getMethod("getHealth").invoke(entity); if (obj instanceof Double ? (Double) obj == 0 : (Integer) obj == 0) { soundType = SoundType.DEATH; @@ -578,186 +729,58 @@ public class PacketsManager { } } if (obj == null) { - boolean hasInvun = false; - Object nmsEntity = ReflectionManager.getNmsEntity(entity); - try { - if (entity instanceof LivingEntity) { - hasInvun = ReflectionManager.getNmsField("Entity", "noDamageTicks").getInt( - nmsEntity) == ReflectionManager.getNmsField("EntityLiving", - "maxNoDamageTicks").getInt(nmsEntity); - } else { - hasInvun = (Boolean) ReflectionManager.getNmsMethod("Entity", "isInvulnerable", DamageSource.class) - .invoke(nmsEntity, DamageSource.GENERIC); - } - } catch (Exception ex) { - ex.printStackTrace(System.out); - } - soundType = entitySound.getType(soundName, !hasInvun); + soundType = SoundType.HURT; } - if (soundType != null) { - disguise = entityDisguise; - disguisedEntity = entity; - break; - } - } - } - } - } - if (disguise != null) { - if (disguise.isSelfDisguiseSoundsReplaced() || disguisedEntity != event.getPlayer()) { - if (disguise.isSoundsReplaced()) { - String sound = null; - DisguiseSound dSound = DisguiseSound.getType(disguise.getType().name()); - if (dSound != null) - sound = dSound.getSound(soundType); - - if (sound == null) { - event.setCancelled(true); - } else { - if (sound.equals("step.grass")) { - try { - int typeId = soundLoc.getWorld().getBlockTypeIdAt(soundLoc.getBlockX(), - soundLoc.getBlockY() - 1, soundLoc.getBlockZ()); - Object block = ReflectionManager.getNmsMethod("RegistryMaterials", "a", int.class) - .invoke(ReflectionManager.getNmsField("Block", "REGISTRY").get(null), - typeId); - if (block != null) { - Object step = ReflectionManager.getNmsField("Block", "stepSound").get(block); - mods.write(0, ReflectionManager.getNmsMethod(step.getClass(), "getStepSound") - .invoke(step)); - } - } catch (Exception ex) { - ex.printStackTrace(System.out); - } - // There is no else statement. Because seriously. This should never be null. Unless - // someone is - // sending fake sounds. In which case. Why cancel it. - } else { - mods.write(0, sound); - // Time to change the pitch and volume - if (soundType == SoundType.HURT || soundType == SoundType.DEATH - || soundType == SoundType.IDLE) { - // If the volume is the default - if (mods.read(4).equals(entitySound.getDamageAndIdleSoundVolume())) { - mods.write(4, dSound.getDamageAndIdleSoundVolume()); - } - // Here I assume its the default pitch as I can't calculate if its real. - if (disguise instanceof MobDisguise && disguisedEntity instanceof LivingEntity - && ((MobDisguise) disguise).doesDisguiseAge()) { - boolean baby = false; - if (disguisedEntity instanceof Zombie) { - baby = ((Zombie) disguisedEntity).isBaby(); - } else if (disguisedEntity instanceof Ageable) { - baby = !((Ageable) disguisedEntity).isAdult(); - } - if (((MobDisguise) disguise).isAdult() == baby) { - - float pitch = (Integer) mods.read(5); - if (baby) { - // If the pitch is not the expected - if (pitch > 97 || pitch < 111) - return; - pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.5F; - // Min = 1.5 - // Cap = 97.5 - // Max = 1.7 - // Cap = 110.5 - } else { - // If the pitch is not the expected - if (pitch >= 63 || pitch <= 76) - return; - pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.0F; - // Min = 1 - // Cap = 63 - // Max = 1.2 - // Cap = 75.6 - } - pitch *= 63; - if (pitch < 0) - pitch = 0; - if (pitch > 255) - pitch = 255; - mods.write(5, (int) pitch); - } - } - } - } - } - } - } - } - } else if (event.getPacketType() == PacketType.Play.Server.ENTITY_STATUS) { - if ((Byte) mods.read(1) == 2) { - // It made a damage animation - Entity entity = event.getPacket().getEntityModifier(observer.getWorld()).read(0); - Disguise disguise = DisguiseAPI.getDisguise(observer, entity); - if (disguise != null && !disguise.getType().isPlayer() - && (disguise.isSelfDisguiseSoundsReplaced() || entity != event.getPlayer())) { - DisguiseSound disSound = DisguiseSound.getType(entity.getType().name()); - if (disSound == null) - return; - SoundType soundType = null; - Object obj = null; - if (entity instanceof LivingEntity) { - try { - obj = LivingEntity.class.getMethod("getHealth").invoke(entity); - if (obj instanceof Double ? (Double) obj == 0 : (Integer) obj == 0) { - soundType = SoundType.DEATH; - } else { - obj = null; - } - } catch (Exception e) { - e.printStackTrace(System.out); - } - } - if (obj == null) { - soundType = SoundType.HURT; - } - if (disSound.getSound(soundType) == null + if (disSound.getSound(soundType) == null || (disguise.isSelfDisguiseSoundsReplaced() && entity == event.getPlayer())) { - if (disguise.isSelfDisguiseSoundsReplaced() && entity == event.getPlayer()) { - cancelSound = !cancelSound; - if (cancelSound) - return; - } - disSound = DisguiseSound.getType(disguise.getType().name()); - if (disSound != null) { - String sound = disSound.getSound(soundType); - if (sound != null) { - Location loc = entity.getLocation(); - PacketContainer packet = new PacketContainer(PacketType.Play.Server.NAMED_SOUND_EFFECT); - mods = packet.getModifier(); - mods.write(0, sound); - mods.write(1, (int) (loc.getX() * 8D)); - mods.write(2, (int) (loc.getY() * 8D)); - mods.write(3, (int) (loc.getZ() * 8D)); - mods.write(4, disSound.getDamageAndIdleSoundVolume()); - float pitch; - if (disguise instanceof MobDisguise && !((MobDisguise) disguise).isAdult()) { - pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.5F; - } else - pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.0F; - if (disguise.getType() == DisguiseType.BAT) - pitch *= 95F; - pitch *= 63; - if (pitch < 0) - pitch = 0; - if (pitch > 255) - pitch = 255; - mods.write(5, (int) pitch); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet); - } catch (InvocationTargetException e) { - e.printStackTrace(System.out); + if (disguise.isSelfDisguiseSoundsReplaced() && entity == event.getPlayer()) { + cancelSound = !cancelSound; + if (cancelSound) { + return; + } + } + disSound = DisguiseSound.getType(disguise.getType().name()); + if (disSound != null) { + String sound = disSound.getSound(soundType); + if (sound != null) { + Location loc = entity.getLocation(); + PacketContainer packet = new PacketContainer(PacketType.Play.Server.NAMED_SOUND_EFFECT); + mods = packet.getModifier(); + mods.write(0, sound); + mods.write(1, (int) (loc.getX() * 8D)); + mods.write(2, (int) (loc.getY() * 8D)); + mods.write(3, (int) (loc.getZ() * 8D)); + mods.write(4, disSound.getDamageAndIdleSoundVolume()); + float pitch; + if (disguise instanceof MobDisguise && !((MobDisguise) disguise).isAdult()) { + pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.5F; + } else { + pitch = (new Random().nextFloat() - new Random().nextFloat()) * 0.2F + 1.0F; + } + if (disguise.getType() == DisguiseType.BAT) { + pitch *= 95F; + } + pitch *= 63; + if (pitch < 0) { + pitch = 0; + } + if (pitch > 255) { + pitch = 255; + } + mods.write(5, (int) pitch); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet); + } catch (InvocationTargetException e) { + e.printStackTrace(System.out); + } + } } } } } } } - } - } - }; + }; viewDisguisesListener = new PacketAdapter(libsDisguises, ListenerPriority.HIGH, PacketType.Play.Server.NAMED_ENTITY_SPAWN, PacketType.Play.Server.ATTACH_ENTITY, PacketType.Play.Server.REL_ENTITY_MOVE, PacketType.Play.Server.ENTITY_MOVE_LOOK, @@ -766,79 +789,82 @@ public class PacketsManager { PacketType.Play.Server.ENTITY_EQUIPMENT, PacketType.Play.Server.ANIMATION, PacketType.Play.Server.BED, PacketType.Play.Server.ENTITY_EFFECT, PacketType.Play.Server.ENTITY_VELOCITY, PacketType.Play.Server.UPDATE_ATTRIBUTES, PacketType.Play.Server.ENTITY_STATUS) { - @Override - public void onPacketSending(PacketEvent event) { - if (event.isCancelled()) - return; - final Player observer = event.getPlayer(); - if (event.getPacket().getIntegers().read(0) == observer.getEntityId()) { - if (DisguiseAPI.isSelfDisguised(observer)) { - // Here I grab the packets to convert them to, So I can display them as if the disguise sent them. - PacketContainer[][] transformed = transformPacket(event.getPacket(), observer, observer); - PacketContainer[] packets = transformed == null ? null : transformed[0]; - final PacketContainer[] delayedPackets = transformed == null ? null : transformed[1]; - if (packets == null) { - packets = new PacketContainer[] { event.getPacket() }; + @Override + public void onPacketSending(PacketEvent event) { + if (event.isCancelled()) { + return; } - for (PacketContainer packet : packets) { - if (packet.getType() != PacketType.Play.Server.PLAYER_INFO) { - if (packet.equals(event.getPacket())) { - packet = packet.shallowClone(); + final Player observer = event.getPlayer(); + if (event.getPacket().getIntegers().read(0) == observer.getEntityId()) { + if (DisguiseAPI.isSelfDisguised(observer)) { + // Here I grab the packets to convert them to, So I can display them as if the disguise sent them. + PacketContainer[][] transformed = transformPacket(event.getPacket(), observer, observer); + PacketContainer[] packets = transformed == null ? null : transformed[0]; + final PacketContainer[] delayedPackets = transformed == null ? null : transformed[1]; + if (packets == null) { + packets = new PacketContainer[]{event.getPacket()}; } - packet.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId()); - } - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); - } catch (InvocationTargetException e) { - e.printStackTrace(System.out); - } - } - if (delayedPackets != null && delayedPackets.length > 0) { - Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() { - @Override - public void run() { - try { - for (PacketContainer packet : delayedPackets) { - ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); + for (PacketContainer packet : packets) { + if (packet.getType() != PacketType.Play.Server.PLAYER_INFO) { + if (packet.equals(event.getPacket())) { + packet = packet.shallowClone(); } + packet.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId()); + } + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); } catch (InvocationTargetException e) { e.printStackTrace(System.out); } } - }, 2); - } - if (event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) { - event.setPacket(event.getPacket().deepClone()); - for (WrappedWatchableObject watch : event.getPacket().getWatchableCollectionModifier().read(0)) { - if (watch.getIndex() == 0) { - byte b = (Byte) watch.getValue(); - byte a = (byte) (b | 1 << 5); - if ((b & 1 << 3) != 0) - a = (byte) (a | 1 << 3); - watch.setValue(a); + if (delayedPackets != null && delayedPackets.length > 0) { + Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() { + @Override + public void run() { + try { + for (PacketContainer packet : delayedPackets) { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet, false); + } + } catch (InvocationTargetException e) { + e.printStackTrace(System.out); + } + } + }, 2); } - } - } else if (event.getPacketType() == PacketType.Play.Server.NAMED_ENTITY_SPAWN) { - event.setCancelled(true); - PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); - StructureModifier mods = packet.getModifier(); - mods.write(0, observer.getEntityId()); - List watchableList = new ArrayList<>(); - byte b = (byte) 1 << 5; - if (observer.isSprinting()) - b = (byte) (b | 1 << 3); - watchableList.add(new WrappedWatchableObject(0, b)); - packet.getWatchableCollectionModifier().write(0, watchableList); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet); - } catch (InvocationTargetException e) { - e.printStackTrace(System.out); - } - } else if (event.getPacketType() == PacketType.Play.Server.ANIMATION) { - if (event.getPacket().getIntegers().read(1) != 2) { - event.setCancelled(true); - } - } else if (event.getPacketType() == PacketType.Play.Server.ATTACH_ENTITY + if (event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) { + event.setPacket(event.getPacket().deepClone()); + for (WrappedWatchableObject watch : event.getPacket().getWatchableCollectionModifier().read(0)) { + if (watch.getIndex() == 0) { + byte b = (Byte) watch.getValue(); + byte a = (byte) (b | 1 << 5); + if ((b & 1 << 3) != 0) { + a = (byte) (a | 1 << 3); + } + watch.setValue(a); + } + } + } else if (event.getPacketType() == PacketType.Play.Server.NAMED_ENTITY_SPAWN) { + event.setCancelled(true); + PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA); + StructureModifier mods = packet.getModifier(); + mods.write(0, observer.getEntityId()); + List watchableList = new ArrayList<>(); + byte b = (byte) 1 << 5; + if (observer.isSprinting()) { + b = (byte) (b | 1 << 3); + } + watchableList.add(new WrappedWatchableObject(0, b)); + packet.getWatchableCollectionModifier().write(0, watchableList); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(observer, packet); + } catch (InvocationTargetException e) { + e.printStackTrace(System.out); + } + } else if (event.getPacketType() == PacketType.Play.Server.ANIMATION) { + if (event.getPacket().getIntegers().read(1) != 2) { + event.setCancelled(true); + } + } else if (event.getPacketType() == PacketType.Play.Server.ATTACH_ENTITY || event.getPacketType() == PacketType.Play.Server.REL_ENTITY_MOVE || event.getPacketType() == PacketType.Play.Server.ENTITY_MOVE_LOOK || event.getPacketType() == PacketType.Play.Server.ENTITY_LOOK @@ -846,170 +872,172 @@ public class PacketsManager { || event.getPacketType() == PacketType.Play.Server.ENTITY_HEAD_ROTATION || event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT || event.getPacketType() == PacketType.Play.Server.ENTITY_EQUIPMENT) { - event.setCancelled(true); - } else if (event.getPacketType() == PacketType.Play.Server.BED) { - ReflectionManager.setAllowSleep(observer); - } else if (event.getPacketType() == PacketType.Play.Server.ENTITY_STATUS) { - Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); - if (disguise.isSelfDisguiseSoundsReplaced() && !disguise.getType().isPlayer() + event.setCancelled(true); + } else if (event.getPacketType() == PacketType.Play.Server.BED) { + ReflectionManager.setAllowSleep(observer); + } else if (event.getPacketType() == PacketType.Play.Server.ENTITY_STATUS) { + Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); + if (disguise.isSelfDisguiseSoundsReplaced() && !disguise.getType().isPlayer() && event.getPacket().getBytes().read(0) == 2) { - event.setCancelled(true); + event.setCancelled(true); + } + } } } } - } - } - }; + }; inventoryListener = new PacketAdapter(libsDisguises, ListenerPriority.HIGHEST, PacketType.Play.Server.SET_SLOT, PacketType.Play.Server.WINDOW_ITEMS, PacketType.Play.Client.HELD_ITEM_SLOT, PacketType.Play.Client.SET_CREATIVE_SLOT, PacketType.Play.Client.WINDOW_CLICK) { - @Override - public void onPacketReceiving(final PacketEvent event) { - if (event.isCancelled()) - return; - if (!(event.getPlayer() instanceof com.comphenix.net.sf.cglib.proxy.Factory) + @Override + public void onPacketReceiving(final PacketEvent event) { + if (event.isCancelled()) { + return; + } + if (!(event.getPlayer() instanceof com.comphenix.net.sf.cglib.proxy.Factory) && event.getPlayer().getVehicle() == null) { - Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); - // If player is disguised, views self disguises and has a inventory modifier - if (disguise != null && disguise.isSelfDisguiseVisible() + Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); + // If player is disguised, views self disguises and has a inventory modifier + if (disguise != null && disguise.isSelfDisguiseVisible() && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) { - // If they are in creative and clicked on a slot - if (event.getPacketType() == PacketType.Play.Client.SET_CREATIVE_SLOT) { - int slot = event.getPacket().getIntegers().read(0); - if (slot >= 5 && slot <= 8) { - if (disguise.isHidingArmorFromSelf()) { - int armorSlot = Math.abs((slot - 5) - 3); - org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory().getArmorContents()[armorSlot]; - if (item != null && item.getType() != Material.AIR) { - PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); - StructureModifier mods = packet.getModifier(); - mods.write(0, 0); - mods.write(1, slot); - mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, - false); - } catch (InvocationTargetException e) { - e.printStackTrace(System.out); + // If they are in creative and clicked on a slot + if (event.getPacketType() == PacketType.Play.Client.SET_CREATIVE_SLOT) { + int slot = event.getPacket().getIntegers().read(0); + if (slot >= 5 && slot <= 8) { + if (disguise.isHidingArmorFromSelf()) { + int armorSlot = Math.abs((slot - 5) - 3); + org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory().getArmorContents()[armorSlot]; + if (item != null && item.getType() != Material.AIR) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); + StructureModifier mods = packet.getModifier(); + mods.write(0, 0); + mods.write(1, slot); + mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, + false); + } catch (InvocationTargetException e) { + e.printStackTrace(System.out); + } + } + } + } else if (slot >= 36 && slot <= 44) { + if (disguise.isHidingHeldItemFromSelf()) { + int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); + if (slot + 36 == currentSlot) { + org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); + if (item != null && item.getType() != Material.AIR) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); + StructureModifier mods = packet.getModifier(); + mods.write(0, 0); + mods.write(1, slot); + mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, + false); + } catch (InvocationTargetException e) { + e.printStackTrace(System.out); + } + } + } } } - } - } else if (slot >= 36 && slot <= 44) { - if (disguise.isHidingHeldItemFromSelf()) { - int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); - if (slot + 36 == currentSlot) { - org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); - if (item != null && item.getType() != Material.AIR) { + } // If the player switched item, aka he moved from slot 1 to slot 2 + else if (event.getPacketType() == PacketType.Play.Client.HELD_ITEM_SLOT) { + if (disguise.isHidingHeldItemFromSelf()) { + // From logging, it seems that both bukkit and nms uses the same thing for the slot switching. + // 0 1 2 3 - 8 + // If the packet is coming, then I need to replace the item they are switching to + // As for the old item, I need to restore it. + org.bukkit.inventory.ItemStack currentlyHeld = event.getPlayer().getItemInHand(); + // If his old weapon isn't air + if (currentlyHeld != null && currentlyHeld.getType() != Material.AIR) { PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); StructureModifier mods = packet.getModifier(); mods.write(0, 0); - mods.write(1, slot); + mods.write(1, event.getPlayer().getInventory().getHeldItemSlot() + 36); + mods.write(2, ReflectionManager.getNmsItem(currentlyHeld)); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); + } catch (InvocationTargetException e) { + e.printStackTrace(System.out); + } + } + org.bukkit.inventory.ItemStack newHeld = event.getPlayer().getInventory() + .getItem(event.getPacket().getIntegers().read(0)); + // If his new weapon isn't air either! + if (newHeld != null && newHeld.getType() != Material.AIR) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); + StructureModifier mods = packet.getModifier(); + mods.write(0, 0); + mods.write(1, event.getPacket().getIntegers().read(0) + 36); mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); try { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, - false); + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); } catch (InvocationTargetException e) { e.printStackTrace(System.out); } } } - } - } - } - // If the player switched item, aka he moved from slot 1 to slot 2 - else if (event.getPacketType() == PacketType.Play.Client.HELD_ITEM_SLOT) { - if (disguise.isHidingHeldItemFromSelf()) { - // From logging, it seems that both bukkit and nms uses the same thing for the slot switching. - // 0 1 2 3 - 8 - // If the packet is coming, then I need to replace the item they are switching to - // As for the old item, I need to restore it. - org.bukkit.inventory.ItemStack currentlyHeld = event.getPlayer().getItemInHand(); - // If his old weapon isn't air - if (currentlyHeld != null && currentlyHeld.getType() != Material.AIR) { - PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); - StructureModifier mods = packet.getModifier(); - mods.write(0, 0); - mods.write(1, event.getPlayer().getInventory().getHeldItemSlot() + 36); - mods.write(2, ReflectionManager.getNmsItem(currentlyHeld)); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); - } catch (InvocationTargetException e) { - e.printStackTrace(System.out); - } - } - org.bukkit.inventory.ItemStack newHeld = event.getPlayer().getInventory() - .getItem(event.getPacket().getIntegers().read(0)); - // If his new weapon isn't air either! - if (newHeld != null && newHeld.getType() != Material.AIR) { - PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); - StructureModifier mods = packet.getModifier(); - mods.write(0, 0); - mods.write(1, event.getPacket().getIntegers().read(0) + 36); - mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, false); - } catch (InvocationTargetException e) { - e.printStackTrace(System.out); - } - } - } - } else if (event.getPacketType() == PacketType.Play.Client.WINDOW_CLICK) { - int slot = event.getPacket().getIntegers().read(1); - org.bukkit.inventory.ItemStack clickedItem; - if (event.getPacket().getIntegers().read(3) == 1) { - // Its a shift click - clickedItem = event.getPacket().getItemModifier().read(0); - if (clickedItem != null && clickedItem.getType() != Material.AIR) { - // Rather than predict the clients actions - // Lets just update the entire inventory.. - Bukkit.getScheduler().runTask(libsDisguises, new Runnable() { - @Override - public void run() { - event.getPlayer().updateInventory(); + } else if (event.getPacketType() == PacketType.Play.Client.WINDOW_CLICK) { + int slot = event.getPacket().getIntegers().read(1); + org.bukkit.inventory.ItemStack clickedItem; + if (event.getPacket().getIntegers().read(3) == 1) { + // Its a shift click + clickedItem = event.getPacket().getItemModifier().read(0); + if (clickedItem != null && clickedItem.getType() != Material.AIR) { + // Rather than predict the clients actions + // Lets just update the entire inventory.. + Bukkit.getScheduler().runTask(libsDisguises, new Runnable() { + @Override + public void run() { + event.getPlayer().updateInventory(); + } + }); } - }); - } - return; - } else { - // If its not a player inventory click - // Shift clicking is exempted for the item in hand.. - if (event.getPacket().getIntegers().read(0) != 0) { - return; - } - clickedItem = event.getPlayer().getItemOnCursor(); - } - if (clickedItem != null && clickedItem.getType() != Material.AIR) { - // If the slot is a armor slot - if (slot >= 5 && slot <= 8) { - if (disguise.isHidingArmorFromSelf()) { - PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); - StructureModifier mods = packet.getModifier(); - mods.write(0, 0); - mods.write(1, slot); - mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, - false); - } catch (InvocationTargetException e) { - e.printStackTrace(System.out); + return; + } else { + // If its not a player inventory click + // Shift clicking is exempted for the item in hand.. + if (event.getPacket().getIntegers().read(0) != 0) { + return; } + clickedItem = event.getPlayer().getItemOnCursor(); } - // Else if its a hotbar slot - } else if (slot >= 36 && slot <= 44) { - if (disguise.isHidingHeldItemFromSelf()) { - int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); - // Check if the player is on the same slot as the slot that its setting - if (slot == currentSlot + 36) { - PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); - StructureModifier mods = packet.getModifier(); - mods.write(0, 0); - mods.write(1, slot); - mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, - false); - } catch (InvocationTargetException e) { - e.printStackTrace(System.out); + if (clickedItem != null && clickedItem.getType() != Material.AIR) { + // If the slot is a armor slot + if (slot >= 5 && slot <= 8) { + if (disguise.isHidingArmorFromSelf()) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); + StructureModifier mods = packet.getModifier(); + mods.write(0, 0); + mods.write(1, slot); + mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, + false); + } catch (InvocationTargetException e) { + e.printStackTrace(System.out); + } + } + // Else if its a hotbar slot + } else if (slot >= 36 && slot <= 44) { + if (disguise.isHidingHeldItemFromSelf()) { + int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); + // Check if the player is on the same slot as the slot that its setting + if (slot == currentSlot + 36) { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.SET_SLOT); + StructureModifier mods = packet.getModifier(); + mods.write(0, 0); + mods.write(1, slot); + mods.write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); + try { + ProtocolLibrary.getProtocolManager().sendServerPacket(event.getPlayer(), packet, + false); + } catch (InvocationTargetException e) { + e.printStackTrace(System.out); + } + } } } } @@ -1017,90 +1045,88 @@ public class PacketsManager { } } } - } - } - @Override - public void onPacketSending(PacketEvent event) { - // If the inventory is the players inventory - if (!(event.getPlayer() instanceof com.comphenix.net.sf.cglib.proxy.Factory) + @Override + public void onPacketSending(PacketEvent event) { + // If the inventory is the players inventory + if (!(event.getPlayer() instanceof com.comphenix.net.sf.cglib.proxy.Factory) && event.getPlayer().getVehicle() == null && event.getPacket().getIntegers().read(0) == 0) { - Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); - // If the player is disguised, views self disguises and is hiding a item. - if (disguise != null && disguise.isSelfDisguiseVisible() + Disguise disguise = DisguiseAPI.getDisguise(event.getPlayer(), event.getPlayer()); + // If the player is disguised, views self disguises and is hiding a item. + if (disguise != null && disguise.isSelfDisguiseVisible() && (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf())) { - // If the server is setting the slot - // Need to set it to air if its in a place it shouldn't be. - // Things such as picking up a item, spawned in item. Plugin sets the item. etc. Will fire this - /** - * Done - */ - if (event.getPacketType() == PacketType.Play.Server.SET_SLOT) { - // The raw slot - // nms code has the start of the hotbar being 36. - int slot = event.getPacket().getIntegers().read(1); - // If the slot is a armor slot - if (slot >= 5 && slot <= 8) { - if (disguise.isHidingArmorFromSelf()) { - // Get the bukkit armor slot! - int armorSlot = Math.abs((slot - 5) - 3); - org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory().getArmorContents()[armorSlot]; - if (item != null && item.getType() != Material.AIR) { - event.setPacket(event.getPacket().shallowClone()); - event.getPacket().getModifier() + // If the server is setting the slot + // Need to set it to air if its in a place it shouldn't be. + // Things such as picking up a item, spawned in item. Plugin sets the item. etc. Will fire this + /** + * Done + */ + if (event.getPacketType() == PacketType.Play.Server.SET_SLOT) { + // The raw slot + // nms code has the start of the hotbar being 36. + int slot = event.getPacket().getIntegers().read(1); + // If the slot is a armor slot + if (slot >= 5 && slot <= 8) { + if (disguise.isHidingArmorFromSelf()) { + // Get the bukkit armor slot! + int armorSlot = Math.abs((slot - 5) - 3); + org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory().getArmorContents()[armorSlot]; + if (item != null && item.getType() != Material.AIR) { + event.setPacket(event.getPacket().shallowClone()); + event.getPacket().getModifier() .write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - } - } - // Else if its a hotbar slot - } else if (slot >= 36 && slot <= 44) { - if (disguise.isHidingHeldItemFromSelf()) { - int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); - // Check if the player is on the same slot as the slot that its setting - if (slot == currentSlot + 36) { - org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); - if (item != null && item.getType() != Material.AIR) { - event.setPacket(event.getPacket().shallowClone()); - event.getPacket() + } + } + // Else if its a hotbar slot + } else if (slot >= 36 && slot <= 44) { + if (disguise.isHidingHeldItemFromSelf()) { + int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); + // Check if the player is on the same slot as the slot that its setting + if (slot == currentSlot + 36) { + org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); + if (item != null && item.getType() != Material.AIR) { + event.setPacket(event.getPacket().shallowClone()); + event.getPacket() .getModifier() .write(2, ReflectionManager.getNmsItem(new org.bukkit.inventory.ItemStack(0))); - } - } - } - } - } else if (event.getPacketType() == PacketType.Play.Server.WINDOW_ITEMS) { - event.setPacket(event.getPacket().deepClone()); - StructureModifier mods = event.getPacket().getItemArrayModifier(); - ItemStack[] items = mods.read(0); - for (int slot = 0; slot < items.length; slot++) { - if (slot >= 5 && slot <= 8) { - if (disguise.isHidingArmorFromSelf()) { - // Get the bukkit armor slot! - int armorSlot = Math.abs((slot - 5) - 3); - org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory().getArmorContents()[armorSlot]; - if (item != null && item.getType() != Material.AIR) { - items[slot] = new org.bukkit.inventory.ItemStack(0); - } - } - // Else if its a hotbar slot - } else if (slot >= 36 && slot <= 44) { - if (disguise.isHidingHeldItemFromSelf()) { - int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); - // Check if the player is on the same slot as the slot that its setting - if (slot == currentSlot + 36) { - org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); - if (item != null && item.getType() != Material.AIR) { - items[slot] = new org.bukkit.inventory.ItemStack(0); + } } } } + } else if (event.getPacketType() == PacketType.Play.Server.WINDOW_ITEMS) { + event.setPacket(event.getPacket().deepClone()); + StructureModifier mods = event.getPacket().getItemArrayModifier(); + ItemStack[] items = mods.read(0); + for (int slot = 0; slot < items.length; slot++) { + if (slot >= 5 && slot <= 8) { + if (disguise.isHidingArmorFromSelf()) { + // Get the bukkit armor slot! + int armorSlot = Math.abs((slot - 5) - 3); + org.bukkit.inventory.ItemStack item = event.getPlayer().getInventory().getArmorContents()[armorSlot]; + if (item != null && item.getType() != Material.AIR) { + items[slot] = new org.bukkit.inventory.ItemStack(0); + } + } + // Else if its a hotbar slot + } else if (slot >= 36 && slot <= 44) { + if (disguise.isHidingHeldItemFromSelf()) { + int currentSlot = event.getPlayer().getInventory().getHeldItemSlot(); + // Check if the player is on the same slot as the slot that its setting + if (slot == currentSlot + 36) { + org.bukkit.inventory.ItemStack item = event.getPlayer().getItemInHand(); + if (item != null && item.getType() != Material.AIR) { + items[slot] = new org.bukkit.inventory.ItemStack(0); + } + } + } + } + } + mods.write(0, items); } } - mods.write(0, items); } } - } - } - }; + }; } public static boolean isHearDisguisesEnabled() { @@ -1197,8 +1223,9 @@ public class PacketsManager { mainListener = new PacketAdapter(libsDisguises, ListenerPriority.HIGH, packetsToListen) { @Override public void onPacketSending(PacketEvent event) { - if (event.isCancelled()) + if (event.isCancelled()) { return; + } final Player observer = event.getPlayer(); // First get the entity, the one sending this packet StructureModifier entityModifer = event.getPacket().getEntityModifier(observer.getWorld()); @@ -1206,8 +1233,9 @@ public class PacketsManager { .read((PacketType.Play.Server.COLLECT == event.getPacketType() ? 1 : 0)); // If the entity is the same as the sender. Don't disguise! // Prevents problems and there is no advantage to be gained. - if (entity == observer) + if (entity == observer) { return; + } PacketContainer[][] packets = transformPacket(event.getPacket(), event.getPlayer(), entity); if (packets != null) { event.setCancelled(true); @@ -1267,8 +1295,12 @@ public class PacketsManager { } /** - * Transform the packet magically into the one I have always dreamed off. My true luv!!! This will return null if its not - * transformed + * Transform the packet magically into the one I have always dreamed off. My true luv!!! This will return null if its not transformed + * + * @param sentPacket + * @param observer + * @param entity + * @return */ public static PacketContainer[][] transformPacket(PacketContainer sentPacket, Player observer, Entity entity) { PacketContainer[] packets = null; @@ -1277,7 +1309,7 @@ public class PacketsManager { Disguise disguise = DisguiseAPI.getDisguise(observer, entity); // If disguised. if (disguise != null) { - packets = new PacketContainer[] { sentPacket }; + packets = new PacketContainer[]{sentPacket}; // This packet sends attributes if (sentPacket.getType() == PacketType.Play.Server.UPDATE_ATTRIBUTES) { @@ -1312,9 +1344,7 @@ public class PacketsManager { packets = new PacketContainer[0]; } } - } - - // Else if the packet is sending entity metadata + } // Else if the packet is sending entity metadata else if (sentPacket.getType() == PacketType.Play.Server.ENTITY_METADATA) { if (DisguiseConfig.isMetadataPacketsEnabled()) { List watchableObjects = disguise.getWatcher().convert( @@ -1327,9 +1357,7 @@ public class PacketsManager { } else { packets = new PacketContainer[0]; } - } - - // Else if the packet is spawning.. + } // Else if the packet is spawning.. else if (sentPacket.getType() == PacketType.Play.Server.NAMED_ENTITY_SPAWN || sentPacket.getType() == PacketType.Play.Server.SPAWN_ENTITY_LIVING || sentPacket.getType() == PacketType.Play.Server.SPAWN_ENTITY_EXPERIENCE_ORB @@ -1338,19 +1366,15 @@ public class PacketsManager { PacketContainer[][] spawnPackets = constructSpawnPackets(observer, disguise, entity); packets = spawnPackets[0]; delayedPackets = spawnPackets[1]; - } - - // Else if the disguise is attempting to send players a forbidden packet + } // Else if the disguise is attempting to send players a forbidden packet else if (sentPacket.getType() == PacketType.Play.Server.ANIMATION) { if (disguise.getType().isMisc() || (packets[0].getIntegers().read(1) == 2 && (!disguise.getType() - .isPlayer() || (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise - .getWatcher()).isSleeping())))) { + .isPlayer() || (DisguiseConfig.isBedPacketsEnabled() && ((PlayerWatcher) disguise + .getWatcher()).isSleeping())))) { packets = new PacketContainer[0]; } - } - - else if (sentPacket.getType() == PacketType.Play.Server.COLLECT) { + } else if (sentPacket.getType() == PacketType.Play.Server.COLLECT) { if (disguise.getType().isMisc()) { packets = new PacketContainer[0]; } else if (DisguiseConfig.isBedPacketsEnabled() && disguise.getType().isPlayer() @@ -1359,11 +1383,9 @@ public class PacketsManager { StructureModifier mods = newPacket.getIntegers(); mods.write(0, disguise.getEntity().getEntityId()); mods.write(1, 3); - packets = new PacketContainer[] { newPacket, sentPacket }; + packets = new PacketContainer[]{newPacket, sentPacket}; } - } - - // Else if the disguise is moving. + } // Else if the disguise is moving. else if (sentPacket.getType() == PacketType.Play.Server.ENTITY_MOVE_LOOK || sentPacket.getType() == PacketType.Play.Server.ENTITY_LOOK || sentPacket.getType() == PacketType.Play.Server.ENTITY_TELEPORT @@ -1393,9 +1415,9 @@ public class PacketsManager { packets[0] = sentPacket.shallowClone(); StructureModifier bytes = packets[0].getBytes(); boolean tele = sentPacket.getType() == PacketType.Play.Server.ENTITY_TELEPORT; - byte yawValue = (Byte) bytes.read(tele ? 0 : 3); + byte yawValue = bytes.read(tele ? 0 : 3); bytes.write(tele ? 0 : 3, getYaw(disguise.getType(), entity.getType(), yawValue)); - byte pitchValue = (Byte) bytes.read(tele ? 1 : 4); + byte pitchValue = bytes.read(tele ? 1 : 4); bytes.write(tele ? 1 : 4, getPitch(disguise.getType(), DisguiseType.getType(entity.getType()), pitchValue)); if (tele && disguise.getType() == DisguiseType.ITEM_FRAME) { @@ -1412,16 +1434,15 @@ public class PacketsManager { double y = getYModifier(entity, disguise); if (y != 0) { y *= 32; - ints.write(2, (Integer) ints.read(2) + (int) Math.floor(y)); + ints.write(2, ints.read(2) + (int) Math.floor(y)); } } } - } - - else if (sentPacket.getType() == PacketType.Play.Server.ENTITY_EQUIPMENT) { + } else if (sentPacket.getType() == PacketType.Play.Server.ENTITY_EQUIPMENT) { int slot = (Integer) packets[0].getModifier().read(1) - 1; - if (slot < 0) + if (slot < 0) { slot = 4; + } org.bukkit.inventory.ItemStack itemstack = disguise.getWatcher().getItemStack(slot); if (itemstack != null) { packets[0] = packets[0].shallowClone(); @@ -1456,26 +1477,20 @@ public class PacketsManager { } // Send the unblock before the itemstack change so that the 2nd metadata packet works. Why? Scheduler // delay. - packets = new PacketContainer[] { packetUnblock, packets[0], packetBlock }; + packets = new PacketContainer[]{packetUnblock, packets[0], packetBlock}; // Silly mojang made the right clicking datawatcher value only valid for one use. So I have to reset // it. } } - } - - else if (sentPacket.getType() == PacketType.Play.Server.BED) { + } else if (sentPacket.getType() == PacketType.Play.Server.BED) { if (!disguise.getType().isPlayer()) { packets = new PacketContainer[0]; } - } - - else if (sentPacket.getType() == PacketType.Play.Server.ENTITY_STATUS) { + } else if (sentPacket.getType() == PacketType.Play.Server.ENTITY_STATUS) { if (packets[0].getBytes().read(0) == (byte) 3) { packets = new PacketContainer[0]; } - } - - else if (sentPacket.getType() == PacketType.Play.Server.ENTITY_HEAD_ROTATION) { + } else if (sentPacket.getType() == PacketType.Play.Server.ENTITY_HEAD_ROTATION) { if (disguise.getType().isPlayer() && entity.getType() != EntityType.PLAYER) { Location loc = entity.getLocation(); byte pitch = getPitch(disguise.getType(), DisguiseType.getType(entity.getType()), @@ -1489,11 +1504,9 @@ public class PacketsManager { look.getIntegers().write(0, entity.getEntityId()); look.getBytes().write(3, yaw); look.getBytes().write(4, pitch); - packets = new PacketContainer[] { look, rotation }; + packets = new PacketContainer[]{look, rotation}; } - } - - else { + } else { packets = null; } @@ -1501,6 +1514,6 @@ public class PacketsManager { } catch (Exception e) { e.printStackTrace(System.out); } - return packets == null ? null : new PacketContainer[][] { packets, delayedPackets }; + return packets == null ? null : new PacketContainer[][]{packets, delayedPackets}; } } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java index 4a39fecb..654eb5f9 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -31,8 +31,10 @@ import org.bukkit.potion.PotionEffect; public class ReflectionManager { public enum LibVersion { + V1_8; private static LibVersion currentVersion; + static { //String mcVersion = Bukkit.getVersion().split("MC: ")[1].replace(")", ""); currentVersion = V1_8; @@ -59,8 +61,7 @@ public class ReflectionManager { private static Map> ForgeFieldMappings; /** - * Map of Forge fully qualified class names to a map from mc-dev method names to a map from method signatures to Forge method - * names. + * Map of Forge fully qualified class names to a map from mc-dev method names to a map from method signatures to Forge method names. */ private static Map>> ForgeMethodMappings; private static final Method ihmGet; @@ -82,7 +83,7 @@ public class ReflectionManager { final String nameseg_class = "a-zA-Z0-9$_"; final String fqn_class = nameseg_class + "/"; - primitiveTypes = ImmutableMap., String> builder().put(boolean.class, "Z").put(byte.class, "B") + primitiveTypes = ImmutableMap., String>builder().put(boolean.class, "Z").put(byte.class, "B") .put(char.class, "C").put(short.class, "S").put(int.class, "I").put(long.class, "J").put(float.class, "F") .put(double.class, "D").put(void.class, "V").build(); @@ -191,7 +192,7 @@ public class ReflectionManager { trackerField = getNmsField("WorldServer", "tracker"); entitiesField = getNmsField("EntityTracker", "trackedEntities"); ihmGet = getNmsMethod("IntHashMap", "get", int.class); - boundingBoxConstructor = getNmsConstructor("AxisAlignedBB",double.class, double.class, double.class, + boundingBoxConstructor = getNmsConstructor("AxisAlignedBB", double.class, double.class, double.class, double.class, double.class, double.class); setBoundingBoxMethod = getNmsMethod("Entity", "a", getNmsClass("AxisAlignedBB")); } @@ -208,7 +209,7 @@ public class ReflectionManager { WrappedGameProfile gameProfile = getGameProfile(null, "LibsDisguises"); entityObject = entityClass.getConstructor(getNmsClass("MinecraftServer"), getNmsClass("WorldServer"), gameProfile.getHandleType(), playerinteractmanager.getClass()).newInstance(minecraftServer, world, - gameProfile.getHandle(), playerinteractmanager); + gameProfile.getHandle(), playerinteractmanager); } else if (entityName.equals("EnderPearl")) { entityObject = entityClass.getConstructor(getNmsClass("World"), getNmsClass("EntityLiving")) .newInstance(world, createEntityInstance("Cow")); @@ -249,26 +250,26 @@ public class ReflectionManager { if (field.getType().getSimpleName().equals("double")) { stage++; switch (stage) { - case 1: - x -= field.getDouble(boundingBox); - break; - case 2: - y -= field.getDouble(boundingBox); - break; - case 3: - z -= field.getDouble(boundingBox); - break; - case 4: - x += field.getDouble(boundingBox); - break; - case 5: - y += field.getDouble(boundingBox); - break; - case 6: - z += field.getDouble(boundingBox); - break; - default: - throw new Exception("Error while setting the bounding box, more doubles than I thought??"); + case 1: + x -= field.getDouble(boundingBox); + break; + case 2: + y -= field.getDouble(boundingBox); + break; + case 3: + z -= field.getDouble(boundingBox); + break; + case 4: + x += field.getDouble(boundingBox); + break; + case 5: + y += field.getDouble(boundingBox); + break; + case 6: + z += field.getDouble(boundingBox); + break; + default: + throw new Exception("Error while setting the bounding box, more doubles than I thought??"); } } } @@ -382,7 +383,7 @@ public class ReflectionManager { return null; } - public static WrappedGameProfile getGameProfile(Player player) { + public static WrappedGameProfile getGameProfile(Player player) { return WrappedGameProfile.fromPlayer(player); } @@ -519,7 +520,7 @@ public class ReflectionManager { float length = getNmsField("Entity", "length").getFloat(getNmsEntity(entity)); float width = getNmsField("Entity", "width").getFloat(getNmsEntity(entity)); float height = (Float) getNmsMethod("Entity", "getHeadHeight").invoke(getNmsEntity(entity)); - return new float[] { length, width, height }; + return new float[]{length, width, height}; } catch (Exception ex) { ex.printStackTrace(System.out); } @@ -573,7 +574,7 @@ public class ReflectionManager { .getClass() .getMethod("findProfilesByNames", String[].class, agent.getClass(), Class.forName("com.mojang.authlib.ProfileLookupCallback")) - .invoke(profileRepo, new String[] { playername }, agent, callback); + .invoke(profileRepo, new String[]{playername}, agent, callback); if (callback.getGameProfile() != null) { return callback.getGameProfile(); } @@ -607,10 +608,8 @@ public class ReflectionManager { public static void setAllowSleep(Player player) { try { /** - Object nmsEntity = getNmsEntity(player); - Object connection = getNmsField(nmsEntity.getClass(), "playerConnection").get(nmsEntity); - Field check = getNmsField(connection.getClass(), "checkMovement"); - check.setBoolean(connection, true); **/ + * Object nmsEntity = getNmsEntity(player); Object connection = getNmsField(nmsEntity.getClass(), "playerConnection").get(nmsEntity); Field check = getNmsField(connection.getClass(), "checkMovement"); check.setBoolean(connection, true); * + */ } catch (Exception ex) { ex.printStackTrace(System.out); } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/UpdateChecker.java b/src/main/java/me/libraryaddict/disguise/utilities/UpdateChecker.java index b565da71..2cf27971 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/UpdateChecker.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/UpdateChecker.java @@ -7,6 +7,7 @@ import java.net.URL; import java.util.regex.Pattern; public class UpdateChecker { + private String latestVersion; private boolean checkHigher(String currentVersion, String newVersion) { @@ -51,8 +52,9 @@ public class UpdateChecker { private String toReadable(String version) { String[] split = Pattern.compile(".", Pattern.LITERAL).split(version.replace("v", "")); version = ""; - for (String s : split) + for (String s : split) { version += String.format("%4s", s); + } return version; } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 3e0cd437..db79e105 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -72,9 +72,9 @@ DisguiseCloneSize: 3 # These disguises, as normal will not persist after a server restart. # There is also no EntityDeath option as entities do not revive after death. KeepDisguises: - EntityDespawn: false - PlayerDeath: false - PlayerLogout: false + EntityDespawn: false + PlayerDeath: false + PlayerLogout: false # This controls if a entitys max health is determined by the entity, or by the disguise. # Wither is 200, a player is 20. With this enabled, a player disguised as a wither will have the boss bar health accurate to the players health. @@ -97,31 +97,31 @@ ContactMojangServers: true # This will help performance, especially with CPU # Due to safety reasons, self disguises can never have their packets disabled. PacketsEnabled: - # This disables the animation packet. If a disguised entity sends a animation packet and they are using a non-living disguise. People will crash. - # Disabling this also means that if a player disguised as a non-player leaves a bug. People will crash - Animation: true - # Disabling this means that you can't use the setSleeping option on a player disguise. Also you will crash anyone watching when you try to sleep in a bed if disguised as a non-player - # This also sends a chunk packet at key positions else it doesn't work for 1.8. Lazyness means it does it for older versions too currently. - Bed: true - # This disguises the collect packet. If a living entity disguised as a non-living entity picks up a item. People will crash. This fixes it - # This also fixes people crashing if a item disguised as a sleeping player is picked up - Only true if Bed is enabled as well - Collect: true - # This disables a fix for when a disguised entity wearing armor dies, if the disguise can wear armor. It drops unpickupable items to anyone watching. - EntityStatus: true - # Entity equipment is the packets that are sent to ensure that a disguise has or doesn't have armor, and their held item. - # Disabling this means that any disguises which can wear armor or hold items will show the armor/held item that the disguised is wearing. - Equipment: true - # This doesn't actually disable the packet. It would introduce problems. Instead it does the next best thing and caches the data. - # This means that entity metadata will not change, and will only be sent in the spawn packet. - # This is good if performance is extremely in need. - # This is bad to disable unless you are ONLY going to use the disguises for decorations. - # To be honest. This is basically "Disable entity animations". That option is called 'AddEntityAnimations' in the config but unlike that, this is always in effect. - # Animations set by use of the api or through the disguise command are still in effect. - Metadata: true - # Movement packets are the biggest cpu hit. These are majorly used to ensure that the disguises facing direction isn't bugged up. - # If you are using the Item_Frame disguise, when a packet is sent (Roughly every 2min) the disguise will bug up until they move. - Movement: true - # Disable this if you don't mind crashing everytime you see someone riding something disguised as a non-living entity - Riding: true - # When disguised as a wither skull, it sends a look packet every tick so that the wither skull is facing the right way. - WitherSkull: true + # This disables the animation packet. If a disguised entity sends a animation packet and they are using a non-living disguise. People will crash. + # Disabling this also means that if a player disguised as a non-player leaves a bug. People will crash + Animation: true + # Disabling this means that you can't use the setSleeping option on a player disguise. Also you will crash anyone watching when you try to sleep in a bed if disguised as a non-player + # This also sends a chunk packet at key positions else it doesn't work for 1.8. Lazyness means it does it for older versions too currently. + Bed: true + # This disguises the collect packet. If a living entity disguised as a non-living entity picks up a item. People will crash. This fixes it + # This also fixes people crashing if a item disguised as a sleeping player is picked up - Only true if Bed is enabled as well + Collect: true + # This disables a fix for when a disguised entity wearing armor dies, if the disguise can wear armor. It drops unpickupable items to anyone watching. + EntityStatus: true + # Entity equipment is the packets that are sent to ensure that a disguise has or doesn't have armor, and their held item. + # Disabling this means that any disguises which can wear armor or hold items will show the armor/held item that the disguised is wearing. + Equipment: true + # This doesn't actually disable the packet. It would introduce problems. Instead it does the next best thing and caches the data. + # This means that entity metadata will not change, and will only be sent in the spawn packet. + # This is good if performance is extremely in need. + # This is bad to disable unless you are ONLY going to use the disguises for decorations. + # To be honest. This is basically "Disable entity animations". That option is called 'AddEntityAnimations' in the config but unlike that, this is always in effect. + # Animations set by use of the api or through the disguise command are still in effect. + Metadata: true + # Movement packets are the biggest cpu hit. These are majorly used to ensure that the disguises facing direction isn't bugged up. + # If you are using the Item_Frame disguise, when a packet is sent (Roughly every 2min) the disguise will bug up until they move. + Movement: true + # Disable this if you don't mind crashing everytime you see someone riding something disguised as a non-living entity + Riding: true + # When disguised as a wither skull, it sends a look packet every tick so that the wither skull is facing the right way. + WitherSkull: true diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index e41f3e1a..a5659874 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: LibsDisguises main: me.libraryaddict.disguise.LibsDisguises -version: 8.6.3 +version: 8.6.4 author: libraryaddict authors: [Byteflux, Navid K.] depend: [ProtocolLib] @@ -54,6 +54,9 @@ commands: description: Toggle seeing your own disguise on or off. permissions: + libsdisguises.reload: + description: Allows the user to reload LibsDisguises. + default: op libsdisguises.seethrough: description: Allows player to see through disguises. default: false @@ -97,4 +100,3 @@ permissions: description: See the /undisguiseradius command in tab-completion libsdisguises.seecmd.disguiseclone: description: See the /disguiseclone command in tab-completion -