package me.libraryaddict.disguise; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.UUID; import me.libraryaddict.disguise.disguisetypes.AnimalColor; import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.FlagWatcher; import me.libraryaddict.disguise.disguisetypes.MiscDisguise; import me.libraryaddict.disguise.disguisetypes.MobDisguise; import me.libraryaddict.disguise.disguisetypes.PlayerDisguise; import me.libraryaddict.disguise.disguisetypes.TargetedDisguise; import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType; import me.libraryaddict.disguise.disguisetypes.watchers.HorseWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; import me.libraryaddict.disguise.events.DisguiseEvent; import me.libraryaddict.disguise.events.UndisguiseEvent; import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.ReflectionManager; import org.bukkit.Bukkit; import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; public class DisguiseAPI { public static Disguise constructDisguise(Entity entity) { return constructDisguise(entity, true, true, true); } public static Disguise constructDisguise(Entity entity, boolean doEnquipment, boolean doSneak, boolean doSprint) { DisguiseType disguiseType = DisguiseType.getType(entity); Disguise disguise; if (disguiseType.isMisc()) { disguise = new MiscDisguise(disguiseType); } else if (disguiseType.isMob()) { disguise = new MobDisguise(disguiseType); } else { disguise = new PlayerDisguise(((Player) entity).getName()); } FlagWatcher watcher = disguise.getWatcher(); if (entity instanceof LivingEntity) { for (PotionEffect effect : ((LivingEntity) entity).getActivePotionEffects()) { ((LivingWatcher) watcher).addPotionEffect(effect.getType()); if (effect.getType().getName().equals("INVISIBILITY")) { watcher.setInvisible(true); } } } if (entity.getFireTicks() > 0) { watcher.setBurning(true); } if (doEnquipment && entity instanceof LivingEntity) { EntityEquipment enquip = ((LivingEntity) entity).getEquipment(); watcher.setArmor(enquip.getArmorContents()); watcher.setItemInHand(enquip.getItemInHand()); if (disguiseType.getEntityType().name().equals("HORSE")) { try { Object horseInv = entity.getClass().getMethod("getInventory").invoke(entity); Object item = horseInv.getClass().getMethod("getSaddle").invoke(horseInv); if (item != null && ((ItemStack) item).getType() == Material.SADDLE) { ((HorseWatcher) watcher).setSaddled(true); } ((HorseWatcher) watcher) .setHorseArmor((ItemStack) horseInv.getClass().getMethod("getArmor").invoke(horseInv)); } catch (Exception ex) { ex.printStackTrace(); } } } for (Method method : entity.getClass().getMethods()) { if ((doSneak || !method.getName().equals("setSneaking")) && (doSprint || !method.getName().equals("setSprinting")) && method.getParameterTypes().length == 0 && method.getReturnType() != void.class) { Class methodReturn = method.getReturnType(); if (methodReturn == float.class || methodReturn == Float.class || methodReturn == Double.class) { methodReturn = double.class; } int firstCapitalMethod = firstCapital(method.getName()); if (firstCapitalMethod > 0) { for (Method watcherMethod : watcher.getClass().getMethods()) { if (!watcherMethod.getName().startsWith("get") && watcherMethod.getReturnType() == void.class && watcherMethod.getParameterTypes().length == 1) { int firstCapitalWatcher = firstCapital(watcherMethod.getName()); if (firstCapitalWatcher > 0 && method.getName().substring(firstCapitalMethod) .equalsIgnoreCase(watcherMethod.getName().substring(firstCapitalWatcher))) { Class methodParam = watcherMethod.getParameterTypes()[0]; if (methodParam == float.class || methodParam == Float.class || methodParam == Double.class) { methodParam = double.class; } else if (methodParam == AnimalColor.class) { methodParam = DyeColor.class; } if (methodReturn == methodParam) { try { Object value = method.invoke(entity); if (value != null) { Class toCast = watcherMethod.getParameterTypes()[0]; if (!(toCast.isInstance(value))) { if (toCast == float.class) { if (value instanceof Float) { value = ((Float) value).floatValue(); } else { double d = (Double) value; value = (float) d; } } else if (toCast == double.class) { if (value instanceof Double) { value = ((Double) value).doubleValue(); } else { float d = (Float) value; value = (double) d; } } else if (toCast == AnimalColor.class) { value = AnimalColor.valueOf(((DyeColor) value).name()); } } if (value instanceof Boolean && !(Boolean) value && watcherMethod.getDeclaringClass() == FlagWatcher.class) { continue; } } watcherMethod.invoke(watcher, value); } catch (Exception ex) { ex.printStackTrace(); } } } } } } } } return disguise; } 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) return; // Fire a disguise event DisguiseEvent event = new DisguiseEvent(entity, disguise); Bukkit.getPluginManager().callEvent(event); // If they cancelled this disguise event. No idea why. // Just return. if (event.isCancelled()) return; // The event wasn't cancelled. // If the disguise entity isn't the same as the one we are disguising if (disguise.getEntity() != entity) { // If the disguise entity actually exists if (disguise.getEntity() != null) { // Clone the disguise disguise = disguise.clone(); } // Set the disguise's entity disguise.setEntity(entity); } disguise.startDisguise(); } public static void disguiseIgnorePlayers(Entity entity, Disguise disguise, Collection playersToNotSeeDisguise) { if (disguise.getEntity() != null) { disguise = disguise.clone(); } ((TargetedDisguise) disguise).setDisguiseTarget(TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS); for (Object obj : playersToNotSeeDisguise) { if (obj instanceof String) { ((TargetedDisguise) disguise).addPlayer((String) obj); } else if (obj instanceof Player) { ((TargetedDisguise) disguise).addPlayer(((Player) obj).getName()); } } disguiseEntity(entity, disguise); } @Deprecated public static void disguiseIgnorePlayers(Entity entity, Disguise disguise, List playersToNotSeeDisguise) { disguiseIgnorePlayers(entity, disguise, (Collection) playersToNotSeeDisguise); } public static void disguiseIgnorePlayers(Entity entity, Disguise disguise, Player... playersToNotSeeDisguise) { disguiseIgnorePlayers(entity, disguise, (Collection) Arrays.asList(playersToNotSeeDisguise)); } public static void disguiseIgnorePlayers(Entity entity, Disguise disguise, String... playersToNotSeeDisguise) { disguiseIgnorePlayers(entity, disguise, (Collection) Arrays.asList(playersToNotSeeDisguise)); } /** * Disguise the next entity to spawn with this disguise. This may not work however if the entity doesn't actually spawn. */ public static int disguiseNextEntity(Disguise disguise) { if (disguise == null) return -1; if (disguise.getEntity() != null || DisguiseUtilities.getDisguises().containsValue(disguise)) { disguise = disguise.clone(); } try { Field field = ReflectionManager.getNmsClass("Entity").getDeclaredField("entityCount"); field.setAccessible(true); int id = field.getInt(null); DisguiseUtilities.addFutureDisguise(id, (TargetedDisguise) disguise); return id; } catch (Exception ex) { ex.printStackTrace(); } return -1; } /** * Disguise this entity with this disguise */ public static void disguiseToAll(Entity entity, Disguise disguise) { if (disguise.getEntity() != null) { disguise = disguise.clone(); } // 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()) ((TargetedDisguise) disguise).removePlayer(observer); disguiseEntity(entity, disguise); } public static void disguiseToPlayers(Entity entity, Disguise disguise, Collection playersToViewDisguise) { if (disguise.getEntity() != null) { disguise = disguise.clone(); } ((TargetedDisguise) disguise).setDisguiseTarget(TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS); for (Object obj : playersToViewDisguise) { if (obj instanceof String) { ((TargetedDisguise) disguise).addPlayer((String) obj); } else if (obj instanceof Player) { ((TargetedDisguise) disguise).addPlayer(((Player) obj).getName()); } } disguiseEntity(entity, disguise); } @Deprecated public static void disguiseToPlayers(Entity entity, Disguise disguise, List playersToViewDisguise) { disguiseToPlayers(entity, disguise, (Collection) playersToViewDisguise); } public static void disguiseToPlayers(Entity entity, Disguise disguise, Player... playersToViewDisguise) { disguiseToPlayers(entity, disguise, (Collection) Arrays.asList(playersToViewDisguise)); } public static void disguiseToPlayers(Entity entity, Disguise disguise, String... playersToViewDisguise) { disguiseToPlayers(entity, disguise, (Collection) Arrays.asList(playersToViewDisguise)); } private static int firstCapital(String str) { for (int i = 0; i < str.length(); i++) { if (Character.isUpperCase(str.charAt(i))) { return i; } } return -1; } /** * Get the disguise of a entity */ public static Disguise getDisguise(Entity disguised) { if (disguised == null) return null; return DisguiseUtilities.getMainDisguise(disguised.getUniqueId()); } /** * Get the disguise of a entity */ public static Disguise getDisguise(Player observer, Entity disguised) { if (disguised == null || observer == null) return null; return DisguiseUtilities.getDisguise(observer, disguised); } /** * Get the disguises of a entity */ public static Disguise[] getDisguises(Entity disguised) { if (disguised == null) return null; return DisguiseUtilities.getDisguises(disguised.getUniqueId()); } /** * Get the ID of a fake disguise for a entityplayer */ public static int getFakeDisguise(UUID entityId) { if (DisguiseUtilities.getSelfDisguisesIds().containsKey(entityId)) return DisguiseUtilities.getSelfDisguisesIds().get(entityId); return -1; } /** * Is this entity disguised */ public static boolean isDisguised(Entity disguised) { return getDisguise(disguised) != null; } /** * Is this entity disguised */ public static boolean isDisguised(Player observer, Entity disguised) { return getDisguise(observer, disguised) != null; } public static boolean isDisguiseInUse(Disguise disguise) { return disguise.isDisguiseInUse(); } /** * Undisguise the entity. This doesn't let you cancel the UndisguiseEvent if the entity is no longer valid. Aka removed from * the world. */ public static void undisguiseToAll(Entity entity) { Disguise[] disguises = getDisguises(entity); for (Disguise disguise : disguises) { UndisguiseEvent event = new UndisguiseEvent(entity, disguise); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) continue; disguise.removeDisguise(); } } private DisguiseAPI() { } }