- Changed entire project to gradle

- Updated for 1.8.3
- No more errors, woo
This commit is contained in:
NavidK0
2015-03-09 20:28:41 -04:00
parent 14757a035b
commit 573f4cdc88
81 changed files with 299 additions and 645 deletions

View File

@@ -0,0 +1,336 @@
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.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.ReflectionManager;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Horse;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.HorseInventory;
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 doEquipment, 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 (doEquipment && entity instanceof LivingEntity) {
EntityEquipment equip = ((LivingEntity) entity).getEquipment();
watcher.setArmor(equip.getArmorContents());
watcher.setItemInHand(equip.getItemInHand());
if (disguiseType.getEntityType() == EntityType.HORSE) {
Horse horse = (Horse) entity;
HorseInventory horseInventory = horse.getInventory();
ItemStack saddle = horseInventory.getSaddle();
if (saddle != null && saddle.getType() == Material.SADDLE) {
((HorseWatcher) watcher).setSaddled(true);
}
((HorseWatcher) watcher).setHorseArmor(horseInventory.getArmor());
}
}
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;
// 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<String> 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<String> 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
*/
@Deprecated
public static int getFakeDisguise(UUID entityId) {
return -10;
}
public static int getSelfDisguiseId() {
return -10;
}
/**
* 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();
}
public static boolean isSelfDisguised(Player player) {
return DisguiseUtilities.getSelfDisguised().contains(player.getUniqueId());
}
/**
* 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) {
disguise.removeDisguise();
}
}
private DisguiseAPI() {
}
}

View File

@@ -0,0 +1,426 @@
package me.libraryaddict.disguise;
import me.libraryaddict.disguise.utilities.PacketsManager;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
public class DisguiseConfig {
private static boolean animationEnabled;
private static boolean bedEnabled;
private static boolean blowDisguisesOnAttack;
private static boolean collectEnabled;
private static boolean colorizeSheep;
private static boolean colorizeWolf;
private static String disguiseBlownMessage;
private static int disguiseCloneExpire;
private static int disguiseEntityExpire;
private static boolean entityAnimationsAdded;
private static boolean entityStatusEnabled;
private static boolean equipmentEnabled;
private static boolean hearSelfDisguise;
private static boolean hidingArmor;
private static boolean hidingHeldItem;
private static boolean keepDisguiseEntityDespawn;
private static boolean keepDisguisePlayerDeath;
private static boolean keepDisguisePlayerLogout;
private static int maxClonedDisguises;
private static boolean maxHealthIsDisguisedEntity;
private static boolean miscDisguisesForLivingEnabled;
private static boolean modifyBoundingBox;
private static boolean movementEnabled;
private static boolean sendsEntityMetadata;
private static boolean sendVelocity;
private static boolean showNameAboveHead;
private static boolean showNameAboveHeadAlwaysVisible;
private static boolean targetDisguises;
private static boolean undisguiseSwitchWorlds;
private static String updateMessage = ChatColor.RED + "[LibsDisguises] " + ChatColor.DARK_RED
+ "There is a update ready to be downloaded! You are using " + ChatColor.RED + "v%s" + ChatColor.DARK_RED
+ ", the new version is " + ChatColor.RED + "%s" + ChatColor.DARK_RED + "!";
private static String updateNotificationPermission;
private static boolean witherSkullEnabled;
public static String getDisguiseBlownMessage() {
return disguiseBlownMessage;
}
public static int getDisguiseCloneExpire() {
return disguiseCloneExpire;
}
public static int getDisguiseEntityExpire() {
return disguiseEntityExpire;
}
public static int getMaxClonedDisguises() {
return maxClonedDisguises;
}
public static String getUpdateMessage() {
return updateMessage;
}
public static String getUpdateNotificationPermission() {
return updateNotificationPermission;
}
public static void initConfig(ConfigurationSection config) {
setSoundsEnabled(config.getBoolean("DisguiseSounds"));
setVelocitySent(config.getBoolean("SendVelocity"));
setViewDisguises(config.getBoolean("ViewSelfDisguises"));
setHearSelfDisguise(config.getBoolean("HearSelfDisguise"));
setHideArmorFromSelf(config.getBoolean("RemoveArmor"));
setHideHeldItemFromSelf(config.getBoolean("RemoveHeldItem"));
setAddEntityAnimations(config.getBoolean("AddEntityAnimations"));
setNameOfPlayerShownAboveDisguise(config.getBoolean("ShowNamesAboveDisguises"));
setNameAboveHeadAlwaysVisible(config.getBoolean("NameAboveHeadAlwaysVisible"));
setModifyBoundingBox(config.getBoolean("ModifyBoundingBox"));
setMonstersIgnoreDisguises(config.getBoolean("MonstersIgnoreDisguises"));
setDisguiseBlownOnAttack(config.getBoolean("BlowDisguises"));
setDisguiseBlownMessage(ChatColor.translateAlternateColorCodes('&', config.getString("BlownDisguiseMessage")));
setKeepDisguiseOnPlayerDeath(config.getBoolean("KeepDisguises.PlayerDeath"));
setKeepDisguiseOnPlayerLogout(config.getBoolean("KeepDisguises.PlayerLogout"));
setKeepDisguiseOnEntityDespawn(config.getBoolean("KeepDisguises.EntityDespawn"));
setMiscDisguisesForLivingEnabled(config.getBoolean("MiscDisguisesForLiving"));
setMovementPacketsEnabled(config.getBoolean("PacketsEnabled.Movement"));
setWitherSkullPacketsEnabled(config.getBoolean("PacketsEnabled.WitherSkull"));
setEquipmentPacketsEnabled(config.getBoolean("PacketsEnabled.Equipment"));
setAnimationPacketsEnabled(config.getBoolean("PacketsEnabled.Animation"));
setBedPacketsEnabled(config.getBoolean("PacketsEnabled.Bed"));
setEntityStatusPacketsEnabled(config.getBoolean("PacketsEnabled.EntityStatus"));
setCollectPacketsEnabled(config.getBoolean("PacketsEnabled.Collect"));
setMetadataPacketsEnabled(config.getBoolean("PacketsEnabled.Metadata"));
setMaxHealthDeterminedByDisguisedEntity(config.getBoolean("MaxHealthDeterminedByEntity"));
setDisguiseEntityExpire(config.getInt("DisguiseEntityExpire"));
setDisguiseCloneExpire(config.getInt("DisguiseCloneExpire"));
setMaxClonedDisguises(config.getInt("DisguiseCloneSize"));
setSheepDyeable(config.getBoolean("DyeableSheep"));
setWolfDyeable(config.getBoolean("DyeableWolf"));
setUndisguiseOnWorldChange(config.getBoolean("UndisguiseOnWorldChange"));
setUpdateNotificationPermission(config.getString("Permission"));
}
public static boolean isAnimationPacketsEnabled() {
return animationEnabled;
}
public static boolean isBedPacketsEnabled() {
return bedEnabled;
}
public static boolean isCollectPacketsEnabled() {
return collectEnabled;
}
public static boolean isDisguiseBlownOnAttack() {
return blowDisguisesOnAttack;
}
/**
* @deprecated Spelling mistake.
*/
@Deprecated
public static boolean isEnquipmentPacketsEnabled() {
return equipmentEnabled;
}
public static boolean isEntityAnimationsAdded() {
return entityAnimationsAdded;
}
public static boolean isEntityStatusPacketsEnabled() {
return entityStatusEnabled;
}
public static boolean isEquipmentPacketsEnabled() {
return equipmentEnabled;
}
/**
* Is the plugin modifying the inventory packets so that players when self disguised, do not see their armor floating around
*/
public static boolean isHidingArmorFromSelf() {
return hidingArmor;
}
/**
* Does the plugin appear to remove the item they are holding, to prevent a floating sword when they are viewing self disguise
*/
public static boolean isHidingHeldItemFromSelf() {
return hidingHeldItem;
}
public static boolean isKeepDisguiseOnEntityDespawn() {
return keepDisguiseEntityDespawn;
}
public static boolean isKeepDisguiseOnPlayerDeath() {
return keepDisguisePlayerDeath;
}
public static boolean isKeepDisguiseOnPlayerLogout() {
return keepDisguisePlayerLogout;
}
public static boolean isMaxHealthDeterminedByDisguisedEntity() {
return maxHealthIsDisguisedEntity;
}
public static boolean isMetadataPacketsEnabled() {
return sendsEntityMetadata;
}
public static boolean isMiscDisguisesForLivingEnabled() {
return miscDisguisesForLivingEnabled;
}
public static boolean isModifyBoundingBox() {
return modifyBoundingBox;
}
public static boolean isMonstersIgnoreDisguises() {
return targetDisguises;
}
public static boolean isMovementPacketsEnabled() {
return movementEnabled;
}
public static boolean isNameAboveHeadAlwaysVisible() {
return showNameAboveHeadAlwaysVisible;
}
public static boolean isNameOfPlayerShownAboveDisguise() {
return showNameAboveHead;
}
public static boolean isSelfDisguisesSoundsReplaced() {
return hearSelfDisguise;
}
public static boolean isSheepDyeable() {
return colorizeSheep;
}
/**
* Is the sound packets caught and modified
*/
public static boolean isSoundEnabled() {
return PacketsManager.isHearDisguisesEnabled();
}
public static boolean isUndisguiseOnWorldChange() {
return undisguiseSwitchWorlds;
}
/**
* Is the velocity packets sent
*/
public static boolean isVelocitySent() {
return sendVelocity;
}
/**
* The default value if a player views his own disguise
*/
public static boolean isViewDisguises() {
return PacketsManager.isViewDisguisesListenerEnabled();
}
public static boolean isWitherSkullPacketsEnabled() {
return witherSkullEnabled;
}
public static boolean isWolfDyeable() {
return colorizeWolf;
}
public static void setAddEntityAnimations(boolean isEntityAnimationsAdded) {
entityAnimationsAdded = isEntityAnimationsAdded;
}
public static void setAnimationPacketsEnabled(boolean enabled) {
if (enabled != isAnimationPacketsEnabled()) {
animationEnabled = enabled;
PacketsManager.setupMainPacketsListener();
}
}
public static void setBedPacketsEnabled(boolean enabled) {
if (enabled != isBedPacketsEnabled()) {
bedEnabled = enabled;
PacketsManager.setupMainPacketsListener();
}
}
public static void setCollectPacketsEnabled(boolean enabled) {
if (enabled != isCollectPacketsEnabled()) {
collectEnabled = enabled;
PacketsManager.setupMainPacketsListener();
}
}
public static void setDisguiseBlownMessage(String newMessage) {
disguiseBlownMessage = newMessage;
}
public static void setDisguiseBlownOnAttack(boolean blowDisguise) {
blowDisguisesOnAttack = blowDisguise;
}
public static void setDisguiseCloneExpire(int newExpires) {
disguiseCloneExpire = newExpires;
}
public static void setDisguiseEntityExpire(int newExpires) {
disguiseEntityExpire = newExpires;
}
@Deprecated
public static void setEnquipmentPacketsEnabled(boolean enabled) {
setEquipmentPacketsEnabled(enabled);
}
public static void setEntityStatusPacketsEnabled(boolean enabled) {
if (enabled != isEntityStatusPacketsEnabled()) {
entityStatusEnabled = enabled;
PacketsManager.setupMainPacketsListener();
}
}
public static void setEquipmentPacketsEnabled(boolean enabled) {
if (enabled != isEquipmentPacketsEnabled()) {
equipmentEnabled = enabled;
PacketsManager.setupMainPacketsListener();
}
}
/**
* Can players hear their own disguises
*/
public static void setHearSelfDisguise(boolean replaceSound) {
if (hearSelfDisguise != replaceSound) {
hearSelfDisguise = replaceSound;
}
}
/**
* Set the plugin to hide self disguises armor from theirselves
*/
public static void setHideArmorFromSelf(boolean hideArmor) {
if (hidingArmor != hideArmor) {
hidingArmor = hideArmor;
PacketsManager.setInventoryListenerEnabled(isHidingHeldItemFromSelf() || isHidingArmorFromSelf());
}
}
/**
* Does the plugin appear to remove the item they are holding, to prevent a floating sword when they are viewing self disguise
*/
public static void setHideHeldItemFromSelf(boolean hideHelditem) {
if (hidingHeldItem != hideHelditem) {
hidingHeldItem = hideHelditem;
PacketsManager.setInventoryListenerEnabled(isHidingHeldItemFromSelf() || isHidingArmorFromSelf());
}
}
public static void setKeepDisguiseOnEntityDespawn(boolean keepDisguise) {
keepDisguiseEntityDespawn = keepDisguise;
}
public static void setKeepDisguiseOnPlayerDeath(boolean keepDisguise) {
keepDisguisePlayerDeath = keepDisguise;
}
public static void setKeepDisguiseOnPlayerLogout(boolean keepDisguise) {
keepDisguisePlayerLogout = keepDisguise;
}
public static void setMaxClonedDisguises(int newMax) {
maxClonedDisguises = newMax;
}
public static void setMaxHealthDeterminedByDisguisedEntity(boolean isDetermined) {
maxHealthIsDisguisedEntity = isDetermined;
}
public static void setMetadataPacketsEnabled(boolean enabled) {
sendsEntityMetadata = enabled;
}
public static void setMiscDisguisesForLivingEnabled(boolean enabled) {
if (enabled != isMiscDisguisesForLivingEnabled()) {
miscDisguisesForLivingEnabled = enabled;
PacketsManager.setupMainPacketsListener();
}
}
public static void setModifyBoundingBox(boolean modifyBounding) {
modifyBoundingBox = modifyBounding;
}
public static void setMonstersIgnoreDisguises(boolean ignore) {
targetDisguises = ignore;
}
public static void setMovementPacketsEnabled(boolean enabled) {
if (enabled != isMovementPacketsEnabled()) {
movementEnabled = enabled;
PacketsManager.setupMainPacketsListener();
}
}
public static void setNameAboveHeadAlwaysVisible(boolean alwaysVisible) {
showNameAboveHeadAlwaysVisible = alwaysVisible;
}
public static void setNameOfPlayerShownAboveDisguise(boolean showNames) {
showNameAboveHead = showNames;
}
public static void setSheepDyeable(boolean color) {
colorizeSheep = color;
}
/**
* Set if the disguises play sounds when hurt
*/
public static void setSoundsEnabled(boolean isSoundsEnabled) {
PacketsManager.setHearDisguisesListener(isSoundsEnabled);
}
public static void setUndisguiseOnWorldChange(boolean isUndisguise) {
undisguiseSwitchWorlds = isUndisguise;
}
public static void setUpdateMessage(String newMessage) {
updateMessage = newMessage;
}
public static void setUpdateNotificationPermission(String newPermission) {
updateNotificationPermission = newPermission;
}
/**
* Disable velocity packets being sent for w/e reason. Maybe you want every ounce of performance you can get?
*/
public static void setVelocitySent(boolean sendVelocityPackets) {
sendVelocity = sendVelocityPackets;
}
public static void setViewDisguises(boolean seeOwnDisguise) {
PacketsManager.setViewDisguisesListener(seeOwnDisguise);
}
public static void setWitherSkullPacketsEnabled(boolean enabled) {
witherSkullEnabled = enabled;
}
public static void setWolfDyeable(boolean color) {
colorizeWolf = color;
}
private DisguiseConfig() {
}
}

View File

@@ -0,0 +1,377 @@
package me.libraryaddict.disguise;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.PlayerDisguise;
import me.libraryaddict.disguise.disguisetypes.TargetedDisguise;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.ReflectionManager;
import me.libraryaddict.disguise.utilities.UpdateChecker;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.event.vehicle.VehicleExitEvent;
import org.bukkit.scheduler.BukkitRunnable;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
public class DisguiseListener implements Listener {
private String currentVersion;
private HashMap<String, Boolean[]> disguiseClone = new HashMap<String, Boolean[]>();
private HashMap<String, Disguise> disguiseEntity = new HashMap<String, Disguise>();
private HashMap<String, BukkitRunnable> disguiseRunnable = new HashMap<String, BukkitRunnable>();
private String latestVersion;
private LibsDisguises plugin;
public DisguiseListener(LibsDisguises libsDisguises) {
plugin = libsDisguises;
if (plugin.getConfig().getBoolean("NotifyUpdate")) {
currentVersion = plugin.getDescription().getVersion();
Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
public void run() {
try {
UpdateChecker updateChecker = new UpdateChecker();
updateChecker.checkUpdate("v" + currentVersion);
latestVersion = updateChecker.getLatestVersion();
if (latestVersion != null) {
latestVersion = "v" + latestVersion;
Bukkit.getScheduler().runTask(plugin, new Runnable() {
public void run() {
for (Player p : Bukkit.getOnlinePlayers())
if (p.hasPermission(DisguiseConfig.getUpdateNotificationPermission()))
p.sendMessage(String.format(DisguiseConfig.getUpdateMessage(), currentVersion,
latestVersion));
}
});
}
} catch (Exception ex) {
System.out.print(String.format("[LibsDisguises] Failed to check for update: %s", ex.getMessage()));
}
}
}, 0, (20 * 60 * 60 * 6)); // Check every 6 hours
// 20 ticks * 60 seconds * 60 minutes * 6 hours
}
}
private void checkPlayerCanBlowDisguise(Player entity) {
Disguise[] disguises = DisguiseAPI.getDisguises(entity);
if (disguises.length > 0) {
DisguiseAPI.undisguiseToAll(entity);
if (DisguiseConfig.getDisguiseBlownMessage().length() > 0) {
entity.sendMessage(DisguiseConfig.getDisguiseBlownMessage());
}
}
}
private void chunkMove(Player player, Location newLoc, Location oldLoc) {
try {
for (PacketContainer packet : DisguiseUtilities.getBedChunkPacket(player, newLoc, oldLoc)) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, false);
}
if (newLoc != null) {
for (HashSet<TargetedDisguise> list : DisguiseUtilities.getDisguises().values()) {
for (TargetedDisguise disguise : list) {
if (disguise.isPlayerDisguise() && disguise.canSee(player)
&& ((PlayerDisguise) disguise).getWatcher().isSleeping()
&& DisguiseUtilities.getPerverts(disguise).contains(player)) {
PacketContainer[] packets = DisguiseUtilities.getBedPackets(player,
disguise.getEntity() == player ? newLoc : disguise.getEntity().getLocation(), newLoc,
(PlayerDisguise) disguise);
if (disguise.getEntity() == player) {
for (PacketContainer packet : packets) {
packet.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId());
}
}
for (PacketContainer packet : packets) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
}
}
}
}
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onAttack(EntityDamageByEntityEvent event) {
if (DisguiseConfig.isDisguiseBlownOnAttack()) {
if (event.getEntity() instanceof Player) {
checkPlayerCanBlowDisguise((Player) event.getEntity());
}
if (event.getDamager() instanceof Player) {
checkPlayerCanBlowDisguise((Player) event.getDamager());
}
}
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player p = event.getPlayer();
if (latestVersion != null && p.hasPermission(DisguiseConfig.getUpdateNotificationPermission())) {
p.sendMessage(String.format(DisguiseConfig.getUpdateMessage(), currentVersion, latestVersion));
}
if (DisguiseConfig.isBedPacketsEnabled()) {
chunkMove(p, p.getLocation(), null);
}
}
/**
* Most likely faster if we don't bother doing checks if he sees a player disguise
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onMove(PlayerMoveEvent event) {
if (DisguiseConfig.isBedPacketsEnabled()) {
Location to = event.getTo();
Location from = event.getFrom();
int x1 = (int) Math.floor(to.getX() / 16D) - 17;
int x2 = (int) Math.floor(from.getX() / 16D) - 17;
int z1 = (int) Math.floor(to.getZ() / 16D) - 17;
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(), to, from);
}
}
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
ReflectionManager.removePlayer(event.getPlayer());
}
@EventHandler
public void onRespawn(PlayerRespawnEvent event) {
Disguise[] disguises = DisguiseAPI.getDisguises(event.getPlayer());
for (Disguise disguise : disguises) {
if (disguise.isRemoveDisguiseOnDeath()) {
disguise.removeDisguise();
}
}
}
@EventHandler
public void onRightClick(PlayerInteractEntityEvent event) {
if (disguiseEntity.containsKey(event.getPlayer().getName()) || disguiseClone.containsKey(event.getPlayer().getName())) {
Player p = event.getPlayer();
event.setCancelled(true);
disguiseRunnable.remove(p.getName()).cancel();
Entity entity = event.getRightClicked();
String entityName = "";
if (entity instanceof Player && !disguiseClone.containsKey(p.getName())) {
entityName = ((Player) entity).getName();
} else {
entityName = DisguiseType.getType(entity).toReadable();
}
if (disguiseClone.containsKey(p.getName())) {
Boolean[] options = disguiseClone.remove(p.getName());
Disguise disguise = DisguiseAPI.getDisguise(p, entity);
if (disguise == null) {
disguise = DisguiseAPI.constructDisguise(entity, options[0], options[1], options[2]);
} else {
disguise = disguise.clone();
}
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray();
String reference = null;
int referenceLength = Math.max(2, (int) Math.ceil((0.1D + DisguiseConfig.getMaxClonedDisguises()) / 26D));
int attempts = 0;
while (reference == null && attempts++ < 1000) {
reference = "@";
for (int i = 0; i < referenceLength; i++) {
reference += alphabet[new Random().nextInt(alphabet.length)];
}
if (DisguiseUtilities.getClonedDisguise(reference) != null) {
reference = null;
}
}
if (reference != null && DisguiseUtilities.addClonedDisguise(reference, disguise)) {
p.sendMessage(ChatColor.RED + "Constructed a " + entityName + " disguise! Your reference is " + reference);
p.sendMessage(ChatColor.RED + "Example usage: /disguise " + reference);
} else {
p.sendMessage(ChatColor.RED
+ "Failed to store the reference due to lack of size. Please set this in the config");
}
} else if (disguiseEntity.containsKey(p.getName())) {
Disguise disguise = disguiseEntity.remove(p.getName());
if (disguise != null) {
if (disguise.isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled()
&& entity instanceof LivingEntity) {
p.sendMessage(ChatColor.RED
+ "Can't disguise a living entity as a misc disguise. This has been disabled in the config!");
} else {
if (entity instanceof Player && DisguiseConfig.isNameOfPlayerShownAboveDisguise()) {
if (disguise.getWatcher() instanceof LivingWatcher) {
((LivingWatcher) disguise.getWatcher()).setCustomName(((Player) entity).getDisplayName());
if (DisguiseConfig.isNameAboveHeadAlwaysVisible()) {
((LivingWatcher) disguise.getWatcher()).setCustomNameVisible(true);
}
}
}
DisguiseAPI.disguiseToAll(entity, disguise);
String disguiseName = "a ";
if (disguise instanceof PlayerDisguise) {
disguiseName = "the player " + ((PlayerDisguise) disguise).getName();
} else {
disguiseName += disguise.getType().toReadable();
}
if (disguise.isDisguiseInUse()) {
p.sendMessage(ChatColor.RED + "Disguised " + (entity instanceof Player ? "" : "the ") + entityName
+ " as " + disguiseName + "!");
} else {
p.sendMessage(ChatColor.RED + "Failed to disguise " + (entity instanceof Player ? "" : "the ")
+ entityName + " as " + disguiseName + "!");
}
}
} else {
if (DisguiseAPI.isDisguised(entity)) {
DisguiseAPI.undisguiseToAll(entity);
p.sendMessage(ChatColor.RED + "Undisguised " + (entity instanceof Player ? "" : "the ") + entityName);
} else
p.sendMessage(ChatColor.RED + (entity instanceof Player ? "" : "the") + entityName + " isn't disguised!");
}
}
}
}
@EventHandler
public void onTarget(EntityTargetEvent event) {
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;
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onTeleport(final PlayerTeleportEvent event) {
Location to = event.getTo();
Location from = event.getFrom();
if (DisguiseConfig.isBedPacketsEnabled()) {
int x1 = (int) Math.floor(to.getX() / 16D) - 17;
int x2 = (int) Math.floor(from.getX() / 16D) - 17;
int z1 = (int) Math.floor(to.getZ() / 16D) - 17;
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() {
public void run() {
if (!event.isCancelled()) {
chunkMove(event.getPlayer(), event.getTo(), null);
} else {
chunkMove(event.getPlayer(), event.getPlayer().getLocation(), null);
}
}
});
}
}
if (DisguiseConfig.isUndisguiseOnWorldChange() && to.getWorld() != null && from.getWorld() != null
&& to.getWorld() != from.getWorld()) {
for (Disguise disguise : DisguiseAPI.getDisguises(event.getPlayer())) {
disguise.removeDisguise();
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onVehicleEnter(VehicleEnterEvent event) {
if (event.getEntered() instanceof Player && DisguiseAPI.isDisguised((Player) event.getEntered(), event.getEntered())) {
DisguiseUtilities.removeSelfDisguise((Player) event.getEntered());
((Player) event.getEntered()).updateInventory();
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onVehicleLeave(VehicleExitEvent event) {
if (event.getExited() instanceof Player) {
final Disguise disguise = DisguiseAPI.getDisguise((Player) event.getExited(), event.getExited());
if (disguise != null) {
Bukkit.getScheduler().runTask(plugin, new Runnable() {
public void run() {
DisguiseUtilities.setupFakeDisguise(disguise);
((Player) disguise.getEntity()).updateInventory();
}
});
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onWorldSwitch(final PlayerChangedWorldEvent event) {
if (DisguiseConfig.isBedPacketsEnabled()) {
chunkMove(event.getPlayer(), event.getPlayer().getLocation(), null);
}
if (DisguiseConfig.isUndisguiseOnWorldChange()) {
for (Disguise disguise : DisguiseAPI.getDisguises(event.getPlayer())) {
disguise.removeDisguise();
}
}
}
public void setDisguiseClone(final String player, Boolean[] options) {
if (disguiseRunnable.containsKey(player)) {
BukkitRunnable run = disguiseRunnable.remove(player);
run.cancel();
run.run();
}
BukkitRunnable runnable = new BukkitRunnable() {
public void run() {
disguiseClone.remove(player);
disguiseRunnable.remove(player);
}
};
runnable.runTaskLater(plugin, 20 * DisguiseConfig.getDisguiseCloneExpire());
disguiseRunnable.put(player, runnable);
disguiseClone.put(player, options);
}
public void setDisguiseEntity(final String player, Disguise disguise) {
if (disguiseRunnable.containsKey(player)) {
BukkitRunnable run = disguiseRunnable.remove(player);
run.cancel();
run.run();
}
BukkitRunnable runnable = new BukkitRunnable() {
public void run() {
disguiseEntity.remove(player);
disguiseRunnable.remove(player);
}
};
runnable.runTaskLater(plugin, 20 * DisguiseConfig.getDisguiseEntityExpire());
disguiseRunnable.put(player, runnable);
disguiseEntity.put(player, disguise);
}
}

View File

@@ -0,0 +1,330 @@
package me.libraryaddict.disguise;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Field;
import me.libraryaddict.disguise.commands.*;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.GuardianWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.HorseWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.MinecartWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.SlimeWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.TameableWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
import me.libraryaddict.disguise.utilities.DisguiseSound;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.PacketsManager;
import me.libraryaddict.disguise.utilities.ReflectionManager;
import me.libraryaddict.disguise.utilities.DisguiseValues;
import org.bukkit.Bukkit;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Damageable;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Zombie;
import org.bukkit.plugin.java.JavaPlugin;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
public class LibsDisguises extends JavaPlugin {
@Override
public void onEnable() {
saveDefaultConfig();
File configFile = new File(getDataFolder(), "config.yml");
InputStream stream = null;
FileReader reader = null;
try {
stream = getClassLoader().getResource("config.yml").openStream();
String toWrite = read(new InputStreamReader(stream));
reader = new FileReader(configFile);
String toRead = read(reader);
if (!toRead.equals(toWrite)) {
try {
FileWriter writer = new FileWriter(configFile);
try {
writer.write(toWrite);
} finally {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
tryClose(stream);
tryClose(reader);
}
PacketsManager.init(this);
DisguiseUtilities.init(this);
DisguiseConfig.initConfig(getConfig());
try {
// Here I use reflection to set the plugin for Disguise..
// Kind of stupid but I don't want open API calls for a commonly used class.
Field field = Disguise.class.getDeclaredField("plugin");
field.setAccessible(true);
field.set(null, this);
} catch (Exception ex) {
ex.printStackTrace();
}
PacketsManager.addPacketListeners();
DisguiseListener listener = new DisguiseListener(this);
Bukkit.getPluginManager().registerEvents(listener, this);
getCommand("disguise").setExecutor(new DisguiseCommand());
getCommand("undisguise").setExecutor(new UndisguiseCommand());
getCommand("disguiseplayer").setExecutor(new DisguisePlayerCommand());
getCommand("undisguiseplayer").setExecutor(new UndisguisePlayerCommand());
getCommand("undisguiseentity").setExecutor(new UndisguiseEntityCommand(listener));
getCommand("disguiseentity").setExecutor(new DisguiseEntityCommand(listener));
getCommand("disguiseradius").setExecutor(new DisguiseRadiusCommand(getConfig().getInt("DisguiseRadiusMax")));
getCommand("undisguiseradius").setExecutor(new UndisguiseRadiusCommand(getConfig().getInt("UndisguiseRadiusMax")));
getCommand("disguisehelp").setExecutor(new DisguiseHelpCommand());
getCommand("disguiseclone").setExecutor(new DisguiseCloneCommand(listener));
getCommand("libsdisguises").setExecutor(new LibsDisguisesCommand());
registerValues();
}
private String read(Reader reader) {
String toWrite = "";
BufferedReader input = null;
try {
input = new BufferedReader(reader);
String currentPath = "";
String line;
while ((line = input.readLine()) != null) {
if (line.replace(" ", "").startsWith("#")) {
toWrite += line;
} else if (line.contains(":")) {
if (line.substring(line.indexOf(":") + 1).equals("")) {
currentPath = line.substring(0, line.length() - 1) + ".";
toWrite += line;
} else {
if (!line.startsWith(" ")) {
currentPath = "";
}
String obj = line.substring(0, line.indexOf(":")).replace(" ", "");
Object value = getConfig().get(currentPath + obj);
if (value instanceof String) {
value = "'" + value + "'";
}
toWrite += (currentPath.length() == 0 ? "" : " ") + obj + ": " + value;
}
}
if (input.ready()) {
toWrite += "\n";
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
tryClose(input);
tryClose(reader);
}
return toWrite;
}
/**
* 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()) {
if (disguiseType.getEntityType() == null) {
continue;
}
Class watcherClass = null;
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;
}
} catch (ClassNotFoundException ex) {
// There is no explicit watcher for this entity.
Class entityClass = disguiseType.getEntityType().getEntityClass();
if (Tameable.class.isAssignableFrom(entityClass)) {
watcherClass = TameableWatcher.class;
} else if (Ageable.class.isAssignableFrom(entityClass)) {
watcherClass = AgeableWatcher.class;
} else if (LivingEntity.class.isAssignableFrom(entityClass)) {
watcherClass = LivingWatcher.class;
} else {
watcherClass = FlagWatcher.class;
}
}
disguiseType.setWatcherClass(watcherClass);
if (DisguiseValues.getDisguiseValues(disguiseType) != null) {
continue;
}
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;
}
try {
Object nmsEntity = ReflectionManager.createEntityInstance(nmsEntityName);
if (nmsEntity == null) {
continue;
}
Entity bukkitEntity = ReflectionManager.getBukkitEntity(nmsEntity);
int entitySize = 0;
for (Field field : ReflectionManager.getNmsClass("Entity").getFields()) {
if (field.getType().getName().equals("EnumEntitySize")) {
Enum enumEntitySize = (Enum) field.get(nmsEntity);
entitySize = enumEntitySize.ordinal();
break;
}
}
DisguiseValues disguiseValues = new DisguiseValues(disguiseType, nmsEntity.getClass(), entitySize,
bukkitEntity instanceof Damageable ? ((Damageable) bukkitEntity).getMaxHealth() : 0);
for (WrappedWatchableObject watch : WrappedDataWatcher.getEntityWatcher(bukkitEntity).getWatchableObjects()) {
disguiseValues.setMetaValue(watch.getIndex(), watch.getValue());
// Uncomment when I need to find the new datawatcher values for a class..
// System.out.print("Disguise: " + disguiseType + ", ID: " + watch.getIndex() + ", Class: "
// + (watch.getValue() == null ? "null" : watch.getValue().getClass()) + ", Value: " + watch.getValue());
}
DisguiseSound sound = DisguiseSound.getType(disguiseType.name());
if (sound != null) {
Float soundStrength = ReflectionManager.getSoundModifier(nmsEntity);
if (soundStrength != null) {
sound.setDamageAndIdleSoundVolume((Float) soundStrength);
}
}
// Get the bounding box
disguiseValues.setAdultBox(ReflectionManager.getBoundingBox(bukkitEntity));
if (bukkitEntity instanceof Ageable) {
((Ageable) bukkitEntity).setBaby();
disguiseValues.setBabyBox(ReflectionManager.getBoundingBox(bukkitEntity));
} else if (bukkitEntity instanceof Zombie) {
((Zombie) bukkitEntity).setBaby(true);
disguiseValues.setBabyBox(ReflectionManager.getBoundingBox(bukkitEntity));
}
disguiseValues.setEntitySize(ReflectionManager.getSize(bukkitEntity));
} catch (Exception ex) {
System.out.print("[LibsDisguises] Uh oh! Trouble while making values for the disguise " + disguiseType.name()
+ "!");
System.out.print("[LibsDisguises] Before reporting this error, "
+ "please make sure you are using the latest version of LibsDisguises and ProtocolLib.");
if (ReflectionManager.isForge()) {
System.out
.print("[LibsDisguises] Development builds are available at (ProtocolLib) "
+ "http://assets.comphenix.net/job/ProtocolLib%20-%20Cauldron/ and (LibsDisguises) http://ci.md-5.net/job/LibsDisguises/");
} else {
System.out
.print("[LibsDisguises] Development builds are available at (ProtocolLib) "
+ "http://assets.comphenix.net/job/ProtocolLib/ and (LibsDisguises) http://ci.md-5.net/job/LibsDisguises/");
}
ex.printStackTrace();
}
}
}
private String toReadable(String string) {
StringBuilder builder = new StringBuilder();
for (String s : string.split("_")) {
builder.append(s.substring(0, 1)).append(s.substring(1).toLowerCase());
}
return builder.toString();
}
private void tryClose(Closeable input) {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,71 @@
package me.libraryaddict.disguise.commands;
import java.util.ArrayList;
import java.util.HashMap;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.DisguiseListener;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.utilities.BaseDisguiseCommand;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
public class DisguiseCloneCommand extends BaseDisguiseCommand {
private DisguiseListener listener;
public DisguiseCloneCommand(DisguiseListener listener) {
this.listener = listener;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.getName().equals("CONSOLE")) {
sender.sendMessage(ChatColor.RED + "You may not use this command from the console!");
return true;
}
if (sender.hasPermission("libsdisguises.disguise.disguiseclone")) {
boolean doEquipment = true;
boolean doSneak = false;
boolean doSprint = false;
for (String option : args) {
if (StringUtils.startsWithIgnoreCase(option, "ignoreEquip")
|| StringUtils.startsWithIgnoreCase(option, "ignoreEnquip")) {
doEquipment = false;
} else if (option.equalsIgnoreCase("doSneakSprint")) {
doSneak = true;
doSprint = true;
} else if (option.equalsIgnoreCase("doSneak")) {
doSneak = true;
} else if (option.equalsIgnoreCase("doSprint")) {
doSprint = true;
} else {
sender.sendMessage(ChatColor.DARK_RED + "Unknown option '" + option
+ "' - Valid options are 'IgnoreEquipment' 'DoSneakSprint' 'DoSneak' 'DoSprint'");
return true;
}
}
listener.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 {
sender.sendMessage(ChatColor.RED + "You are forbidden to use this command.");
}
return true;
}
/**
* Send the player the information
*/
protected void sendCommandUsage(CommandSender sender, HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map) {
sender.sendMessage(ChatColor.DARK_GREEN
+ "Right click a entity to get a disguise reference you can pass to other disguise commands!");
sender.sendMessage(ChatColor.DARK_GREEN
+ "Security note: Any references you create will be available to all players able to use disguise references.");
sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseclone IgnoreEquipment" + ChatColor.DARK_GREEN + "(" + ChatColor.GREEN
+ "Optional" + ChatColor.DARK_GREEN + ")");
}
}

View File

@@ -0,0 +1,70 @@
package me.libraryaddict.disguise.commands;
import java.util.ArrayList;
import java.util.HashMap;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.utilities.BaseDisguiseCommand;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class DisguiseCommand extends BaseDisguiseCommand {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.getName().equals("CONSOLE")) {
sender.sendMessage(ChatColor.RED + "You may not use this command from the console!");
return true;
}
Disguise disguise;
try {
disguise = parseDisguise(sender, args, getPermissions(sender));
} catch (DisguiseParseException ex) {
if (ex.getMessage() != null) {
sender.sendMessage(ex.getMessage());
}
return true;
} catch (Exception ex) {
ex.printStackTrace();
return true;
}
if (DisguiseConfig.isNameOfPlayerShownAboveDisguise()) {
if (disguise.getWatcher() instanceof LivingWatcher) {
((LivingWatcher) disguise.getWatcher()).setCustomName(((Player) sender).getDisplayName());
if (DisguiseConfig.isNameAboveHeadAlwaysVisible()) {
((LivingWatcher) disguise.getWatcher()).setCustomNameVisible(true);
}
}
}
DisguiseAPI.disguiseToAll((Player) sender, disguise);
if (disguise.isDisguiseInUse()) {
sender.sendMessage(ChatColor.RED + "Now disguised as a " + disguise.getType().toReadable());
} else {
sender.sendMessage(ChatColor.RED + "Failed to disguise as a " + disguise.getType().toReadable());
}
return true;
}
/**
* Send the player the information
*/
protected void sendCommandUsage(CommandSender sender, HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map) {
ArrayList<String> allowedDisguises = getAllowedDisguises(map);
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"))
sender.sendMessage(ChatColor.DARK_GREEN + "/disguise player <Name>");
sender.sendMessage(ChatColor.DARK_GREEN + "/disguise <DisguiseType> <Baby>");
if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block"))
sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseplayer <Dropped_Item/Falling_Block> <Id> <Durability>");
}
}

View File

@@ -0,0 +1,63 @@
package me.libraryaddict.disguise.commands;
import java.util.ArrayList;
import java.util.HashMap;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.DisguiseListener;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.utilities.BaseDisguiseCommand;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
public class DisguiseEntityCommand extends BaseDisguiseCommand {
private DisguiseListener listener;
public DisguiseEntityCommand(DisguiseListener listener) {
this.listener = listener;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.getName().equals("CONSOLE")) {
sender.sendMessage(ChatColor.RED + "You may not use this command from the console!");
return true;
}
Disguise disguise;
try {
disguise = parseDisguise(sender, args, getPermissions(sender));
} catch (DisguiseParseException ex) {
if (ex.getMessage() != null) {
sender.sendMessage(ex.getMessage());
}
return true;
} catch (Exception ex) {
ex.printStackTrace();
return true;
}
listener.setDisguiseEntity(sender.getName(), disguise);
sender.sendMessage(ChatColor.RED + "Right click a entity in the next " + DisguiseConfig.getDisguiseEntityExpire()
+ " seconds to disguise it as a " + disguise.getType().toReadable() + "!");
return true;
}
/**
* Send the player the information
*/
protected void sendCommandUsage(CommandSender sender, HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map) {
ArrayList<String> allowedDisguises = getAllowedDisguises(map);
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"))
sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseentity player <Name>");
sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseentity <DisguiseType> <Baby>");
if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block"))
sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseentity <Dropped_Item/Falling_Block> <Id> <Durability>");
}
}

View File

@@ -0,0 +1,279 @@
package me.libraryaddict.disguise.commands;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import me.libraryaddict.disguise.disguisetypes.AnimalColor;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
import me.libraryaddict.disguise.disguisetypes.RabbitType;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.utilities.BaseDisguiseCommand;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.block.BlockFace;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
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;
private String readableEnum;
public EnumHelp(String enumName, String enumReadable, String enumDescription, Enum[] enums) {
String[] strings = new String[enums.length];
for (int i = 0; i < strings.length; i++) {
strings[i] = toReadable(enums[i].name());
}
this.enumName = enumName;
this.enumDescription = enumDescription;
this.enums = strings;
this.readableEnum = enumReadable;
}
public EnumHelp(String enumName, String enumReadable, String enumDescription, String[] enums) {
this.enumName = enumName;
this.enumDescription = enumDescription;
this.enums = enums;
this.readableEnum = enumReadable;
}
public String getEnumDescription() {
return enumDescription;
}
public String getEnumName() {
return enumName;
}
public String[] getEnums() {
return enums;
}
public String getReadableEnum() {
return readableEnum;
}
}
private ArrayList<EnumHelp> enumHelp = new ArrayList<EnumHelp>();
public DisguiseHelpCommand() {
try {
enumHelp.add(new EnumHelp("AnimalColor", "Animal colors", ChatColor.RED + "/disguisehelp AnimalColors "
+ ChatColor.GREEN + "- View all the colors you can use for a animal color", AnimalColor.values()));
} catch (Exception ex) {
ex.printStackTrace();
}
try {
enumHelp.add(new EnumHelp("Art", "Arts", ChatColor.RED + "/disguisehelp Art " + ChatColor.GREEN
+ "- View all the painting arts you can use on a painting disguise", (Enum[]) Class.forName("org.bukkit.Art")
.getEnumConstants()));
} catch (Exception ex) {
}
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()));
} 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()));
} 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()));
} catch (Exception ex) {
}
try {
ArrayList<String> enumReturns = new ArrayList<String>();
for (PotionEffectType potionType : PotionEffectType.values()) {
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()])));
} catch (Exception ex) {
ex.printStackTrace();
}
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()));
} catch (Exception ex) {
}
enumHelp.add(new EnumHelp("Direction", "Directions", ChatColor.RED + "/disguisehelp Directions " + ChatColor.GREEN
+ "- View the five directions usable on player setsleeping disguise", Arrays.copyOf(BlockFace.values(), 5)));
enumHelp.add(new EnumHelp("RabbitType", "RabbitType", ChatColor.RED + "/disguisehelp RabbitType " + ChatColor.GREEN
+ "View the kinds of rabbits you can turn into", RabbitType.values()));
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
for (String node : new String[] { "disguise", "disguiseradius", "disguiseentity", "disguiseplayer" }) {
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> permMap = getPermissions(sender, "libsdisguises." + node
+ ".");
if (!permMap.isEmpty()) {
if (args.length == 0) {
sendCommandUsage(sender, null);
return true;
} else {
EnumHelp help = null;
for (EnumHelp s : enumHelp) {
if (args[0].equalsIgnoreCase(s.getEnumName()) || args[0].equalsIgnoreCase(s.getEnumName() + "s")) {
help = s;
break;
}
}
if (help != null) {
sender.sendMessage(ChatColor.RED + help.getReadableEnum() + ": " + ChatColor.GREEN
+ StringUtils.join(help.getEnums(), ChatColor.RED + ", " + ChatColor.GREEN));
return true;
}
DisguiseType type = null;
for (DisguiseType disguiseType : DisguiseType.values()) {
if (args[0].equalsIgnoreCase(disguiseType.name())
|| disguiseType.name().replace("_", "").equalsIgnoreCase(args[0])) {
type = disguiseType;
break;
}
}
if (type == null) {
sender.sendMessage(ChatColor.RED + "Cannot find the disguise " + args[0]);
return true;
}
if (!permMap.containsKey(type)) {
sender.sendMessage(ChatColor.RED + "You do not have permission for that disguise!");
return true;
}
ArrayList<String> methods = new ArrayList<String>();
HashMap<String, ChatColor> map = new HashMap<String, ChatColor>();
Class watcher = type.getWatcherClass();
int ignored = 0;
try {
for (Method method : this.getDisguiseWatcherMethods(watcher)) {
if (!method.getName().startsWith("get") && method.getParameterTypes().length == 1
&& method.getAnnotation(Deprecated.class) == null) {
if (args.length < 2 || !args[1].equalsIgnoreCase("show")) {
boolean allowed = false;
for (ArrayList<String> key : permMap.get(type).keySet()) {
if (permMap.get(type).get(key)) {
if (key.contains("*") || key.contains(method.getName().toLowerCase())) {
allowed = true;
break;
}
} else if (!key.contains(method.getName().toLowerCase())) {
allowed = true;
break;
}
}
if (!allowed) {
ignored++;
continue;
}
}
Class c = method.getParameterTypes()[0];
String valueType = null;
if (c == String.class) {
valueType = "String";
} else if (boolean.class == c) {
valueType = "True/False";
} else if (int.class == c) {
valueType = "Number";
} else if (float.class == c || double.class == c) {
valueType = "Decimal";
} else if (AnimalColor.class == c) {
valueType = "Color";
} else if (ItemStack.class == c) {
valueType = "Item (id:damage)";
} else if (ItemStack[].class == c) {
valueType = "4 items (id:damage,id,...)";
} else if (c.getSimpleName().equals("Style")) {
valueType = "Horse Style";
} else if (c.getSimpleName().equals("Color")) {
valueType = "Horse Color";
} else if (c.getSimpleName().equals("Type")) {
valueType = "Ocelot type";
} else if (c.getSimpleName().equals("Profession")) {
valueType = "Villager Profession";
} else if (PotionEffectType.class == c) {
valueType = "Potion effect";
} else if (c == int[].class) {
valueType = "number,number,number...";
} else if (c == BlockFace.class) {
valueType = "direction";
} else if (c == RabbitType.class) {
valueType = "rabbit type";
}
if (valueType != null) {
ChatColor methodColor = ChatColor.YELLOW;
Class<?> declaring = method.getDeclaringClass();
if (declaring == LivingWatcher.class) {
methodColor = ChatColor.AQUA;
} else if (!(FlagWatcher.class.isAssignableFrom(declaring)) || declaring == FlagWatcher.class) {
methodColor = ChatColor.GRAY;
}
String str = method.getName() + ChatColor.DARK_RED + "(" + ChatColor.GREEN + valueType
+ ChatColor.DARK_RED + ")";
map.put(str, methodColor);
methods.add(str);
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
Collections.sort(methods, String.CASE_INSENSITIVE_ORDER);
for (int i = 0; i < methods.size(); i++) {
methods.set(i, map.get(methods.get(i)) + methods.get(i));
}
if (methods.isEmpty()) {
methods.add(ChatColor.RED + "No options with permission to use");
}
sender.sendMessage(ChatColor.DARK_RED + type.toReadable() + " options: "
+ StringUtils.join(methods, ChatColor.DARK_RED + ", "));
if (ignored > 0) {
sender.sendMessage(ChatColor.RED + "Ignored " + ignored
+ " options you do not have permission to view. Add 'show' to view unusable options.");
}
return true;
}
}
}
sender.sendMessage(ChatColor.RED + "You are forbidden to use this command.");
return true;
}
/**
* Send the player the information
*/
protected void sendCommandUsage(CommandSender sender, HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map) {
sender.sendMessage(ChatColor.RED
+ "/disguisehelp <DisguiseType> "
+ ChatColor.GREEN
+ "- View the options you can set on a disguise. Add 'show' to reveal the options you don't have permission to use");
for (EnumHelp s : enumHelp) {
sender.sendMessage(s.getEnumDescription());
}
}
public String toReadable(String string) {
String[] split = string.split("_");
for (int i = 0; i < split.length; i++)
split[i] = split[i].substring(0, 1) + split[i].substring(1).toLowerCase();
return StringUtils.join(split, "_");
}
}

View File

@@ -0,0 +1,94 @@
package me.libraryaddict.disguise.commands;
import java.util.ArrayList;
import java.util.HashMap;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.utilities.BaseDisguiseCommand;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class DisguisePlayerCommand extends BaseDisguiseCommand {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map = getPermissions(sender);
if (map.isEmpty()) {
sender.sendMessage(ChatColor.RED + "You are forbidden to use this command.");
return true;
}
if (args.length == 0) {
sendCommandUsage(sender, map);
return true;
}
if (args.length == 1) {
sender.sendMessage(ChatColor.RED + "You need to supply a disguise as well as the player");
return true;
}
Player player = Bukkit.getPlayer(args[0]);
if (player == null) {
sender.sendMessage(ChatColor.RED + "Cannot find the player '" + args[0] + "'");
return true;
}
String[] newArgs = new String[args.length - 1];
System.arraycopy(args, 1, newArgs, 0, newArgs.length);
Disguise disguise;
try {
disguise = parseDisguise(sender, newArgs, map);
} catch (DisguiseParseException ex) {
if (ex.getMessage() != null) {
sender.sendMessage(ex.getMessage());
}
return true;
} catch (Exception ex) {
ex.printStackTrace();
return true;
}
if (disguise.isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled()) {
sender.sendMessage(ChatColor.RED
+ "Can't disguise a living entity as a misc disguise. This has been disabled in the config!");
return true;
}
if (DisguiseConfig.isNameOfPlayerShownAboveDisguise()) {
if (disguise.getWatcher() instanceof LivingWatcher) {
((LivingWatcher) disguise.getWatcher()).setCustomName(player.getDisplayName());
if (DisguiseConfig.isNameAboveHeadAlwaysVisible()) {
((LivingWatcher) disguise.getWatcher()).setCustomNameVisible(true);
}
}
}
DisguiseAPI.disguiseToAll(player, disguise);
if (disguise.isDisguiseInUse()) {
sender.sendMessage(ChatColor.RED + "Successfully disguised " + player.getName() + " as a "
+ disguise.getType().toReadable() + "!");
} else {
sender.sendMessage(ChatColor.RED + "Failed to disguise " + player.getName() + " as a "
+ disguise.getType().toReadable() + "!");
}
return true;
}
/**
* Send the player the information
*/
protected void sendCommandUsage(CommandSender sender, HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map) {
ArrayList<String> allowedDisguises = getAllowedDisguises(map);
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"))
sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseplayer <PlayerName> player <Name>");
sender.sendMessage(ChatColor.DARK_GREEN + "/disguiseplayer <PlayerName> <DisguiseType> <Baby>");
if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block"))
sender.sendMessage(ChatColor.DARK_GREEN
+ "/disguiseplayer <PlayerName> <Dropped_Item/Falling_Block> <Id> <Durability>");
}
}

View File

@@ -0,0 +1,173 @@
package me.libraryaddict.disguise.commands;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.utilities.BaseDisguiseCommand;
import me.libraryaddict.disguise.utilities.ClassGetter;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
public class DisguiseRadiusCommand extends BaseDisguiseCommand {
private int maxRadius = 30;
private ArrayList<Class> validClasses = new ArrayList<Class>();
public DisguiseRadiusCommand(int maxRadius) {
this.maxRadius = maxRadius;
for (Class c : ClassGetter.getClassesForPackage("org.bukkit.entity")) {
if (c != Entity.class && Entity.class.isAssignableFrom(c) && c.getAnnotation(Deprecated.class) == null) {
validClasses.add(c);
}
}
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.getName().equals("CONSOLE")) {
sender.sendMessage(ChatColor.RED + "You may not use this command from the console!");
return true;
}
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map = getPermissions(sender);
if (map.isEmpty()) {
sender.sendMessage(ChatColor.RED + "You are forbidden to use this command.");
return true;
}
if (args.length == 0) {
sendCommandUsage(sender, map);
return true;
}
if (args[0].equalsIgnoreCase("entitytype") || args[0].equalsIgnoreCase("entitytypes")) {
ArrayList<String> classes = new ArrayList<String>();
for (Class c : validClasses) {
classes.add(c.getSimpleName());
}
Collections.sort(classes);
sender.sendMessage(ChatColor.DARK_GREEN + "EntityTypes usable are: " + ChatColor.GREEN
+ StringUtils.join(classes, ChatColor.DARK_GREEN + ", " + ChatColor.GREEN) + ChatColor.DARK_GREEN + ".");
return true;
}
Class entityClass = Entity.class;
EntityType type = null;
int starting = 0;
if (!isNumeric(args[0])) {
for (Class c : validClasses) {
if (c.getSimpleName().equalsIgnoreCase(args[0])) {
entityClass = c;
starting = 1;
break;
}
}
if (starting == 0) {
try {
type = EntityType.valueOf(args[0].toUpperCase());
} catch (Exception ex) {
}
if (type == null) {
sender.sendMessage(ChatColor.RED + "Unrecognised EntityType " + args[0]);
return true;
}
}
}
if (args.length == starting + 1) {
sender.sendMessage(ChatColor.RED + "You need to supply a disguise as well as the radius"
+ (starting != 0 ? " and EntityType" : ""));
return true;
}
if (!isNumeric(args[starting])) {
sender.sendMessage(ChatColor.RED + args[starting] + " is not a number");
return true;
}
int radius = Integer.parseInt(args[starting]);
if (radius > maxRadius) {
sender.sendMessage(ChatColor.RED + "Limited radius to " + maxRadius + "! Don't want to make too much lag right?");
radius = maxRadius;
}
String[] newArgs = new String[args.length - (starting + 1)];
System.arraycopy(args, starting + 1, newArgs, 0, newArgs.length);
Disguise disguise;
try {
disguise = parseDisguise(sender, newArgs, map);
} catch (DisguiseParseException ex) {
if (ex.getMessage() != null) {
sender.sendMessage(ex.getMessage());
}
return true;
} catch (Exception ex) {
ex.printStackTrace();
return true;
} // Time to use it!
int disguisedEntitys = 0;
int miscDisguises = 0;
for (Entity entity : ((Player) sender).getNearbyEntities(radius, radius, radius)) {
if (entity == sender)
continue;
if (type != null ? entity.getType() == type : entityClass.isAssignableFrom(entity.getClass())) {
if (disguise.isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled()
&& entity instanceof LivingEntity) {
miscDisguises++;
continue;
}
disguise = disguise.clone();
if (entity instanceof Player && DisguiseConfig.isNameOfPlayerShownAboveDisguise()) {
if (disguise.getWatcher() instanceof LivingWatcher) {
((LivingWatcher) disguise.getWatcher()).setCustomName(((Player) entity).getDisplayName());
if (DisguiseConfig.isNameAboveHeadAlwaysVisible()) {
((LivingWatcher) disguise.getWatcher()).setCustomNameVisible(true);
}
}
}
DisguiseAPI.disguiseToAll(entity, disguise);
if (disguise.isDisguiseInUse()) {
disguisedEntitys++;
}
}
}
if (disguisedEntitys > 0) {
sender.sendMessage(ChatColor.RED + "Successfully disguised " + disguisedEntitys + " entities!");
} else {
sender.sendMessage(ChatColor.RED + "Couldn't find any entities to disguise!");
}
if (miscDisguises > 0) {
sender.sendMessage(ChatColor.RED + "Failed to disguise " + miscDisguises
+ " entities because the option to disguise a living entity as a non-living has been disabled in the config");
}
return true;
}
/**
* Send the player the information
*/
protected void sendCommandUsage(CommandSender sender, HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map) {
ArrayList<String> allowedDisguises = getAllowedDisguises(map);
sender.sendMessage(ChatColor.DARK_GREEN + "Disguise all entities in a radius! Caps at 30 blocks!");
sender.sendMessage(ChatColor.DARK_GREEN + "You can use the disguises: " + ChatColor.GREEN
+ StringUtils.join(allowedDisguises, ChatColor.RED + ", " + ChatColor.GREEN));
String optional = ChatColor.DARK_GREEN + "(" + ChatColor.GREEN + "Optional" + ChatColor.DARK_GREEN + ")";
if (allowedDisguises.contains("player")) {
sender.sendMessage((ChatColor.DARK_GREEN + "/disguiseradius <EntityType" + optional + "> <Radius> player <Name>")
.replace("<", "<" + ChatColor.GREEN).replace(">", ChatColor.DARK_GREEN + ">"));
}
sender.sendMessage((ChatColor.DARK_GREEN + "/disguiseradius <EntityType" + optional + "> <Radius> <DisguiseType> <Baby"
+ optional + ">").replace("<", "<" + ChatColor.GREEN).replace(">", ChatColor.DARK_GREEN + ">"));
if (allowedDisguises.contains("dropped_item") || allowedDisguises.contains("falling_block")) {
sender.sendMessage((ChatColor.DARK_GREEN + "/disguiseradius <EntityType" + optional
+ "> <Radius> <Dropped_Item/Falling_Block> <Id> <Durability" + optional + ">").replace("<",
"<" + ChatColor.GREEN).replace(">", ChatColor.DARK_GREEN + ">"));
}
sender.sendMessage(ChatColor.DARK_GREEN + "See the EntityType's usable by " + ChatColor.GREEN
+ "/disguiseradius EntityTypes");
}
}

View File

@@ -0,0 +1,21 @@
package me.libraryaddict.disguise.commands;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
public class LibsDisguisesCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
sender.sendMessage(ChatColor.DARK_GREEN
+ "This server is running "
+ "Lib's Disguises "
+ (sender.getName().equals("libraryaddict") ? "v"
+ Bukkit.getPluginManager().getPlugin("LibsDisguises").getDescription().getVersion() + " " : "")
+ "by libraryaddict");
return true;
}
}

View File

@@ -0,0 +1,30 @@
package me.libraryaddict.disguise.commands;
import me.libraryaddict.disguise.DisguiseAPI;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
public class UndisguiseCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.getName().equals("CONSOLE")) {
sender.sendMessage(ChatColor.RED + "You may not use this command from the console!");
return true;
}
if (sender.hasPermission("libsdisguises.undisguise")) {
if (DisguiseAPI.isDisguised((Entity) sender)) {
DisguiseAPI.undisguiseToAll((Player) sender);
sender.sendMessage(ChatColor.RED + "You are no longer disguised");
} else
sender.sendMessage(ChatColor.RED + "You are not disguised!");
} else
sender.sendMessage(ChatColor.RED + "You are forbidden to use this command.");
return true;
}
}

View File

@@ -0,0 +1,30 @@
package me.libraryaddict.disguise.commands;
import me.libraryaddict.disguise.DisguiseListener;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
public class UndisguiseEntityCommand implements CommandExecutor {
private DisguiseListener listener;
public UndisguiseEntityCommand(DisguiseListener listener) {
this.listener = listener;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.getName().equals("CONSOLE")) {
sender.sendMessage(ChatColor.RED + "You may not use this command from the console!");
return true;
}
if (sender.hasPermission("libsdisguises.undisguiseentity")) {
listener.setDisguiseEntity(sender.getName(), null);
sender.sendMessage(ChatColor.RED + "Right click a disguised entity to undisguise them!");
} else
sender.sendMessage(ChatColor.RED + "You are forbidden to use this command.");
return true;
}
}

View File

@@ -0,0 +1,33 @@
package me.libraryaddict.disguise.commands;
import me.libraryaddict.disguise.DisguiseAPI;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class UndisguisePlayerCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.hasPermission("libsdisguises.undisguiseplayer")) {
if (args.length > 0) {
Player p = Bukkit.getPlayer(args[0]);
if (p != null) {
if (DisguiseAPI.isDisguised(p)) {
DisguiseAPI.undisguiseToAll(p);
sender.sendMessage(ChatColor.RED + "The player is no longer disguised");
} else
sender.sendMessage(ChatColor.RED + "The player is not disguised!");
} else
sender.sendMessage(ChatColor.RED + "Player not found");
} else
sender.sendMessage(ChatColor.RED + "/undisguiseplayer <Name>");
} else
sender.sendMessage(ChatColor.RED + "You are forbidden to use this command.");
return true;
}
}

View File

@@ -0,0 +1,63 @@
package me.libraryaddict.disguise.commands;
import me.libraryaddict.disguise.DisguiseAPI;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
public class UndisguiseRadiusCommand implements CommandExecutor {
private int maxRadius = 30;
public UndisguiseRadiusCommand(int maxRadius) {
this.maxRadius = maxRadius;
}
private boolean isNumeric(String string) {
try {
Integer.parseInt(string);
return true;
} catch (Exception ex) {
return false;
}
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender.getName().equals("CONSOLE")) {
sender.sendMessage(ChatColor.RED + "You may not use this command from the console!");
return true;
}
if (sender.hasPermission("libsdisguises.undisguiseradius")) {
int radius = maxRadius;
if (args.length > 0) {
if (!isNumeric(args[0])) {
sender.sendMessage(ChatColor.RED + "Error! " + ChatColor.GREEN + args[0] + ChatColor.RED
+ " is not a number!");
return true;
}
radius = Integer.parseInt(args[0]);
if (radius > maxRadius) {
sender.sendMessage(ChatColor.RED + "Limited radius to " + maxRadius
+ "! Don't want to make too much lag right?");
radius = maxRadius;
}
}
int disguisedEntitys = 0;
for (Entity entity : ((Player) sender).getNearbyEntities(radius, radius, radius)) {
if (entity == sender)
continue;
if (DisguiseAPI.isDisguised(entity)) {
DisguiseAPI.undisguiseToAll(entity);
disguisedEntitys++;
}
}
sender.sendMessage(ChatColor.RED + "Successfully undisguised " + disguisedEntitys + " entities!");
} else
sender.sendMessage(ChatColor.RED + "You are forbidden to use this command.");
return true;
}
}

View File

@@ -0,0 +1,28 @@
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);
public static AnimalColor getColor(int nmsId) {
for (AnimalColor color : values()) {
if (color.getId() == nmsId) {
return color;
}
}
return null;
}
private int value;
private AnimalColor(int newValue) {
value = newValue;
}
/**
* The color ID as defined by nms internals.
*/
public int getId() {
return value;
}
}

View File

@@ -0,0 +1,733 @@
package me.libraryaddict.disguise.disguisetypes;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.UUID;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType;
import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.BatWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.HorseWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
import me.libraryaddict.disguise.events.DisguiseEvent;
import me.libraryaddict.disguise.events.UndisguiseEvent;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.PacketsManager;
import me.libraryaddict.disguise.utilities.ReflectionManager;
import me.libraryaddict.disguise.utilities.DisguiseValues;
import me.libraryaddict.disguise.utilities.ReflectionManager.LibVersion;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Horse.Variant;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.reflect.StructureModifier;
public abstract class Disguise {
private static JavaPlugin plugin;
private boolean disguiseInUse;
private DisguiseType disguiseType;
private Entity entity;
private boolean hearSelfDisguise = DisguiseConfig.isSelfDisguisesSoundsReplaced();
private boolean hideArmorFromSelf = DisguiseConfig.isHidingArmorFromSelf();
private boolean hideHeldItemFromSelf = DisguiseConfig.isHidingHeldItemFromSelf();
private boolean keepDisguiseEntityDespawn = DisguiseConfig.isKeepDisguiseOnEntityDespawn();
private boolean keepDisguisePlayerDeath = DisguiseConfig.isKeepDisguiseOnPlayerDeath();
private boolean keepDisguisePlayerLogout = DisguiseConfig.isKeepDisguiseOnPlayerLogout();
private boolean modifyBoundingBox = DisguiseConfig.isModifyBoundingBox();
private boolean replaceSounds = DisguiseConfig.isSoundEnabled();
private BukkitTask task = null;
private Runnable velocityRunnable;
private boolean velocitySent = DisguiseConfig.isVelocitySent();
private boolean viewSelfDisguise = DisguiseConfig.isViewDisguises();
private FlagWatcher watcher;
@Override
public abstract Disguise clone();
/**
* Seems I do this method so I can make cleaner constructors on disguises..
*/
protected void createDisguise(DisguiseType newType) {
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");
}
// Set the disguise type
disguiseType = newType;
// Get if they are a adult now..
boolean isAdult = true;
if (isMobDisguise()) {
isAdult = ((MobDisguise) this).isAdult();
}
try {
// Construct the FlagWatcher from the stored class
setWatcher((FlagWatcher) getType().getWatcherClass().getConstructor(Disguise.class).newInstance(this));
} catch (Exception e) {
e.printStackTrace();
}
// Set the disguise if its a baby or not
if (!isAdult) {
if (getWatcher() instanceof AgeableWatcher) {
((AgeableWatcher) getWatcher()).setBaby(true);
} else if (getWatcher() instanceof ZombieWatcher) {
((ZombieWatcher) getWatcher()).setBaby(true);
}
}
// 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 (getType() == DisguiseType.ZOMBIE_VILLAGER) {
getWatcher().setValue(13, (byte) 1);
}
else if (getType() == DisguiseType.ELDER_GUARDIAN) {
getWatcher().setValue(16, 0 | 4);
}
// 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.
// Not something that a watcher needs to access.
Variant horseType = Variant.valueOf(getType().name());
getWatcher().setValue(19, (byte) horseType.ordinal());
} catch (Exception ex) {
// Ok.. So it aint a horse
}
}
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;
}
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;
}
final double vectorY = velocitySpeed;
final TargetedDisguise disguise = (TargetedDisguise) this;
// A scheduler to clean up any unused disguises.
velocityRunnable = new Runnable() {
private int blockX, blockY, blockZ, facing;
private int deadTicks = 0;
private int refreshDisguise = 0;
public void run() {
// If entity is no longer valid. Remove it.
if (!getEntity().isValid()) {
// If it has been dead for 30+ ticks
// This is to ensure that this disguise isn't removed while clients think its the real entity
// The delay is because if it sends the destroy entity packets straight away, then it means no death animation
// This is probably still a problem for wither and enderdragon deaths.
if (deadTicks++ > (getType() == DisguiseType.ENDER_DRAGON ? 200 : 20)) {
deadTicks = 0;
if (isRemoveDisguiseOnDeath()) {
removeDisguise();
} else {
entity = null;
watcher = getWatcher().clone(disguise);
task.cancel();
task = null;
}
}
} else {
deadTicks = 0;
// If the disguise type is tnt, we need to resend the entity packet else it will turn invisible
if (getType() == DisguiseType.PRIMED_TNT || getType() == DisguiseType.FIREWORK) {
refreshDisguise++;
if (refreshDisguise % 40 == 0) {
refreshDisguise = 0;
DisguiseUtilities.refreshTrackers(disguise);
}
}
if (getType() == DisguiseType.ITEM_FRAME) {
Location loc = getEntity().getLocation();
int newFacing = (((int) loc.getYaw() + 720 + 45) / 90) % 4;
if (loc.getBlockX() != blockX || loc.getBlockY() != blockY || loc.getBlockZ() != blockZ
|| newFacing != facing) {
blockX = loc.getBlockX();
blockY = loc.getBlockY();
blockZ = loc.getBlockZ();
facing = newFacing;
DisguiseUtilities.refreshTrackers(disguise);
}
}
if (isModifyBoundingBox()) {
DisguiseUtilities.doBoundingBox(disguise);
}
if (getType() == DisguiseType.BAT && !((BatWatcher) getWatcher()).isFlying()) {
return;
}
// If the vectorY isn't 0. Cos if it is. Then it doesn't want to send any vectors.
// If this disguise has velocity sending enabled and the entity is flying.
if (isVelocitySent() && vectorY != 0 && (alwaysSendVelocity || !getEntity().isOnGround())) {
Vector vector = getEntity().getVelocity();
// If the entity doesn't have velocity changes already - You know. I really can't wrap my head about the
// if statement.
// But it doesn't seem to do anything wrong..
if (vector.getY() != 0 && !(vector.getY() < 0 && alwaysSendVelocity && getEntity().isOnGround())) {
return;
}
// If disguise isn't a experience orb, or the entity isn't standing on the ground
if (getType() != DisguiseType.EXPERIENCE_ORB || !getEntity().isOnGround()) {
PacketContainer lookPacket = null;
if (getType() == DisguiseType.WITHER_SKULL && DisguiseConfig.isWitherSkullPacketsEnabled()) {
lookPacket = new PacketContainer(PacketType.Play.Server.ENTITY_LOOK);
StructureModifier<Object> mods = lookPacket.getModifier();
lookPacket.getIntegers().write(0, getEntity().getEntityId());
Location loc = getEntity().getLocation();
mods.write(
4,
PacketsManager.getYaw(getType(), getEntity().getType(),
(byte) Math.floor(loc.getYaw() * 256.0F / 360.0F)));
mods.write(5, PacketsManager.getPitch(getType(), DisguiseType.getType(getEntity().getType()),
(byte) Math.floor(loc.getPitch() * 256.0F / 360.0F)));
if (isSelfDisguiseVisible() && getEntity() instanceof Player) {
PacketContainer selfLookPacket = lookPacket.shallowClone();
selfLookPacket.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId());
try {
ProtocolLibrary.getProtocolManager().sendServerPacket((Player) getEntity(),
selfLookPacket, false);
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
try {
PacketContainer velocityPacket = new PacketContainer(PacketType.Play.Server.ENTITY_VELOCITY);
StructureModifier<Integer> mods = velocityPacket.getIntegers();
mods.write(1, (int) (vector.getX() * 8000));
mods.write(3, (int) (vector.getZ() * 8000));
for (Player player : DisguiseUtilities.getPerverts(disguise)) {
if (getEntity() == player) {
if (!isSelfDisguiseVisible()) {
continue;
}
mods.write(0, DisguiseAPI.getSelfDisguiseId());
} else {
mods.write(0, getEntity().getEntityId());
}
mods.write(2, (int) (8000D * (vectorY * ReflectionManager.getPing(player)) * 0.069D));
if (lookPacket != null && player != getEntity()) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, lookPacket, false);
}
ProtocolLibrary.getProtocolManager().sendServerPacket(player, velocityPacket.shallowClone(),
false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// If we need to send a packet to update the exp position as it likes to gravitate client sided to
// players.
}
if (getType() == DisguiseType.EXPERIENCE_ORB) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE);
packet.getIntegers().write(0, getEntity().getEntityId());
try {
for (Player player : DisguiseUtilities.getPerverts(disguise)) {
if (getEntity() != player) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, false);
} else if (isSelfDisguiseVisible()) {
PacketContainer selfPacket = packet.shallowClone();
selfPacket.getModifier().write(0, DisguiseAPI.getSelfDisguiseId());
try {
ProtocolLibrary.getProtocolManager().sendServerPacket((Player) getEntity(), selfPacket,
false);
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
};
}
/**
* Get the disguised entity
*/
public Entity getEntity() {
return entity;
}
/**
* Get the disguise type
*/
public DisguiseType getType() {
return disguiseType;
}
/**
* Get the flag watcher
*/
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.
*/
public boolean isDisguiseInUse() {
return disguiseInUse;
}
public boolean isHidingArmorFromSelf() {
return hideArmorFromSelf;
}
public boolean isHidingHeldItemFromSelf() {
return hideHeldItemFromSelf;
}
public boolean isKeepDisguiseOnEntityDespawn() {
return this.keepDisguiseEntityDespawn;
}
public boolean isKeepDisguiseOnPlayerDeath() {
return this.keepDisguisePlayerDeath;
}
public boolean isKeepDisguiseOnPlayerLogout() {
return this.keepDisguisePlayerLogout;
}
public boolean isMiscDisguise() {
return false;
}
public boolean isMobDisguise() {
return false;
}
public boolean isModifyBoundingBox() {
return modifyBoundingBox;
}
public boolean isPlayerDisguise() {
return false;
}
/**
* Internal use
*/
public boolean isRemoveDisguiseOnDeath() {
return getEntity() instanceof Player ?
(!((Player) getEntity()).isOnline() ? !isKeepDisguiseOnPlayerLogout() : !isKeepDisguiseOnPlayerDeath())
:
(!isKeepDisguiseOnEntityDespawn() || getEntity().isDead());
}
public boolean isSelfDisguiseSoundsReplaced() {
return hearSelfDisguise;
}
/**
* Can the disguised view himself as the disguise
*/
public boolean isSelfDisguiseVisible() {
return viewSelfDisguise;
}
public boolean isSoundsReplaced() {
return replaceSounds;
}
public boolean isVelocitySent() {
return velocitySent;
}
/**
* Removes the disguise and undisguises the entity if its using this disguise.
*
* @return
*/
public boolean removeDisguise() {
if (disguiseInUse) {
UndisguiseEvent event = new UndisguiseEvent(entity, this);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
disguiseInUse = false;
if (task != null) {
task.cancel();
task = null;
}
HashMap<UUID, HashSet<TargetedDisguise>> disguises = DisguiseUtilities.getDisguises();
// If this disguise has a entity set
if (getEntity() != null) {
// If this disguise is active
// Remove the disguise from the current disguises.
if (DisguiseUtilities.removeDisguise((TargetedDisguise) this)) {
if (getEntity() instanceof Player) {
DisguiseUtilities.removeSelfDisguise((Player) getEntity());
}
// Better refresh the entity to undisguise it
if (getEntity().isValid()) {
DisguiseUtilities.refreshTrackers((TargetedDisguise) this);
} else {
DisguiseUtilities.destroyEntity((TargetedDisguise) this);
}
}
} else {
// Loop through the disguises because it could be used with a unknown entity id.
HashMap<Integer, HashSet<TargetedDisguise>> future = DisguiseUtilities.getFutureDisguises();
Iterator<Integer> itel = DisguiseUtilities.getFutureDisguises().keySet().iterator();
while (itel.hasNext()) {
int id = itel.next();
if (future.get(id).remove(this) && future.get(id).isEmpty()) {
itel.remove();
}
}
}
if (isPlayerDisguise()) {
String name = ((PlayerDisguise) this).getName();
if (!DisguiseUtilities.getAddedByPlugins().contains(name.toLowerCase())) {
for (HashSet<TargetedDisguise> disguise : disguises.values()) {
for (Disguise d : disguise) {
if (d.isPlayerDisguise() && ((PlayerDisguise) d).getName().equals(name)) {
return true;
}
}
}
DisguiseUtilities.getGameProfiles().remove(name.toLowerCase());
}
}
return true;
}
}
return false;
}
/**
* Set the entity of the disguise. Only used for internal things.
*/
public Disguise setEntity(Entity entity) {
if (this.getEntity() != null) {
if (getEntity() == entity)
return this;
throw new RuntimeException("This disguise is already in use! Try .clone()");
}
if (isMiscDisguise() && !DisguiseConfig.isMiscDisguisesForLivingEnabled() && entity instanceof LivingEntity) {
throw new RuntimeException(
"Cannot disguise a living entity with a misc disguise. Renable MiscDisguisesForLiving in the config to do this");
}
this.entity = entity;
setupWatcher();
return this;
}
public Disguise setHearSelfDisguise(boolean hearSelfDisguise) {
this.hearSelfDisguise = hearSelfDisguise;
return this;
}
public Disguise setHideArmorFromSelf(boolean hideArmor) {
this.hideArmorFromSelf = hideArmor;
if (getEntity() instanceof Player) {
((Player) getEntity()).updateInventory();
}
return this;
}
public Disguise setHideHeldItemFromSelf(boolean hideHeldItem) {
this.hideHeldItemFromSelf = hideHeldItem;
if (getEntity() instanceof Player) {
((Player) getEntity()).updateInventory();
}
return this;
}
public Disguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) {
this.keepDisguiseEntityDespawn = keepDisguise;
return this;
}
public Disguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) {
this.keepDisguisePlayerDeath = keepDisguise;
return this;
}
public Disguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) {
this.keepDisguisePlayerLogout = keepDisguise;
return this;
}
public Disguise setModifyBoundingBox(boolean modifyBox) {
if (((TargetedDisguise) this).getDisguiseTarget() != TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
throw new RuntimeException(
"Cannot modify the bounding box of a disguise which is not TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS");
}
if (isModifyBoundingBox() != modifyBox) {
this.modifyBoundingBox = modifyBox;
if (DisguiseUtilities.isDisguiseInUse(this)) {
DisguiseUtilities.doBoundingBox((TargetedDisguise) this);
}
}
return this;
}
public Disguise setReplaceSounds(boolean areSoundsReplaced) {
replaceSounds = areSoundsReplaced;
return this;
}
/**
* 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<Integer, Object> disguiseValues = DisguiseValues.getMetaValues(getType());
HashMap<Integer, Object> entityValues = DisguiseValues.getMetaValues(DisguiseType.getType(getEntity().getType()));
// Start from 2 as they ALL share 0 and 1
for (int dataNo = 0; dataNo <= 31; dataNo++) {
// STEP 1. Find out if the watcher has set data on it.
// If the watcher already set a metadata on this
if (getWatcher().hasValue(dataNo)) {
// Better check that the value is stable.
// To check this, I'm going to check if there exists a default value
// Then I'm going to check if the watcher value is the same as the default value.
if (disguiseValues.containsKey(dataNo)) {
// Now check if they are the same class, or both null.
if (disguiseValues.get(dataNo) == null || getWatcher().getValue(dataNo, null) == null) {
if (disguiseValues.get(dataNo) == null && getWatcher().getValue(dataNo, null) == null) {
// They are both null. Idk what this means really.
continue;
}
} else if (getWatcher().getValue(dataNo, null).getClass() == disguiseValues.get(dataNo).getClass()) {
// The classes are the same. The client "shouldn't" crash.
continue;
}
}
}
// 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))
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));
continue;
}
// Else if the disguise doesn't have it. But the entity does. Better remove it!
if (entityValues.containsKey(dataNo) && !disguiseValues.containsKey(dataNo)) {
getWatcher().setBackupValue(dataNo, null);
continue;
}
Object eObj = entityValues.get(dataNo);
Object dObj = disguiseValues.get(dataNo);
if (eObj == null || dObj == null) {
if (eObj == null && dObj == null)
continue;
else {
getWatcher().setBackupValue(dataNo, dObj);
continue;
}
}
if (eObj.getClass() != dObj.getClass()) {
getWatcher().setBackupValue(dataNo, dObj);
continue;
}
// Since they both share it. With the same classes. Time to check if its from something they extend.
// Better make this clear before I compare the values because some default values are different!
// Entity is 0 & 1 - But we aint gonna be checking that
// EntityAgeable is 16
// 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;
}
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))
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))
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!
getWatcher().setBackupValue(dataNo, disguiseValues.get(dataNo));
}
}
public Disguise setVelocitySent(boolean sendVelocity) {
this.velocitySent = sendVelocity;
return this;
}
/**
* Can the disguised view himself as the disguise
*
* @return
*/
public Disguise setViewSelfDisguise(boolean viewSelfDisguise) {
if (isSelfDisguiseVisible() != viewSelfDisguise) {
this.viewSelfDisguise = viewSelfDisguise;
if (getEntity() != null && getEntity() instanceof Player) {
if (DisguiseAPI.getDisguise((Player) getEntity(), getEntity()) == this) {
if (isSelfDisguiseVisible()) {
DisguiseUtilities.setupFakeDisguise(this);
} else
DisguiseUtilities.removeSelfDisguise((Player) getEntity());
}
}
}
return this;
}
public Disguise setWatcher(FlagWatcher newWatcher) {
if (!getType().getWatcherClass().isInstance(newWatcher)) {
throw new IllegalArgumentException(newWatcher.getClass().getSimpleName() + " is not a instance of "
+ getType().getWatcherClass().getSimpleName() + " for DisguiseType " + getType().name());
}
watcher = newWatcher;
if (getEntity() != null) {
setupWatcher();
}
return this;
}
public boolean startDisguise() {
if (!isDisguiseInUse()) {
if (getEntity() == null) {
throw new RuntimeException("No entity is assigned to this disguise!");
}
// Fire a disguise event
DisguiseEvent event = new DisguiseEvent(entity, this);
Bukkit.getPluginManager().callEvent(event);
// If they cancelled this disguise event. No idea why.
// Just return.
if (!event.isCancelled()) {
disguiseInUse = true;
task = Bukkit.getScheduler().runTaskTimer(plugin, velocityRunnable, 1, 1);
// Stick the disguise in the disguises bin
DisguiseUtilities.addDisguise(entity.getUniqueId(), (TargetedDisguise) this);
if (isSelfDisguiseVisible() && getEntity() instanceof Player) {
DisguiseUtilities.removeSelfDisguise((Player) getEntity());
}
// Resend the disguised entity's packet
DisguiseUtilities.refreshTrackers((TargetedDisguise) this);
// If he is a player, then self disguise himself
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
public void run() {
DisguiseUtilities.setupFakeDisguise(Disguise.this);
}
}, 2);
return true;
}
}
return false;
}
public boolean stopDisguise() {
return removeDisguise();
}
}

View File

@@ -0,0 +1,333 @@
package me.libraryaddict.disguise.disguisetypes;
import java.lang.reflect.Method;
import org.apache.commons.lang.StringUtils;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Guardian;
import org.bukkit.entity.Horse;
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;
private static Method isVillager, getVariant, getSkeletonType, isElder;
static {
// We set the entity type in this so that we can safely ignore disguisetypes which don't exist in older versions of MC.
// Without erroring up everything.
for (DisguiseType type : values()) {
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;
}
type.setEntityType(EntityType.valueOf(toUse.name()));
} catch (Throwable ex) {
// This version of craftbukkit doesn't have the disguise.
}
}
try {
isVillager = Zombie.class.getMethod("isVillager");
} catch (Throwable ignored) {
}
try {
getVariant = Horse.class.getMethod("getVariant");
} catch (Throwable ignored) {
// Pre-1.6, but that isn't even supported
}
try {
getSkeletonType = Skeleton.class.getMethod("getSkeletonType");
} catch (Throwable ignored) {
}
try {
isElder = Guardian.class.getMethod("isElder");
} catch (Throwable ignored) {
}
}
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;
}
} catch (Exception ex) {
ex.printStackTrace();
}
break;
case HORSE:
try {
Object variant = getVariant.invoke(entity);
disguiseType = DisguiseType.valueOf(((Enum) variant).name());
} catch (Exception ex) {
ex.printStackTrace();
}
break;
case SKELETON:
try {
Object type = getSkeletonType.invoke(entity);
if (type == Skeleton.SkeletonType.WITHER) {
disguiseType = DisguiseType.WITHER_SKELETON;
}
} catch (Exception ex) {
ex.printStackTrace();
}
break;
case GUARDIAN:
try {
if ((Boolean) isElder.invoke(entity)) {
disguiseType = DisguiseType.ELDER_GUARDIAN;
}
} catch (Exception ex) {
ex.printStackTrace();
}
break;
default:
break;
}
return disguiseType;
}
public static DisguiseType getType(EntityType entityType) {
try {
return valueOf(entityType.name().toUpperCase());
} catch (Throwable ex) {
return null;
}
}
private int defaultId, entityId;
private EntityType entityType;
private Class<? extends FlagWatcher> watcherClass;
private DisguiseType(int... ints) {
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;
}
}
}
public int getDefaultId() {
return defaultId;
}
public Class<? extends Entity> getEntityClass() {
if (entityType != null) {
return getEntityType().getEntityClass();
}
return Entity.class;
}
public int getEntityId() {
return entityId;
}
public EntityType getEntityType() {
return entityType;
}
public int getTypeId() {
return (int) getEntityType().getTypeId();
}
public Class getWatcherClass() {
return watcherClass;
}
public boolean isMisc() {
return getEntityType() != null && !getEntityType().isAlive();
}
public boolean isMob() {
return getEntityType() != null && getEntityType().isAlive() && !isPlayer();
}
public boolean isPlayer() {
return this == DisguiseType.PLAYER;
}
private void setEntityType(EntityType entityType) {
this.entityType = entityType;
}
public void setWatcherClass(Class<? extends FlagWatcher> c) {
watcherClass = c;
}
public String toReadable() {
String[] split = name().split("_");
for (int i = 0; i < split.length; i++)
split[i] = split[i].substring(0, 1) + split[i].substring(1).toLowerCase();
return StringUtils.join(split, " ");
}
}

View File

@@ -0,0 +1,394 @@
package me.libraryaddict.disguise.disguisetypes;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.ItemStack;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.DisguiseConfig;
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;
private SlotType(int no) {
slotNo = no;
}
public int getSlot() {
return slotNo;
}
}
private boolean addEntityAnimations = DisguiseConfig.isEntityAnimationsAdded();
/**
* This is the entity values I need to add else it could crash them..
*/
private HashMap<Integer, Object> backupEntityValues = new HashMap<Integer, Object>();
private TargetedDisguise disguise;
private HashMap<Integer, Object> entityValues = new HashMap<Integer, Object>();
private boolean hasDied;
private ItemStack[] items = new ItemStack[5];
private HashSet<Integer> modifiedEntityAnimations = new HashSet<Integer>();
private List<WrappedWatchableObject> watchableObjects;
public FlagWatcher(Disguise disguise) {
this.disguise = (TargetedDisguise) disguise;
}
private byte addEntityAnimations(byte originalValue, byte entityValue) {
byte valueByte = originalValue;
for (int i = 0; i < 6; i++) {
if ((entityValue & 1 << i) != 0 && !modifiedEntityAnimations.contains(i)) {
valueByte = (byte) (valueByte | 1 << i);
}
}
originalValue = valueByte;
return originalValue;
}
public FlagWatcher clone(Disguise owningDisguise) {
FlagWatcher cloned;
try {
cloned = getClass().getConstructor(Disguise.class).newInstance(getDisguise());
} catch (Exception e) {
e.printStackTrace();
cloned = new FlagWatcher(getDisguise());
}
cloned.entityValues = (HashMap<Integer, Object>) entityValues.clone();
cloned.items = items.clone();
cloned.modifiedEntityAnimations = (HashSet) modifiedEntityAnimations.clone();
cloned.addEntityAnimations = addEntityAnimations;
return cloned;
}
public List<WrappedWatchableObject> convert(List<WrappedWatchableObject> list) {
List<WrappedWatchableObject> newList = new ArrayList<WrappedWatchableObject>();
HashSet<Integer> sentValues = new HashSet<Integer>();
boolean sendAllCustom = false;
for (WrappedWatchableObject watch : list) {
int dataType = watch.getIndex();
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)
sendAllCustom = true;
Object value = null;
if (entityValues.containsKey(dataType)) {
if (entityValues.get(dataType) == null)
continue;
value = entityValues.get(dataType);
} else if (backupEntityValues.containsKey(dataType)) {
if (backupEntityValues.get(dataType) == null)
continue;
value = backupEntityValues.get(dataType);
}
if (value != null) {
if (isEntityAnimationsAdded() && dataType == 0) {
value = this.addEntityAnimations((Byte) value, (Byte) watch.getValue());
}
boolean isDirty = watch.getDirtyState();
watch = new WrappedWatchableObject(dataType, value);
if (!isDirty)
watch.setDirtyState(false);
} else {
boolean isDirty = watch.getDirtyState();
watch = new WrappedWatchableObject(dataType, watch.getValue());
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))
continue;
Object obj = entityValues.get(value);
if (obj == null)
continue;
WrappedWatchableObject watch = new WrappedWatchableObject(value, obj);
newList.add(watch);
}
}
// Here we check for if there is a health packet that says they died.
if (getDisguise().isSelfDisguiseVisible() && getDisguise().getEntity() != null
&& getDisguise().getEntity() instanceof Player) {
for (WrappedWatchableObject watch : newList) {
// Its a health packet
if (watch.getIndex() == 6) {
Object value = watch.getValue();
if (value != null && value instanceof Float) {
float newHealth = (Float) value;
if (newHealth > 0 && hasDied) {
hasDied = false;
DisguiseUtilities.sendSelfDisguise((Player) getDisguise().getEntity(), disguise);
} else if (newHealth <= 0 && !hasDied) {
hasDied = true;
}
}
}
}
}
return newList;
}
public ItemStack[] getArmor() {
ItemStack[] armor = new ItemStack[4];
System.arraycopy(items, 0, armor, 0, 4);
return armor;
}
public String getCustomName() {
return (String) getValue(2, null);
}
protected TargetedDisguise getDisguise() {
return disguise;
}
private boolean getFlag(int byteValue) {
return ((Byte) getValue(0, (byte) 0) & 1 << byteValue) != 0;
}
public ItemStack getItemInHand() {
return getItemStack(SlotType.HELD_ITEM);
}
public ItemStack getItemStack(int slot) {
return items[slot];
}
public ItemStack getItemStack(SlotType slot) {
return getItemStack(slot.getSlot());
}
protected Object getValue(int no, Object backup) {
if (entityValues.containsKey(no))
return entityValues.get(no);
return backup;
}
public List<WrappedWatchableObject> getWatchableObjects() {
if (watchableObjects == null) {
rebuildWatchableObjects();
}
return watchableObjects;
}
public boolean hasCustomName() {
return getCustomName() != null;
}
protected boolean hasValue(int no) {
return entityValues.containsKey(no);
}
public boolean isBurning() {
return getFlag(0);
}
public boolean isCustomNameVisible() {
return (Byte) getValue(3, (byte) 0) == 1;
}
public boolean isEntityAnimationsAdded() {
return addEntityAnimations;
}
public boolean isInvisible() {
return getFlag(5);
}
public boolean isRightClicking() {
return getFlag(4);
}
public boolean isSneaking() {
return getFlag(1);
}
public boolean isSprinting() {
return getFlag(3);
}
public void rebuildWatchableObjects() {
watchableObjects = new ArrayList<WrappedWatchableObject>();
for (int i = 0; i <= 31; i++) {
WrappedWatchableObject watchable = null;
if (this.entityValues.containsKey(i) && this.entityValues.get(i) != null) {
watchable = new WrappedWatchableObject(i, entityValues.get(i));
} else if (this.backupEntityValues.containsKey(i) && this.backupEntityValues.get(i) != null) {
watchable = new WrappedWatchableObject(i, backupEntityValues.get(i));
}
if (watchable != null) {
watchableObjects.add(watchable);
}
}
}
protected void sendData(int... dataValues) {
if (!DisguiseAPI.isDisguiseInUse(getDisguise()) || getDisguise().getWatcher() != this)
return;
List<WrappedWatchableObject> list = new ArrayList<WrappedWatchableObject>();
for (int data : dataValues) {
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));
}
list.add(new WrappedWatchableObject(data, value));
}
if (!list.isEmpty()) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
StructureModifier<Object> mods = packet.getModifier();
mods.write(0, getDisguise().getEntity().getEntityId());
packet.getWatchableCollectionModifier().write(0, list);
for (Player player : DisguiseUtilities.getPerverts(getDisguise())) {
try {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
public void setAddEntityAnimations(boolean isEntityAnimationsAdded) {
this.addEntityAnimations = isEntityAnimationsAdded;
}
public void setArmor(ItemStack[] itemstack) {
for (int i = 0; i < itemstack.length; i++) {
setItemStack(i, itemstack[i]);
}
}
protected void setBackupValue(int no, Object value) {
backupEntityValues.put(no, value);
}
public void setBurning(boolean setBurning) {
setFlag(0, setBurning);
sendData(0);
}
public void setCustomName(String name) {
if (name != null && name.length() > 64) {
name = name.substring(0, 64);
}
setValue(2, name);
sendData(2);
}
public void setCustomNameVisible(boolean display) {
setValue(3, (byte) (display ? 1 : 0));
sendData(3);
}
private void setFlag(int byteValue, boolean flag) {
modifiedEntityAnimations.add(byteValue);
byte b0 = (Byte) getValue(0, (byte) 0);
if (flag) {
setValue(0, (byte) (b0 | 1 << byteValue));
} else {
setValue(0, (byte) (b0 & ~(1 << byteValue)));
}
}
public void setInvisible(boolean setInvis) {
setFlag(5, setInvis);
sendData(0);
}
public void setItemInHand(ItemStack itemstack) {
setItemStack(SlotType.HELD_ITEM, itemstack);
}
public void setItemStack(int slot, ItemStack itemStack) {
// Itemstack which is null means that its not replacing the disguises itemstack.
if (itemStack == null) {
// Find the item to replace it with
if (getDisguise().getEntity() instanceof LivingEntity) {
EntityEquipment equipment = ((LivingEntity) getDisguise().getEntity()).getEquipment();
if (slot == 4) {
itemStack = equipment.getItemInHand();
} else {
itemStack = equipment.getArmorContents()[slot];
}
if (itemStack != null && itemStack.getTypeId() == 0) {
itemStack = null;
}
}
}
Object itemToSend = null;
if (itemStack != null && itemStack.getTypeId() != 0) {
itemToSend = ReflectionManager.getNmsItem(itemStack);
}
items[slot] = itemStack;
if (DisguiseAPI.isDisguiseInUse(getDisguise()) && getDisguise().getWatcher() == this) {
slot++;
if (slot > 4)
slot = 0;
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
StructureModifier<Object> mods = packet.getModifier();
mods.write(0, getDisguise().getEntity().getEntityId());
mods.write(1, slot);
mods.write(2, itemToSend);
for (Player player : DisguiseUtilities.getPerverts(getDisguise())) {
try {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
public void setItemStack(SlotType slot, ItemStack itemStack) {
setItemStack(slot.getSlot(), itemStack);
}
public void setRightClicking(boolean setRightClicking) {
setFlag(4, setRightClicking);
sendData(0);
}
public void setSneaking(boolean setSneaking) {
setFlag(1, setSneaking);
sendData(0);
}
public void setSprinting(boolean setSprinting) {
setFlag(3, setSprinting);
sendData(0);
}
protected void setValue(int no, Object value) {
entityValues.put(no, value);
if (!DisguiseConfig.isMetadataPacketsEnabled()) {
this.rebuildWatchableObjects();
}
}
}

View File

@@ -0,0 +1,229 @@
package me.libraryaddict.disguise.disguisetypes;
import java.security.InvalidParameterException;
import me.libraryaddict.disguise.disguisetypes.watchers.DroppedItemWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.FallingBlockWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.PaintingWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.SplashPotionWatcher;
import org.bukkit.Art;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
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) {
this(disguiseType, -1, -1);
}
@Deprecated
public MiscDisguise(DisguiseType disguiseType, boolean replaceSounds) {
this(disguiseType, replaceSounds, -1, -1);
}
@Deprecated
public MiscDisguise(DisguiseType disguiseType, boolean replaceSounds, int addictionalData) {
this(disguiseType, replaceSounds, (disguiseType == DisguiseType.FALLING_BLOCK
|| disguiseType == DisguiseType.DROPPED_ITEM ? addictionalData : -1), (disguiseType == DisguiseType.FALLING_BLOCK
|| disguiseType == DisguiseType.DROPPED_ITEM ? -1 : addictionalData));
}
@Deprecated
public MiscDisguise(DisguiseType disguiseType, boolean replaceSounds, int id, int data) {
this(disguiseType, id, data);
this.setReplaceSounds(replaceSounds);
}
public MiscDisguise(DisguiseType disguiseType, int id) {
this(disguiseType, id, -1);
}
public MiscDisguise(DisguiseType disguiseType, int firstParam, int secondParam) {
if (!disguiseType.isMisc()) {
throw new InvalidParameterException("Expected a non-living DisguiseType while constructing MiscDisguise. Received "
+ disguiseType + " instead. Please use " + (disguiseType.isPlayer() ? "PlayerDisguise" : "MobDisguise")
+ " instead");
}
createDisguise(disguiseType);
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;
}
}
@Deprecated
public MiscDisguise(EntityType entityType) {
this(entityType, -1, -1);
}
@Deprecated
public MiscDisguise(EntityType entityType, boolean replaceSounds) {
this(entityType, replaceSounds, -1, -1);
}
@Deprecated
public MiscDisguise(EntityType entityType, boolean replaceSounds, int id, int data) {
this(DisguiseType.getType(entityType), replaceSounds, id, data);
}
@Deprecated
public MiscDisguise(EntityType entityType, int id) {
this(entityType, id, -1);
}
@Deprecated
public MiscDisguise(EntityType disguiseType, int id, int data) {
this(DisguiseType.getType(disguiseType), id, data);
}
public MiscDisguise addPlayer(Player player) {
return (MiscDisguise) super.addPlayer(player);
}
public MiscDisguise addPlayer(String playername) {
return (MiscDisguise) super.addPlayer(playername);
}
@Override
public MiscDisguise clone() {
MiscDisguise disguise = new MiscDisguise(getType(), getData());
disguise.setReplaceSounds(isSoundsReplaced());
disguise.setViewSelfDisguise(isSelfDisguiseVisible());
disguise.setHearSelfDisguise(isSelfDisguiseSoundsReplaced());
disguise.setHideArmorFromSelf(isHidingArmorFromSelf());
disguise.setHideHeldItemFromSelf(isHidingHeldItemFromSelf());
disguise.setVelocitySent(isVelocitySent());
disguise.setModifyBoundingBox(isModifyBoundingBox());
disguise.setWatcher(getWatcher().clone(disguise));
return disguise;
}
/**
* This is the getId of everything but falling block.
*/
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;
}
}
/**
* Only falling block should use this
*/
public int getId() {
if (getType() == DisguiseType.FALLING_BLOCK) {
return ((FallingBlockWatcher) getWatcher()).getBlock().getTypeId();
}
return id;
}
public boolean isMiscDisguise() {
return true;
}
public MiscDisguise removePlayer(Player player) {
return (MiscDisguise) super.removePlayer(player);
}
public MiscDisguise removePlayer(String playername) {
return (MiscDisguise) super.removePlayer(playername);
}
public MiscDisguise setDisguiseTarget(TargetType newTargetType) {
return (MiscDisguise) super.setDisguiseTarget(newTargetType);
}
@Override
public MiscDisguise setEntity(Entity entity) {
return (MiscDisguise) super.setEntity(entity);
}
public MiscDisguise setHearSelfDisguise(boolean hearSelfDisguise) {
return (MiscDisguise) super.setHearSelfDisguise(hearSelfDisguise);
}
public MiscDisguise setHideArmorFromSelf(boolean hideArmor) {
return (MiscDisguise) super.setHideArmorFromSelf(hideArmor);
}
public MiscDisguise setHideHeldItemFromSelf(boolean hideHeldItem) {
return (MiscDisguise) super.setHideHeldItemFromSelf(hideHeldItem);
}
public MiscDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) {
return (MiscDisguise) super.setKeepDisguiseOnEntityDespawn(keepDisguise);
}
public MiscDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) {
return (MiscDisguise) super.setKeepDisguiseOnPlayerDeath(keepDisguise);
}
public MiscDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) {
return (MiscDisguise) super.setKeepDisguiseOnPlayerLogout(keepDisguise);
}
public MiscDisguise setModifyBoundingBox(boolean modifyBox) {
return (MiscDisguise) super.setModifyBoundingBox(modifyBox);
}
public MiscDisguise setReplaceSounds(boolean areSoundsReplaced) {
return (MiscDisguise) super.setReplaceSounds(areSoundsReplaced);
}
public MiscDisguise setVelocitySent(boolean sendVelocity) {
return (MiscDisguise) super.setVelocitySent(sendVelocity);
}
public MiscDisguise setViewSelfDisguise(boolean viewSelfDisguise) {
return (MiscDisguise) super.setViewSelfDisguise(viewSelfDisguise);
}
public MiscDisguise setWatcher(FlagWatcher newWatcher) {
return (MiscDisguise) super.setWatcher(newWatcher);
}
public MiscDisguise silentlyAddPlayer(String playername) {
return (MiscDisguise) super.silentlyAddPlayer(playername);
}
public MiscDisguise silentlyRemovePlayer(String playername) {
return (MiscDisguise) super.silentlyRemovePlayer(playername);
}
}

View File

@@ -0,0 +1,168 @@
package me.libraryaddict.disguise.disguisetypes;
import java.security.InvalidParameterException;
import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
public class MobDisguise extends TargetedDisguise {
private boolean isAdult;
public MobDisguise(DisguiseType disguiseType) {
this(disguiseType, true);
}
public MobDisguise(DisguiseType disguiseType, boolean isAdult) {
if (!disguiseType.isMob()) {
throw new InvalidParameterException("Expected a living DisguiseType while constructing MobDisguise. Received "
+ disguiseType + " instead. Please use " + (disguiseType.isPlayer() ? "PlayerDisguise" : "MiscDisguise")
+ " instead");
}
this.isAdult = isAdult;
createDisguise(disguiseType);
}
@Deprecated
public MobDisguise(DisguiseType disguiseType, boolean isAdult, boolean replaceSounds) {
this(disguiseType, isAdult);
this.setReplaceSounds(replaceSounds);
}
@Deprecated
public MobDisguise(EntityType entityType) {
this(entityType, true);
}
@Deprecated
public MobDisguise(EntityType entityType, boolean isAdult) {
this(DisguiseType.getType(entityType), isAdult);
}
@Deprecated
public MobDisguise(EntityType entityType, boolean isAdult, boolean replaceSounds) {
this(entityType, isAdult);
this.setReplaceSounds(replaceSounds);
}
public MobDisguise addPlayer(Player player) {
return (MobDisguise) super.addPlayer(player);
}
public MobDisguise addPlayer(String playername) {
return (MobDisguise) super.addPlayer(playername);
}
@Override
public MobDisguise clone() {
MobDisguise disguise = new MobDisguise(getType(), isAdult());
disguise.setReplaceSounds(isSoundsReplaced());
disguise.setViewSelfDisguise(isSelfDisguiseVisible());
disguise.setHearSelfDisguise(isSelfDisguiseSoundsReplaced());
disguise.setHideArmorFromSelf(isHidingArmorFromSelf());
disguise.setHideHeldItemFromSelf(isHidingHeldItemFromSelf());
disguise.setVelocitySent(isVelocitySent());
disguise.setModifyBoundingBox(isModifyBoundingBox());
disguise.setWatcher(getWatcher().clone(disguise));
return disguise;
}
public boolean doesDisguiseAge() {
return getWatcher() != null && (getWatcher() instanceof AgeableWatcher || getWatcher() instanceof ZombieWatcher);
}
@Override
public LivingWatcher getWatcher() {
return (LivingWatcher) super.getWatcher();
}
public boolean isAdult() {
if (getWatcher() != null) {
if (getWatcher() instanceof AgeableWatcher) {
return ((AgeableWatcher) getWatcher()).isAdult();
} else if (getWatcher() instanceof ZombieWatcher) {
return ((ZombieWatcher) getWatcher()).isAdult();
}
return true;
}
return isAdult;
}
public boolean isMobDisguise() {
return true;
}
public MobDisguise removePlayer(Player player) {
return (MobDisguise) super.removePlayer(player);
}
public MobDisguise removePlayer(String playername) {
return (MobDisguise) super.removePlayer(playername);
}
public MobDisguise setDisguiseTarget(TargetType newTargetType) {
return (MobDisguise) super.setDisguiseTarget(newTargetType);
}
@Override
public MobDisguise setEntity(Entity entity) {
return (MobDisguise) super.setEntity(entity);
}
public MobDisguise setHearSelfDisguise(boolean hearSelfDisguise) {
return (MobDisguise) super.setHearSelfDisguise(hearSelfDisguise);
}
public MobDisguise setHideArmorFromSelf(boolean hideArmor) {
return (MobDisguise) super.setHideArmorFromSelf(hideArmor);
}
public MobDisguise setHideHeldItemFromSelf(boolean hideHeldItem) {
return (MobDisguise) super.setHideHeldItemFromSelf(hideHeldItem);
}
public MobDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) {
return (MobDisguise) super.setKeepDisguiseOnEntityDespawn(keepDisguise);
}
public MobDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) {
return (MobDisguise) super.setKeepDisguiseOnPlayerDeath(keepDisguise);
}
public MobDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) {
return (MobDisguise) super.setKeepDisguiseOnPlayerLogout(keepDisguise);
}
public MobDisguise setModifyBoundingBox(boolean modifyBox) {
return (MobDisguise) super.setModifyBoundingBox(modifyBox);
}
public MobDisguise setReplaceSounds(boolean areSoundsReplaced) {
return (MobDisguise) super.setReplaceSounds(areSoundsReplaced);
}
public MobDisguise setVelocitySent(boolean sendVelocity) {
return (MobDisguise) super.setVelocitySent(sendVelocity);
}
public MobDisguise setViewSelfDisguise(boolean viewSelfDisguise) {
return (MobDisguise) super.setViewSelfDisguise(viewSelfDisguise);
}
public MobDisguise setWatcher(FlagWatcher newWatcher) {
return (MobDisguise) super.setWatcher(newWatcher);
}
public MobDisguise silentlyAddPlayer(String playername) {
return (MobDisguise) super.silentlyAddPlayer(playername);
}
public MobDisguise silentlyRemovePlayer(String playername) {
return (MobDisguise) super.silentlyRemovePlayer(playername);
}
}

View File

@@ -0,0 +1,224 @@
package me.libraryaddict.disguise.disguisetypes;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.LibsProfileLookup;
import me.libraryaddict.disguise.utilities.ReflectionManager;
import me.libraryaddict.disguise.utilities.ReflectionManager.LibVersion;
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)
name = name.substring(0, 16);
playerName = name;
createDisguise(DisguiseType.PLAYER);
}
@Deprecated
public PlayerDisguise(String name, boolean replaceSounds) {
this(name);
this.setReplaceSounds(replaceSounds);
}
public PlayerDisguise(String name, String skinToUse) {
this(name);
setSkin(skinToUse);
}
public PlayerDisguise(WrappedGameProfile gameProfile) {
this(gameProfile.getName());
this.gameProfile = gameProfile;
}
public PlayerDisguise addPlayer(Player player) {
return (PlayerDisguise) super.addPlayer(player);
}
public PlayerDisguise addPlayer(String playername) {
return (PlayerDisguise) super.addPlayer(playername);
}
@Override
public PlayerDisguise clone() {
PlayerDisguise disguise = new PlayerDisguise(getName());
if (disguise.currentLookup == null && disguise.gameProfile != null) {
disguise.skinToUse = getSkin();
disguise.gameProfile = gameProfile;
} else {
disguise.setSkin(getSkin());
}
disguise.setReplaceSounds(isSoundsReplaced());
disguise.setViewSelfDisguise(isSelfDisguiseVisible());
disguise.setHearSelfDisguise(isSelfDisguiseSoundsReplaced());
disguise.setHideArmorFromSelf(isHidingArmorFromSelf());
disguise.setHideHeldItemFromSelf(isHidingHeldItemFromSelf());
disguise.setVelocitySent(isVelocitySent());
disguise.setModifyBoundingBox(isModifyBoundingBox());
disguise.setWatcher(getWatcher().clone(disguise));
return disguise;
}
public void setGameProfile(WrappedGameProfile gameProfile) {
this.gameProfile = ReflectionManager.getGameProfileWithThisSkin(null, gameProfile.getName(), gameProfile);
}
public WrappedGameProfile getGameProfile() {
if (gameProfile == null) {
if (getSkin() != null) {
gameProfile = ReflectionManager.getGameProfile(null, getName());
} else {
gameProfile = ReflectionManager.getGameProfileWithThisSkin(null, getName(),
DisguiseUtilities.getProfileFromMojang(this));
}
}
return gameProfile;
}
public String getName() {
return playerName;
}
public String getSkin() {
return skinToUse;
}
@Override
public PlayerWatcher getWatcher() {
return (PlayerWatcher) super.getWatcher();
}
@Override
public boolean isPlayerDisguise() {
return true;
}
public PlayerDisguise removePlayer(Player player) {
return (PlayerDisguise) super.removePlayer(player);
}
public PlayerDisguise removePlayer(String playername) {
return (PlayerDisguise) super.removePlayer(playername);
}
public PlayerDisguise setDisguiseTarget(TargetType newTargetType) {
return (PlayerDisguise) super.setDisguiseTarget(newTargetType);
}
@Override
public PlayerDisguise setEntity(Entity entity) {
return (PlayerDisguise) super.setEntity(entity);
}
public PlayerDisguise setHearSelfDisguise(boolean hearSelfDisguise) {
return (PlayerDisguise) super.setHearSelfDisguise(hearSelfDisguise);
}
public PlayerDisguise setHideArmorFromSelf(boolean hideArmor) {
return (PlayerDisguise) super.setHideArmorFromSelf(hideArmor);
}
public PlayerDisguise setHideHeldItemFromSelf(boolean hideHeldItem) {
return (PlayerDisguise) super.setHideHeldItemFromSelf(hideHeldItem);
}
public PlayerDisguise setKeepDisguiseOnEntityDespawn(boolean keepDisguise) {
return (PlayerDisguise) super.setKeepDisguiseOnEntityDespawn(keepDisguise);
}
public PlayerDisguise setKeepDisguiseOnPlayerDeath(boolean keepDisguise) {
return (PlayerDisguise) super.setKeepDisguiseOnPlayerDeath(keepDisguise);
}
public PlayerDisguise setKeepDisguiseOnPlayerLogout(boolean keepDisguise) {
return (PlayerDisguise) super.setKeepDisguiseOnPlayerLogout(keepDisguise);
}
public PlayerDisguise setModifyBoundingBox(boolean modifyBox) {
return (PlayerDisguise) super.setModifyBoundingBox(modifyBox);
}
public PlayerDisguise setReplaceSounds(boolean areSoundsReplaced) {
return (PlayerDisguise) super.setReplaceSounds(areSoundsReplaced);
}
public PlayerDisguise setSkin(String skinToUse) {
this.skinToUse = skinToUse;
if (skinToUse == null) {
this.currentLookup = null;
this.gameProfile = null;
} else {
if (skinToUse.length() > 16) {
this.skinToUse = skinToUse.substring(0, 16);
}
currentLookup = new LibsProfileLookup() {
@Override
public void onLookup(WrappedGameProfile gameProfile) {
if (currentLookup == this && gameProfile != null) {
setSkin(gameProfile);
if (!gameProfile.getProperties().isEmpty() && DisguiseUtilities.isDisguiseInUse(PlayerDisguise.this)) {
DisguiseUtilities.refreshTrackers(PlayerDisguise.this);
}
currentLookup = null;
}
}
};
WrappedGameProfile gameProfile = DisguiseUtilities.getProfileFromMojang(this.skinToUse, currentLookup);
if (gameProfile != null) {
setSkin(gameProfile);
}
}
return this;
}
/**
* Set the GameProfile, without tampering.
*
* @param gameProfile
* GameProfile
* @return
*/
public PlayerDisguise setSkin(WrappedGameProfile gameProfile) {
if (gameProfile == null) {
this.gameProfile = null;
this.skinToUse = null;
return this;
}
Validate.notEmpty(gameProfile.getName(), "Name must be set");
this.skinToUse = gameProfile.getName();
this.gameProfile = ReflectionManager.getGameProfileWithThisSkin(null, getName(), gameProfile);
return this;
}
public PlayerDisguise setVelocitySent(boolean sendVelocity) {
return (PlayerDisguise) super.setVelocitySent(sendVelocity);
}
public PlayerDisguise setViewSelfDisguise(boolean viewSelfDisguise) {
return (PlayerDisguise) super.setViewSelfDisguise(viewSelfDisguise);
}
public PlayerDisguise setWatcher(FlagWatcher newWatcher) {
return (PlayerDisguise) super.setWatcher(newWatcher);
}
public PlayerDisguise silentlyAddPlayer(String playername) {
return (PlayerDisguise) super.silentlyAddPlayer(playername);
}
public PlayerDisguise silentlyRemovePlayer(String playername) {
return (PlayerDisguise) super.silentlyRemovePlayer(playername);
}
}

View File

@@ -0,0 +1,24 @@
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) {
for (RabbitType type : values()) {
if (type.getTypeId() == id) {
return type;
}
}
return null;
}
private int type;
private RabbitType(int type) {
this.type = type;
}
public int getTypeId() {
return type;
}
}

View File

@@ -0,0 +1,93 @@
package me.libraryaddict.disguise.disguisetypes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
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;
}
private List<String> disguiseViewers = new ArrayList<String>();
private TargetType targetType = TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS;
public TargetedDisguise addPlayer(Player player) {
addPlayer(player.getName());
return this;
}
public TargetedDisguise addPlayer(String playername) {
if (!disguiseViewers.contains(playername)) {
disguiseViewers.add(playername);
if (DisguiseAPI.isDisguiseInUse(this)) {
DisguiseUtilities.checkConflicts(this, playername);
DisguiseUtilities.refreshTracker(this, playername);
}
}
return this;
}
public boolean canSee(Player player) {
return canSee(player.getName());
}
public boolean canSee(String playername) {
boolean hasPlayer = disguiseViewers.contains(playername);
if (targetType == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
return !hasPlayer;
}
return hasPlayer;
}
public TargetType getDisguiseTarget() {
return targetType;
}
public List<String> getObservers() {
return Collections.unmodifiableList(disguiseViewers);
}
public TargetedDisguise removePlayer(Player player) {
removePlayer(player.getName());
return this;
}
public TargetedDisguise removePlayer(String playername) {
if (disguiseViewers.contains(playername)) {
disguiseViewers.remove(playername);
if (DisguiseAPI.isDisguiseInUse(this)) {
DisguiseUtilities.checkConflicts(this, playername);
DisguiseUtilities.refreshTracker(this, playername);
}
}
return this;
}
public TargetedDisguise setDisguiseTarget(TargetType newTargetType) {
if (DisguiseUtilities.isDisguiseInUse(this)) {
throw new RuntimeException("Cannot set the disguise target after the entity has been disguised");
}
targetType = newTargetType;
return this;
}
public TargetedDisguise silentlyAddPlayer(String playername) {
if (!disguiseViewers.contains(playername)) {
disguiseViewers.add(playername);
}
return this;
}
public TargetedDisguise silentlyRemovePlayer(String playername) {
if (disguiseViewers.contains(playername)) {
disguiseViewers.remove(playername);
}
return this;
}
}

View File

@@ -0,0 +1,41 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class AgeableWatcher extends LivingWatcher {
public AgeableWatcher(Disguise disguise) {
super(disguise);
}
public int getAge() {
return (Integer) getValue(12, 0);
}
public boolean isAdult() {
return !isBaby();
}
public boolean isBaby() {
return ((Byte) getValue(12, (byte) 0)).intValue() < 0;
}
public void setAdult() {
setBaby(false);
}
public void setAge(int newAge) {
setValue(12, (byte) newAge);
sendData(12);
}
public void setBaby() {
setBaby(true);
}
public void setBaby(boolean isBaby) {
setValue(12, (byte) (isBaby ? -1 : 0));
sendData(12);
}
}

View File

@@ -0,0 +1,62 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class ArmorStandWatcher extends LivingWatcher {
public ArmorStandWatcher(Disguise disguise) {
super(disguise);
}
private boolean get10(int value) {
return ((Byte) getValue(10, 0) & value) != 0;
}
public boolean isNoBasePlate() {
return get10(8);
}
public boolean isNoGravity() {
return get10(2);
}
public boolean isShowArms() {
return get10(4);
}
public boolean isSmall() {
return get10(1);
}
private void set10(int value, boolean isTrue) {
byte b1 = (Byte) getValue(10, (byte) 0);
if (isTrue)
b1 = (byte) (b1 | value);
else {
b1 = (byte) (b1 & value);
}
setValue(10, b1);
sendData(10);
}
public void setNoBasePlate(boolean noBasePlate) {
set10(8, noBasePlate);
sendData(10);
}
public void setNoGravity(boolean noGravity) {
set10(2, noGravity);
sendData(10);
}
public void setShowArms(boolean showArms) {
set10(4, showArms);
sendData(10);
}
public void setSmall(boolean isSmall) {
set10(1, isSmall);
sendData(10);
}
}

View File

@@ -0,0 +1,21 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
public class ArrowWatcher extends FlagWatcher {
public ArrowWatcher(Disguise disguise) {
super(disguise);
}
public boolean isCritical() {
return (Byte) getValue(16, (byte) 0) == 1;
}
public void setCritical(boolean critical) {
setValue(16, (byte) (critical ? 1 : 0));
sendData(16);
}
}

View File

@@ -0,0 +1,20 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class BatWatcher extends LivingWatcher {
public BatWatcher(Disguise disguise) {
super(disguise);
setFlying(true);
}
public boolean isFlying() {
return (Byte) getValue(16, (byte) 1) == 0;
}
public void setFlying(boolean flying) {
setValue(16, (byte) (flying ? 0 : 1));
sendData(16);
}
}

View File

@@ -0,0 +1,20 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class BlazeWatcher extends LivingWatcher {
public BlazeWatcher(Disguise disguise) {
super(disguise);
}
public boolean isBlazing() {
return (Byte) getValue(16, (byte) 0) == 1;
}
public void setBlazing(boolean isBlazing) {
setValue(16, (byte) (isBlazing ? 1 : 0));
sendData(16);
}
}

View File

@@ -0,0 +1,30 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
public class BoatWatcher extends FlagWatcher {
public BoatWatcher(Disguise disguise) {
super(disguise);
}
public int getDamage() {
return (Integer) getValue(19, 40F);
}
public int getHealth() {
return (Integer) getValue(17, 10);
}
public void setDamage(float dmg) {
setValue(19, dmg);
sendData(19);
}
public void setHealth(int health) {
setValue(17, health);
sendData(17);
}
}

View File

@@ -0,0 +1,29 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class CreeperWatcher extends LivingWatcher {
public CreeperWatcher(Disguise disguise) {
super(disguise);
}
public boolean isIgnited() {
return (Byte) getValue(18, (byte) 0) == 1;
}
public boolean isPowered() {
return (Byte) getValue(17, (byte) 0) == 1;
}
public void setIgnited(boolean ignited) {
setValue(18, (byte) (ignited ? 1 : 0));
sendData(18);
}
public void setPowered(boolean powered) {
setValue(17, (byte) (powered ? 1 : 0));
sendData(17);
}
}

View File

@@ -0,0 +1,23 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
import org.bukkit.inventory.ItemStack;
public class DroppedItemWatcher extends FlagWatcher {
public DroppedItemWatcher(Disguise disguise) {
super(disguise);
}
public ItemStack getItemStack() {
return (ItemStack) getValue(10, new ItemStack(1));
}
public void setItemStack(ItemStack item) {
setValue(10, item);
sendData(10);
}
}

View File

@@ -0,0 +1,43 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import org.bukkit.inventory.ItemStack;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class EndermanWatcher extends LivingWatcher {
public EndermanWatcher(Disguise disguise) {
super(disguise);
}
@Override
public ItemStack getItemInHand() {
return new ItemStack((Byte) getValue(16, (byte) 0), 1, ((Byte) getValue(17, (byte) 0)));
}
public boolean isAggressive() {
return (Byte) getValue(18, (byte) 0) == 1;
}
@Deprecated
public boolean isAgressive() {
return isAggressive();
}
public void setAggressive(boolean isAggressive) {
setValue(18, (byte) (isAggressive ? 1 : 0));
sendData(18);
}
@Deprecated
public void setAgressive(boolean isAgressive) {
setAggressive(isAgressive);
}
@Override
public void setItemInHand(ItemStack itemstack) {
setValue(16, (short) (itemstack.getTypeId() & 255));
setValue(17, (byte) (itemstack.getDurability() & 255));
}
}

View File

@@ -0,0 +1,38 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
public class FallingBlockWatcher extends FlagWatcher {
private ItemStack block;
public FallingBlockWatcher(Disguise disguise) {
super(disguise);
}
@Override
public FallingBlockWatcher clone(Disguise disguise) {
FallingBlockWatcher watcher = (FallingBlockWatcher) super.clone(disguise);
watcher.setBlock(getBlock());
return watcher;
}
public ItemStack getBlock() {
return block;
}
public void setBlock(ItemStack block) {
this.block = block;
if (block.getType() == null || block.getType() == Material.AIR) {
block.setType(Material.STONE);
}
if (DisguiseAPI.isDisguiseInUse(getDisguise()) && getDisguise().getWatcher() == this) {
DisguiseUtilities.refreshTrackers(getDisguise());
}
}
}

View File

@@ -0,0 +1,20 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class GhastWatcher extends LivingWatcher {
public GhastWatcher(Disguise disguise) {
super(disguise);
}
public boolean isAggressive() {
return (Byte) getValue(16, (byte) 0) == 1;
}
public void setAggressive(boolean isAggressive) {
setValue(16, (byte) (isAggressive ? 1 : 0));
sendData(16);
}
}

View File

@@ -0,0 +1,20 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class GuardianWatcher extends LivingWatcher {
public GuardianWatcher(Disguise disguise) {
super(disguise);
}
public boolean isBeam() {
return (Integer) getValue(17, 0) == 1;
}
public void setBeam(boolean isBeaming) {
setValue(17, isBeaming ? 1 : 0);
sendData(17);
}
}

View File

@@ -0,0 +1,157 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import java.util.Random;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import org.bukkit.Material;
import org.bukkit.entity.Horse.Color;
import org.bukkit.entity.Horse.Style;
import org.bukkit.inventory.ItemStack;
public class HorseWatcher extends AgeableWatcher {
public HorseWatcher(Disguise disguise) {
super(disguise);
setColor(Color.values()[new Random().nextInt(Color.values().length)]);
}
public Color getColor() {
return Color.values()[((Integer) getValue(20, 0) & 0xFF)];
}
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;
}
return null;
}
@Deprecated
public int getHorseArmorAsInt() {
return (Integer) getValue(22, 0);
}
public String getOwnerName() {
return (String) getValue(21, null);
}
public Style getStyle() {
return Style.values()[((Integer) getValue(20, 0) >>> 8)];
}
public boolean hasChest() {
return isTrue(8);
}
public boolean isBreedable() {
return isTrue(16);
}
public boolean isGrazing() {
return isTrue(32);
}
public boolean isMouthOpen() {
return isTrue(128);
}
public boolean isRearing() {
return isTrue(64);
}
public boolean isSaddled() {
return isTrue(4);
}
public boolean isTamed() {
return isTrue(2);
}
private boolean isTrue(int i) {
return ((Integer) getValue(16, (byte) 0) & i) != 0;
}
public void setCanBreed(boolean breed) {
setFlag(16, breed);
}
public void setCarryingChest(boolean chest) {
setFlag(8, chest);
}
public void setColor(Color color) {
setValue(20, color.ordinal() & 0xFF | getStyle().ordinal() << 8);
sendData(20);
}
private void setFlag(int i, boolean flag) {
int j = (Integer) getValue(16, 0);
if (flag) {
setValue(16, j | i);
} else {
setValue(16, j & ~i);
}
sendData(16);
}
public void setGrazing(boolean grazing) {
setFlag(32, grazing);
}
@Deprecated
public void setHorseArmor(int armor) {
setValue(22, armor % 4);
sendData(22);
}
public void setHorseArmor(ItemStack item) {
int value = 0;
if (item != null) {
Material mat = item.getType();
if (mat.name().equals("IRON_BARDING")) {
value = 1;
} else if (mat.name().equals("GOLD_BARDING")) {
value = 2;
} else if (mat.name().equals("DIAMOND_BARDING")) {
value = 3;
}
}
setHorseArmor(value);
}
public void setMouthOpen(boolean mouthOpen) {
setFlag(128, mouthOpen);
}
public void setOwnerName(String name) {
setValue(21, name);
sendData(21);
}
public void setRearing(boolean rear) {
setFlag(64, rear);
}
public void setSaddled(boolean saddled) {
setFlag(4, saddled);
}
public void setStyle(Style style) {
setValue(20, getColor().ordinal() & 0xFF | style.ordinal() << 8);
sendData(20);
}
public void setTamed(boolean tamed) {
setFlag(2, tamed);
}
}

View File

@@ -0,0 +1,37 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
import org.bukkit.inventory.ItemStack;
public class ItemFrameWatcher extends FlagWatcher {
public ItemFrameWatcher(Disguise disguise) {
super(disguise);
}
public ItemStack getItem() {
if (getValue(2, null) == null)
return new ItemStack(0);
return (ItemStack) getValue(8, null);
}
public int getRotation() {
return (Integer) getValue(9, 0);
}
public void setItem(ItemStack newItem) {
if (newItem == null)
newItem = new ItemStack(0);
newItem = newItem.clone();
newItem.setAmount(1);
setValue(8, newItem);
sendData(8);
}
public void setRotation(int rotation) {
setValue(9, (byte) (rotation % 4));
sendData(9);
}
}

View File

@@ -0,0 +1,169 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.ReflectionManager;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
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);
for (Object obj : list) {
if (obj != null) {
for (Method field : obj.getClass().getMethods()) {
if (field.getReturnType() == int.class) {
if ((Integer) field.invoke(obj) > 10000) {
potionNo = field;
break;
}
}
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private double maxHealth;
private boolean maxHealthSet;
private HashSet<Integer> potionEffects = new HashSet<Integer>();
public LivingWatcher(Disguise disguise) {
super(disguise);
}
public void addPotionEffect(PotionEffectType potionEffect) {
if (!hasPotionEffect(potionEffect)) {
removePotionEffect(potionEffect);
potionEffects.add(potionEffect.getId());
sendPotionEffects();
}
}
@Override
public LivingWatcher clone(Disguise disguise) {
LivingWatcher clone = (LivingWatcher) super.clone(disguise);
clone.potionEffects = (HashSet<Integer>) potionEffects.clone();
clone.maxHealth = maxHealth;
clone.maxHealthSet = maxHealthSet;
return clone;
}
public float getHealth() {
return (Float) getValue(6, 0F);
}
public double getMaxHealth() {
return maxHealth;
}
public boolean getPotionParticlesRemoved() {
return (Byte) getValue(8, (byte) 0) == 1;
}
private int getPotions() {
int m = 3694022;
if (potionEffects.isEmpty()) {
return m;
}
float f1 = 0.0F;
float f2 = 0.0F;
float f3 = 0.0F;
float f4 = 0.0F;
try {
for (int localMobEffect : potionEffects) {
int n = (Integer) potionNo.invoke(list[localMobEffect]);
f1 += (n >> 16 & 0xFF) / 255.0F;
f2 += (n >> 8 & 0xFF) / 255.0F;
f3 += (n >> 0 & 0xFF) / 255.0F;
f4 += 1.0F;
}
} catch (Exception ex) {
ex.printStackTrace();
}
f1 = f1 / f4 * 255.0F;
f2 = f2 / f4 * 255.0F;
f3 = f3 / f4 * 255.0F;
return (int) f1 << 16 | (int) f2 << 8 | (int) f3;
}
public boolean hasPotionEffect(PotionEffectType type) {
return potionEffects.contains(type.getId());
}
public boolean isMaxHealthSet() {
return maxHealthSet;
}
public void removePotionEffect(PotionEffectType type) {
if (potionEffects.contains(type.getId())) {
potionEffects.remove(type.getId());
sendPotionEffects();
}
}
public void removePotionParticles(boolean particles) {
setValue(8, (byte) (particles ? 1 : 0));
sendData(8);
}
private void sendPotionEffects() {
setValue(7, getPotions());
sendData(7);
}
public void setHealth(float health) {
setValue(6, health);
sendData(6);
}
public void setMaxHealth(double newHealth) {
this.maxHealth = newHealth;
this.maxHealthSet = true;
if (DisguiseAPI.isDisguiseInUse(getDisguise()) && getDisguise().getWatcher() == this) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.UPDATE_ATTRIBUTES);
List<WrappedAttribute> attributes = new ArrayList<WrappedAttribute>();
Builder builder;
builder = WrappedAttribute.newBuilder();
builder.attributeKey("generic.maxHealth");
builder.baseValue(getMaxHealth());
builder.packet(packet);
attributes.add(builder.build());
Entity entity = getDisguise().getEntity();
packet.getIntegers().write(0, entity.getEntityId());
packet.getAttributeCollectionModifier().write(0, attributes);
for (Player player : DisguiseUtilities.getPerverts(getDisguise())) {
try {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, false);
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}

View File

@@ -0,0 +1,64 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import org.bukkit.inventory.ItemStack;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
public class MinecartWatcher extends FlagWatcher {
public MinecartWatcher(Disguise disguise) {
super(disguise);
}
public ItemStack getBlockInCart() {
int id = (Integer) getValue(20, 0) & 0xffff;
int data = (Integer) getValue(20, 0) >> 16;
return new ItemStack(id, 1, (short) data);
}
public int getBlockOffset() {
return (Integer) getValue(21, 0);
}
@Deprecated
public int getBlockOffSet() {
return getBlockOffset();
}
public float getDamage() {
return (Float) getValue(19, 0F);
}
public boolean getViewBlockInCart() {
return ((Byte) getValue(22, (byte) 0)) == (byte) 1;
}
public void setBlockInCart(ItemStack item) {
int id = item.getTypeId();
int data = item.getDurability();
setValue(20, (int) (id & 0xffff | data << 16));
setValue(22, (byte) 1);
sendData(20, 22);
}
public void setBlockOffset(int i) {
setValue(21, i);
sendData(21);
}
@Deprecated
public void setBlockOffSet(int i) {
setBlockOffset(i);
}
public void setDamage(float damage) {
setValue(19, damage);
sendData(19);
}
public void setViewBlockInCart(boolean viewBlock) {
setValue(22, (byte) (viewBlock ? 1 : 0));
sendData(22);
}
}

View File

@@ -0,0 +1,22 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Ocelot.Type;
public class OcelotWatcher extends TameableWatcher {
public OcelotWatcher(Disguise disguise) {
super(disguise);
}
public Type getType() {
return Ocelot.Type.getType((Byte) getValue(18, (byte) 0));
}
public void setType(Type newType) {
setValue(18, (byte) newType.getId());
sendData(18);
}
}

View File

@@ -0,0 +1,33 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import org.bukkit.Art;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
public class PaintingWatcher extends FlagWatcher {
private Art painting;
public PaintingWatcher(Disguise disguise) {
super(disguise);
}
@Override
public PaintingWatcher clone(Disguise disguise) {
PaintingWatcher watcher = (PaintingWatcher) super.clone(disguise);
watcher.setArt(getArt());
return watcher;
}
public Art getArt() {
return painting;
}
public void setArt(Art newPainting) {
this.painting = newPainting;
if (getDisguise().getEntity() != null && getDisguise().getWatcher() == this) {
DisguiseUtilities.refreshTrackers(getDisguise());
}
}
}

View File

@@ -0,0 +1,19 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class PigWatcher extends AgeableWatcher {
public PigWatcher(Disguise disguise) {
super(disguise);
}
public boolean isSaddled() {
return (Byte) getValue(16, (byte) 0) == 1;
}
public void setSaddled(boolean isSaddled) {
setValue(16, (byte) (isSaddled ? 1 : 0));
sendData(16);
}
}

View File

@@ -0,0 +1,135 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.reflect.StructureModifier;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.PlayerDisguise;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
import me.libraryaddict.disguise.utilities.ReflectionManager.LibVersion;
public class PlayerWatcher extends LivingWatcher {
private boolean isInBed;
private BlockFace sleepingDirection;
public PlayerWatcher(Disguise disguise) {
super(disguise);
}
public PlayerWatcher clone(Disguise disguise) {
PlayerWatcher watcher = (PlayerWatcher) super.clone(disguise);
watcher.isInBed = isInBed;
return watcher;
}
public int getArrowsSticking() {
return (Byte) getValue(9, (byte) 0);
}
public BlockFace getSleepingDirection() {
if (sleepingDirection == null) {
if (this.getDisguise().getEntity() != null && isSleeping()) {
this.sleepingDirection = BlockFace.values()[Math
.round(this.getDisguise().getEntity().getLocation().getYaw() / 90F) & 0x3];
} else {
return BlockFace.EAST;
}
}
return sleepingDirection;
}
private boolean getValue16(int i) {
return ((Byte) getValue(16, (byte) 0) & 1 << i) != 0;
}
public boolean isHideCape() {
return getValue16(1);
}
public boolean isSleeping() {
return isInBed;
}
public void setArrowsSticking(int arrowsNo) {
setValue(9, (byte) arrowsNo);
sendData(9);
}
public void setHideCape(boolean hideCape) {
setValue16(1, hideCape);
sendData(16);
}
public void setSkin(String playerName) {
((PlayerDisguise) getDisguise()).setSkin(playerName);
}
public void setSleeping(BlockFace sleepingDirection) {
setSleeping(true, sleepingDirection);
}
public void setSleeping(boolean sleep) {
setSleeping(sleep, null);
}
/**
* If no BlockFace is supplied. It grabs it from the entities facing direction if applicable.
*/
public void setSleeping(boolean sleeping, BlockFace sleepingDirection) {
if (sleepingDirection != null) {
this.sleepingDirection = BlockFace.values()[sleepingDirection.ordinal() % 4];
}
if (sleeping != isSleeping()) {
isInBed = sleeping;
if (DisguiseConfig.isBedPacketsEnabled() && DisguiseUtilities.isDisguiseInUse(getDisguise())) {
try {
if (isSleeping()) {
for (Player player : DisguiseUtilities.getPerverts(getDisguise())) {
PacketContainer[] packets = DisguiseUtilities.getBedPackets(player, this.getDisguise().getEntity()
.getLocation(), player.getLocation(), (PlayerDisguise) this.getDisguise());
if (getDisguise().getEntity() == player) {
for (PacketContainer packet : packets) {
packet = packet.shallowClone();
packet.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId());
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
}
} else {
for (PacketContainer packet : packets) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
}
}
}
} else {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ANIMATION);
StructureModifier<Integer> mods = packet.getIntegers();
mods.write(0, getDisguise().getEntity().getEntityId());
mods.write(1, 3);
for (Player player : DisguiseUtilities.getPerverts(getDisguise())) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
private void setValue16(int i, boolean flag) {
byte b0 = (Byte) getValue(16, (byte) 0);
if (flag) {
setValue(16, Byte.valueOf((byte) (b0 | 1 << i)));
} else {
setValue(16, Byte.valueOf((byte) (b0 & (1 << i ^ 0xFFFFFFFF))));
}
}
}

View File

@@ -0,0 +1,24 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import java.util.Random;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.RabbitType;
public class RabbitWatcher extends AgeableWatcher {
public RabbitWatcher(Disguise disguise) {
super(disguise);
setType(RabbitType.values()[new Random().nextInt(RabbitType.values().length)]);
}
public RabbitType getType() {
return RabbitType.getType((Integer) getValue(18, (int) 0));
}
public void setType(RabbitType type) {
setValue(18, (byte) type.getTypeId());
sendData(18);
}
}

View File

@@ -0,0 +1,36 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.AnimalColor;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class SheepWatcher extends AgeableWatcher {
public SheepWatcher(Disguise disguise) {
super(disguise);
setValue(16, (byte) 0);
}
public AnimalColor getColor() {
return AnimalColor.getColor((Byte) getValue(16, (byte) 0) & 15);
}
public boolean isSheared() {
return ((Byte) getValue(16, (byte) 0) & 16) != 0;
}
public void setColor(AnimalColor color) {
byte b0 = (Byte) getValue(16, (byte) 0);
setValue(16, (byte) (b0 & 240 | color.getId() & 15));
sendData(16);
}
public void setSheared(boolean flag) {
byte b0 = (Byte) getValue(16, (byte) 0);
if (flag) {
setValue(16, (byte) (b0 | 16));
} else {
setValue(16, (byte) (b0 & -17));
}
sendData(16);
}
}

View File

@@ -0,0 +1,26 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import java.util.Random;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class SlimeWatcher extends LivingWatcher {
public SlimeWatcher(Disguise disguise) {
super(disguise);
setSize(new Random().nextInt(4) + 1);
}
public int getSize() {
return (Byte) getValue(16, (byte) 1);
}
public void setSize(int size) {
if (size <= 0 || size >= 128) {
size = 1;
}
setValue(16, (byte) size);
sendData(16);
}
}

View File

@@ -0,0 +1,32 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
import me.libraryaddict.disguise.utilities.DisguiseUtilities;
public class SplashPotionWatcher extends FlagWatcher {
private int potionId;
public SplashPotionWatcher(Disguise disguise) {
super(disguise);
}
@Override
public SplashPotionWatcher clone(Disguise disguise) {
SplashPotionWatcher watcher = (SplashPotionWatcher) super.clone(disguise);
watcher.setPotionId(getPotionId());
return watcher;
}
public int getPotionId() {
return potionId;
}
public void setPotionId(int newPotionId) {
this.potionId = newPotionId;
if (getDisguise().getEntity() != null && getDisguise().getWatcher() == this) {
DisguiseUtilities.refreshTrackers(getDisguise());
}
}
}

View File

@@ -0,0 +1,62 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class TameableWatcher extends AgeableWatcher {
public TameableWatcher(Disguise disguise) {
super(disguise);
}
@Override
public float getHealth() {
return (Float) getValue(18, 8F);
}
public String getOwner() {
return (String) getValue(17, null);
}
public boolean isSitting() {
return isTrue(1);
}
public boolean isTamed() {
return isTrue(4);
}
protected boolean isTrue(int no) {
return ((Byte) getValue(16, (byte) 0) & no) != 0;
}
protected void setFlag(int no, boolean flag) {
byte b0 = (Byte) getValue(16, (byte) 0);
if (flag) {
setValue(16, (byte) (b0 | no));
} else {
setValue(16, (byte) (b0 & -(no + 1)));
}
sendData(16);
}
@Override
public void setHealth(float newHealth) {
setValue(18, newHealth);
setValue(6, newHealth);
sendData(6, 18);
}
public void setOwner(String owner) {
setValue(17, owner);
sendData(17);
}
public void setSitting(boolean sitting) {
setFlag(1, sitting);
}
public void setTamed(boolean tamed) {
setFlag(4, tamed);
}
}

View File

@@ -0,0 +1,28 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import java.util.Random;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import org.bukkit.entity.Villager.Profession;
public class VillagerWatcher extends AgeableWatcher {
public VillagerWatcher(Disguise disguise) {
super(disguise);
setProfession(Profession.values()[new Random().nextInt(Profession.values().length)]);
}
public Profession getProfession() {
return Profession.values()[(Integer) getValue(16, 0)];
}
public void setProfession(int professionId){
setValue(16, professionId % 6);
sendData(16);
}
public void setProfession(Profession newProfession) {
setProfession(newProfession.getId());
}
}

View File

@@ -0,0 +1,21 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
public class WitherSkullWatcher extends FlagWatcher {
public WitherSkullWatcher(Disguise disguise) {
super(disguise);
}
public boolean isBlue() {
return (Byte) getValue(10, (byte) 0) == 1;
}
public void setBlue(boolean blue) {
setValue(10, (byte) (blue ? 1 : 0));
sendData(10);
}
}

View File

@@ -0,0 +1,47 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import java.security.InvalidParameterException;
import org.bukkit.ChatColor;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class WitherWatcher extends LivingWatcher {
public WitherWatcher(Disguise disguise) {
super(disguise);
}
public int getInvul() {
return getInvulnerability();
}
public int getInvulnerability() {
return (Integer) getValue(20, 0);
}
public int[] getTargets() {
return new int[] { (Integer) getValue(17, 0), (Integer) getValue(18, 0), (Integer) getValue(19, 0) };
}
public void setInvul(int invulnerability) {
setInvulnerability(invulnerability);
}
public void setInvulnerability(int invulnerability) {
setValue(20, invulnerability);
sendData(20);
}
public void setTargets(int... targets) {
if (targets.length != 3) {
throw new InvalidParameterException(ChatColor.RED + "Expected 3 numbers for wither setTargets. Received "
+ targets.length);
}
setValue(17, targets[0]);
setValue(18, targets[1]);
setValue(19, targets[2]);
sendData(17, 18, 19);
}
}

View File

@@ -0,0 +1,34 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.AnimalColor;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class WolfWatcher extends TameableWatcher {
public WolfWatcher(Disguise disguise) {
super(disguise);
}
public AnimalColor getCollarColor() {
return AnimalColor.getColor((Byte) getValue(20, (byte) 14));
}
public boolean isAngry() {
return isTrue(2);
}
public void setAngry(boolean angry) {
setFlag(2, angry);
}
public void setCollarColor(AnimalColor newColor) {
if (!isTamed()) {
setTamed(true);
}
if (newColor != getCollarColor()) {
setValue(20, (byte) newColor.getId());
sendData(20);
}
}
}

View File

@@ -0,0 +1,50 @@
package me.libraryaddict.disguise.disguisetypes.watchers;
import me.libraryaddict.disguise.disguisetypes.Disguise;
public class ZombieWatcher extends LivingWatcher {
public ZombieWatcher(Disguise disguise) {
super(disguise);
}
public boolean isAdult() {
return !isBaby();
}
public boolean isBaby() {
return (Byte) getValue(12, (byte) 0) == 1;
}
public boolean isShaking() {
return (Byte) getValue(14, (byte) 0) == 1;
}
public boolean isVillager() {
return (Byte) getValue(13, (byte) 0) == 1;
}
public void setAdult() {
setBaby(false);
}
public void setBaby() {
setBaby(true);
}
public void setBaby(boolean baby) {
setValue(12, (byte) (baby ? 1 : 0));
sendData(12);
}
public void setShaking(boolean shaking) {
setValue(14, (byte) (shaking ? 1 : 0));
sendData(14);
}
public void setVillager(boolean villager) {
setValue(13, (byte) (villager ? 1 : 0));
sendData(13);
}
}

View File

@@ -0,0 +1,47 @@
package me.libraryaddict.disguise.events;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
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() {
return handlers;
}
private Disguise disguise;
private Entity disguised;
private boolean isCancelled;
public DisguiseEvent(Entity entity, Disguise disguise) {
this.disguised = entity;
this.disguise = disguise;
}
public Disguise getDisguise() {
return disguise;
}
public Entity getEntity() {
return disguised;
}
public HandlerList getHandlers() {
return handlers;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancelled) {
isCancelled = cancelled;
}
}

View File

@@ -0,0 +1,47 @@
package me.libraryaddict.disguise.events;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
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() {
return handlers;
}
private Disguise disguise;
private Entity disguised;
private boolean isCancelled;
public UndisguiseEvent(Entity entity, Disguise disguise) {
this.disguised = entity;
this.disguise = disguise;
}
public Disguise getDisguise() {
return disguise;
}
public Entity getEntity() {
return disguised;
}
public HandlerList getHandlers() {
return handlers;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public void setCancelled(boolean cancelled) {
isCancelled = cancelled;
}
}

View File

@@ -0,0 +1,736 @@
package me.libraryaddict.disguise.utilities;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map.Entry;
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.RabbitType;
import me.libraryaddict.disguise.utilities.ReflectionManager.LibVersion;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Monster;
import org.bukkit.inventory.ItemStack;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.potion.PotionEffectType;
public abstract class BaseDisguiseCommand implements CommandExecutor {
public class DisguiseParseException extends Exception {
private static final long serialVersionUID = 1276971370793124510L;
public DisguiseParseException() {
super();
}
public DisguiseParseException(String string) {
super(string);
}
}
protected ArrayList<String> getAllowedDisguises(HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> hashMap) {
ArrayList<String> allowedDisguises = new ArrayList<String>();
for (DisguiseType type : hashMap.keySet()) {
allowedDisguises.add(type.toReadable().replace(" ", "_"));
}
Collections.sort(allowedDisguises, String.CASE_INSENSITIVE_ORDER);
return allowedDisguises;
}
protected HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> getPermissions(CommandSender sender) {
return getPermissions(sender, "libsdisguises." + getClass().getSimpleName().replace("Command", "").toLowerCase() + ".");
}
protected HashMap<String, Boolean> getDisguisePermission(CommandSender sender, DisguiseType type) {
switch (type) {
case PLAYER:
case FALLING_BLOCK:
case PAINTING:
case SPLASH_POTION:
case FISHING_HOOK:
case DROPPED_ITEM:
HashMap<String, Boolean> returns = new HashMap<String, Boolean>();
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<String, Boolean>();
}
}
protected Method[] getDisguiseWatcherMethods(Class<? extends FlagWatcher> watcherClass) {
Method[] methods = watcherClass.getMethods();
methods = Arrays.copyOf(methods, methods.length + 4);
int i = 4;
for (String methodName : new String[] { "setViewSelfDisguise", "setHideHeldItemFromSelf", "setHideArmorFromSelf",
"setHearSelfDisguise" }) {
try {
methods[methods.length - i--] = Disguise.class.getMethod(methodName, boolean.class);
} catch (Exception ex) {
ex.printStackTrace();
}
}
return methods;
}
/**
* Get perms for the node. Returns a hashmap of allowed disguisetypes and their options
*/
protected HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> getPermissions(CommandSender sender,
String permissionNode) {
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> singleDisguises = new HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>>();
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> rangeDisguises = new HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>>();
HashMap<String, Boolean> perms = new HashMap<String, Boolean>();
for (PermissionAttachmentInfo permission : sender.getEffectivePermissions()) {
String perm = permission.getPermission().toLowerCase();
if (perm.startsWith(permissionNode) && (!perms.containsKey(perm) || !permission.getValue())) {
perms.put(perm, permission.getValue());
}
}
if (!perms.containsKey(permissionNode + "*") && sender.hasPermission(permissionNode + "*")) {
perms.put(permissionNode + "*", true);
}
if (!perms.containsKey(permissionNode + "*.*") && sender.hasPermission(permissionNode + "*.*")) {
perms.put(permissionNode + "*.*", true);
}
for (String perm : perms.keySet()) {
if (perms.get(perm)) {
perm = perm.substring(permissionNode.length());
String disguiseType = perm.split("\\.")[0];
DisguiseType dType = null;
for (DisguiseType t : DisguiseType.values()) {
if (t.name().replace("_", "").equalsIgnoreCase(disguiseType.replace("_", ""))) {
dType = t;
break;
}
}
if (dType != null) {
HashMap<ArrayList<String>, Boolean> list;
if (singleDisguises.containsKey(dType)) {
list = singleDisguises.get(dType);
} else {
list = new HashMap<ArrayList<String>, Boolean>();
singleDisguises.put(dType, list);
}
HashMap<ArrayList<String>, Boolean> map1 = getOptions(perm);
list.put(map1.keySet().iterator().next(), map1.values().iterator().next());
} else {
for (DisguiseType type : DisguiseType.values()) {
HashMap<ArrayList<String>, Boolean> options = null;
Class entityClass = type.getEntityClass();
if (disguiseType.equals("mob")) {
if (type.isMob()) {
options = getOptions(perm);
}
} else if (disguiseType.equals("animal") || disguiseType.equals("animals")) {
if (Animals.class.isAssignableFrom(entityClass)) {
options = getOptions(perm);
}
} else if (disguiseType.equals("monster") || disguiseType.equals("monsters")) {
if (Monster.class.isAssignableFrom(entityClass)) {
options = getOptions(perm);
}
} else if (disguiseType.equals("misc")) {
if (type.isMisc()) {
options = getOptions(perm);
}
} else if (disguiseType.equals("ageable")) {
if (Ageable.class.isAssignableFrom(entityClass)) {
options = getOptions(perm);
}
} else if (disguiseType.equals("*")) {
options = getOptions(perm);
}
if (options != null) {
HashMap<ArrayList<String>, Boolean> list;
if (rangeDisguises.containsKey(type)) {
list = rangeDisguises.get(type);
} else {
list = new HashMap<ArrayList<String>, Boolean>();
rangeDisguises.put(type, list);
}
HashMap<ArrayList<String>, Boolean> map1 = getOptions(perm);
list.put(map1.keySet().iterator().next(), map1.values().iterator().next());
}
}
}
}
}
for (String perm : perms.keySet()) {
if (!perms.get(perm)) {
perm = perm.substring(permissionNode.length());
String disguiseType = perm.split("\\.")[0];
DisguiseType dType = null;
for (DisguiseType t : DisguiseType.values()) {
if (t.name().replace("_", "").equalsIgnoreCase(disguiseType.replace("_", ""))) {
dType = t;
break;
}
}
if (dType != null) {
singleDisguises.remove(dType);
rangeDisguises.remove(dType);
} else {
for (DisguiseType type : DisguiseType.values()) {
boolean foundHim = false;
Class entityClass = type.getEntityClass();
if (disguiseType.equals("mob")) {
if (type.isMob()) {
foundHim = true;
}
} else if (disguiseType.equals("animal") || disguiseType.equals("animals")) {
if (Animals.class.isAssignableFrom(entityClass)) {
foundHim = true;
}
} else if (disguiseType.equals("monster") || disguiseType.equals("monsters")) {
if (Monster.class.isAssignableFrom(entityClass)) {
foundHim = true;
}
} else if (disguiseType.equals("misc")) {
if (type.isMisc()) {
foundHim = true;
}
} else if (disguiseType.equals("ageable")) {
if (Ageable.class.isAssignableFrom(entityClass)) {
foundHim = true;
}
} else if (disguiseType.equals("*")) {
foundHim = true;
}
if (foundHim) {
rangeDisguises.remove(type);
}
}
}
}
}
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map = new HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>>();
for (DisguiseType type : DisguiseType.values()) {
HashMap<ArrayList<String>, Boolean> temp = new HashMap<ArrayList<String>, Boolean>();
if (singleDisguises.containsKey(type)) {
temp.putAll(singleDisguises.get(type));
}
if (rangeDisguises.containsKey(type)) {
temp.putAll(rangeDisguises.get(type));
}
if (!temp.isEmpty()) {
map.put(type, temp);
}
}
return map;
}
private HashMap<ArrayList<String>, Boolean> getOptions(String perm) {
ArrayList<String> list = new ArrayList<String>();
boolean isRemove = true;
String[] split = perm.split("\\.");
for (int i = 1; i < split.length; i++) {
String option = split[i];
boolean value = option.startsWith("-");
if (value) {
option = option.substring(1);
isRemove = false;
}
if (option.equals("baby"))
option = "setbaby";
list.add(option);
}
HashMap<ArrayList<String>, Boolean> options = new HashMap<ArrayList<String>, Boolean>();
options.put(list, isRemove);
return options;
}
protected boolean isDouble(String string) {
try {
Float.parseFloat(string);
return true;
} catch (Exception ex) {
return false;
}
}
protected boolean isNumeric(String string) {
try {
Integer.parseInt(string);
return true;
} catch (Exception ex) {
return false;
}
}
/**
* 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.
*/
protected Disguise parseDisguise(CommandSender sender, String[] args,
HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map) throws DisguiseParseException,
IllegalAccessException, InvocationTargetException {
if (map.isEmpty()) {
throw new DisguiseParseException(ChatColor.RED + "You are forbidden to use this command.");
}
if (args.length == 0) {
sendCommandUsage(sender, map);
throw new DisguiseParseException();
}
// How many args to skip due to the disugise being constructed
// Time to start constructing the disguise.
// We will need to check between all 3 kinds of disguises
int toSkip = 1;
ArrayList<String> usedOptions = new ArrayList<String>();
Disguise disguise = null;
HashMap<ArrayList<String>, Boolean> optionPermissions;
if (args[0].startsWith("@")) {
if (sender.hasPermission("libsdisguises.disguise.disguiseclone")) {
disguise = DisguiseUtilities.getClonedDisguise(args[0].toLowerCase());
if (disguise == null) {
throw new DisguiseParseException(ChatColor.RED + "Cannot find a disguise under the reference " + args[0]);
}
} else {
throw new DisguiseParseException(ChatColor.RED + "You do not have perimssion to use disguise references!");
}
optionPermissions = (map.containsKey(disguise.getType()) ? map.get(disguise.getType())
: new HashMap<ArrayList<String>, Boolean>());
} else {
DisguiseType disguiseType = null;
if (args[0].equalsIgnoreCase("p")) {
disguiseType = DisguiseType.PLAYER;
} else {
for (DisguiseType type : DisguiseType.values()) {
if (args[0].equalsIgnoreCase(type.name()) || args[0].equalsIgnoreCase(type.name().replace("_", ""))) {
disguiseType = type;
break;
}
}
}
if (disguiseType == null) {
throw new DisguiseParseException(ChatColor.RED + "Error! The disguise " + ChatColor.GREEN + args[0]
+ ChatColor.RED + " doesn't exist!");
}
if (disguiseType.getEntityType() == null) {
throw new DisguiseParseException(ChatColor.RED + "Error! This version of minecraft does not have that disguise!");
}
if (!map.containsKey(disguiseType)) {
throw new DisguiseParseException(ChatColor.RED + "You are forbidden to use this disguise.");
}
optionPermissions = map.get(disguiseType);
HashMap<String, Boolean> disguiseOptions = this.getDisguisePermission(sender, disguiseType);
if (disguiseType.isPlayer()) {// If he is doing a player disguise
if (args.length == 1) {
// He needs to give the player name
throw new DisguiseParseException(ChatColor.RED + "Error! You need to give a player name!");
} else {
if (!disguiseOptions.isEmpty()
&& (!disguiseOptions.containsKey(args[1].toLowerCase()) || !disguiseOptions
.get(args[1].toLowerCase()))) {
throw new DisguiseParseException(ChatColor.RED + "Error! You don't have permission to use that name!");
}
// Construct the player disguise
disguise = new PlayerDisguise(ChatColor.translateAlternateColorCodes('&', args[1]));
toSkip++;
}
} else {
if (disguiseType.isMob()) { // Its a mob, use the mob constructor
boolean adult = true;
if (args.length > 1) {
if (args[1].equalsIgnoreCase("baby") || args[1].equalsIgnoreCase("adult")) {
usedOptions.add("setbaby");
doCheck(optionPermissions, usedOptions);
adult = args[1].equalsIgnoreCase("adult");
toSkip++;
}
}
disguise = new MobDisguise(disguiseType, adult);
} else if (disguiseType.isMisc()) {
// Its a misc, we are going to use the MiscDisguise constructor.
int miscId = -1;
int miscData = -1;
String secondArg = null;
if (args.length > 1) {
// They have defined more arguements!
// If the first arg is a number
if (args[1].contains(":")) {
String[] split = args[1].split(":");
if (isNumeric(split[1])) {
secondArg = split[1];
}
args[1] = split[0];
}
if (isNumeric(args[1])) {
miscId = Integer.parseInt(args[1]);
} else {
if (disguiseType == DisguiseType.FALLING_BLOCK || disguiseType == DisguiseType.DROPPED_ITEM) {
for (Material mat : Material.values()) {
if (mat.name().replace("_", "").equalsIgnoreCase(args[1].replace("_", ""))) {
miscId = mat.getId();
break;
}
}
}
}
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] + "!");
}
toSkip++;
// If they also defined a data value
if (args.length > 2 && secondArg == null && isNumeric(args[2])) {
secondArg = args[2];
toSkip++;
}
if (secondArg != null) {
if (disguiseType != DisguiseType.FALLING_BLOCK && disguiseType != DisguiseType.DROPPED_ITEM) {
throw new DisguiseParseException(ChatColor.RED + "Error! Only the disguises "
+ DisguiseType.FALLING_BLOCK.toReadable() + " and "
+ DisguiseType.DROPPED_ITEM.toReadable() + " uses a second number!");
}
miscData = Integer.parseInt(secondArg);
}
}
}
if (!disguiseOptions.isEmpty() && miscId != -1) {
String toCheck = "" + miscId;
if (miscData == 0 || miscData == -1) {
if (!disguiseOptions.containsKey(toCheck) || !disguiseOptions.get(toCheck)) {
toCheck += ":0";
}
} else {
toCheck += ":" + miscData;
}
if (!disguiseOptions.containsKey(toCheck) || !disguiseOptions.get(toCheck)) {
throw new DisguiseParseException(ChatColor.RED
+ "Error! You do not have permission to use the parameter " + toCheck + " on the "
+ disguiseType.toReadable() + " disguise!");
}
}
if (miscId != -1) {
if (disguiseType == DisguiseType.FALLING_BLOCK) {
usedOptions.add("setblock");
doCheck(optionPermissions, usedOptions);
} else if (disguiseType == DisguiseType.PAINTING) {
usedOptions.add("setpainting");
doCheck(optionPermissions, usedOptions);
} else if (disguiseType == DisguiseType.SPLASH_POTION) {
usedOptions.add("setpotionid");
doCheck(optionPermissions, usedOptions);
}
}
// Construct the disguise
disguise = new MiscDisguise(disguiseType, miscId, miscData);
}
}
}
// Copy strings to their new range
String[] newArgs = new String[args.length - toSkip];
System.arraycopy(args, toSkip, newArgs, 0, args.length - toSkip);
args = newArgs;
Method[] methods = this.getDisguiseWatcherMethods(disguise.getWatcher().getClass());
for (int i = 0; i < args.length; i += 2) {
String methodName = args[i];
String valueString = (args.length - 1 == i ? null : args[i + 1]);
Method methodToUse = null;
Object value = null;
DisguiseParseException storedEx = null;
int c = 0;
while (c < methods.length) {
try {
Entry<Method, Integer> entry = getMethod(methods, methodName, c);
if (entry == null) {
break;
}
methodToUse = entry.getKey();
c = entry.getValue();
methodName = methodToUse.getName();
Class<?>[] types = methodToUse.getParameterTypes();
Class param = types[0];
if (valueString != null) {
if (int.class == param) {
// Parse to integer
if (isNumeric(valueString)) {
value = (int) Integer.parseInt(valueString);
} else {
throw parseToException("number", valueString, methodName);
}
} else if (float.class == param || double.class == param) {
// Parse to number
if (isDouble(valueString)) {
float obj = Float.parseFloat(valueString);
if (param == float.class) {
value = (float) obj;
} else if (param == double.class) {
value = (double) obj;
}
} else {
throw parseToException("number.0", valueString, methodName);
}
} else if (param == String.class) {
// Parse to string
value = ChatColor.translateAlternateColorCodes('&', valueString);
} else if (param == AnimalColor.class) {
// Parse to animal color
try {
value = AnimalColor.valueOf(valueString.toUpperCase());
} catch (Exception ex) {
throw parseToException("animal color", valueString, methodName);
}
} else if (param == ItemStack.class) {
// Parse to itemstack
try {
value = parseToItemstack(valueString);
} catch (Exception ex) {
throw new DisguiseParseException(String.format(ex.getMessage(), methodName));
}
} else if (param == ItemStack[].class) {
// Parse to itemstack array
ItemStack[] items = new ItemStack[4];
String[] split = valueString.split(",");
if (split.length == 4) {
for (int a = 0; a < 4; a++) {
try {
items[a] = parseToItemstack(split[a]);
} catch (Exception ex) {
throw parseToException("item ID,ID,ID,ID" + ChatColor.RED + " or " + ChatColor.GREEN
+ "ID:Data,ID:Data,ID:Data,ID:Data combo", valueString, methodName);
}
}
} else {
throw parseToException("item ID,ID,ID,ID" + ChatColor.RED + " or " + ChatColor.GREEN
+ "ID:Data,ID:Data,ID:Data,ID:Data combo", valueString, methodName);
}
value = items;
} else if (param.getSimpleName().equals("Color")) {
// Parse to horse color
value = callValueOf(param, valueString, methodName, "a horse color");
} else if (param.getSimpleName().equals("Style")) {
// Parse to horse style
value = callValueOf(param, valueString, methodName, "a horse style");
} else if (param.getSimpleName().equals("Profession")) {
// Parse to villager profession
value = callValueOf(param, valueString, methodName, "a villager profession");
} else if (param.getSimpleName().equals("Art")) {
// Parse to art type
value = callValueOf(param, valueString, methodName, "a painting art");
} else if (param.getSimpleName().equals("Type")) {
// Parse to ocelot type
value = callValueOf(param, valueString, methodName, "a ocelot type");
} else if (param == PotionEffectType.class) {
// Parse to potion effect
try {
PotionEffectType potionType = PotionEffectType.getByName(valueString.toUpperCase());
if (potionType == null && isNumeric(valueString)) {
potionType = PotionEffectType.getById(Integer.parseInt(valueString));
}
if (potionType == null)
throw new DisguiseParseException();
value = potionType;
} catch (Exception ex) {
throw parseToException("a potioneffect type", valueString, methodName);
}
} else if (param == int[].class) {
String[] split = valueString.split(",");
int[] values = new int[split.length];
for (int b = 0; b < values.length; b++) {
try {
values[b] = Integer.parseInt(split[b]);
} catch (NumberFormatException ex) {
throw parseToException("Number,Number,Number...", valueString, methodName);
}
}
value = values;
} else if (param == BlockFace.class) {
try {
BlockFace face = BlockFace.valueOf(valueString.toUpperCase());
if (face.ordinal() > 4)
throw new DisguiseParseException();
value = face;
} catch (Exception ex) {
throw parseToException("a direction (north, east, south, west, up)", valueString, methodName);
}
} else if (param == RabbitType.class) {
try {
for (RabbitType type : RabbitType.values()) {
if (type.name().replace("_", "")
.equalsIgnoreCase(valueString.replace("_", "").replace(" ", ""))) {
value = type;
break;
}
}
if (value == null) {
throw new Exception();
}
} catch (Exception ex) {
throw parseToException("rabbit type (white, brown, patches...)", valueString, methodName);
}
}
}
if (value == null && boolean.class == param) {
if (valueString == null) {
value = true;
i--;
} else if (valueString.equalsIgnoreCase("true")) {
value = true;
} else if (valueString.equalsIgnoreCase("false")) {
value = false;
} else {
if (getMethod(methods, valueString, 0) == null) {
throw parseToException("true/false", valueString, methodName);
} else {
value = true;
i--;
}
}
}
if (value != null) {
break;
}
} catch (DisguiseParseException ex) {
storedEx = ex;
methodToUse = null;
} catch (Exception ex) {
ex.printStackTrace();
methodToUse = null;
}
}
if (methodToUse == null) {
if (storedEx != null) {
throw storedEx;
}
throw new DisguiseParseException(ChatColor.RED + "Cannot find the option " + methodName);
}
if (value == null) {
throw new DisguiseParseException(ChatColor.RED + "No value was given for the option " + methodName);
}
if (!usedOptions.contains(methodName.toLowerCase())) {
usedOptions.add(methodName.toLowerCase());
}
doCheck(optionPermissions, usedOptions);
if (FlagWatcher.class.isAssignableFrom(methodToUse.getDeclaringClass()))
methodToUse.invoke(disguise.getWatcher(), value);
else
methodToUse.invoke(disguise, value);
}
// Alright. We've constructed our disguise.
return disguise;
}
private Entry<Method, Integer> getMethod(Method[] methods, String methodName, int toStart) {
for (int i = toStart; i < methods.length; i++) {
Method method = methods[i];
if (!method.getName().startsWith("get") && method.getName().equalsIgnoreCase(methodName)
&& method.getAnnotation(Deprecated.class) == null && method.getParameterTypes().length == 1) {
return new HashMap.SimpleEntry(method, ++i);
}
}
return null;
}
private Object callValueOf(Class<?> param, String valueString, String methodName, String description)
throws DisguiseParseException {
Object value;
try {
value = param.getMethod("valueOf", String.class).invoke(null, valueString.toUpperCase());
} catch (Exception ex) {
throw parseToException(description, valueString, methodName);
}
return value;
}
private boolean passesCheck(HashMap<ArrayList<String>, Boolean> map1, ArrayList<String> usedOptions) {
boolean hasPermission = false;
for (ArrayList<String> list : map1.keySet()) {
boolean myPerms = true;
for (String option : usedOptions) {
if (!(map1.get(list) && list.contains("*")) && (list.contains(option) != map1.get(list))) {
myPerms = false;
break;
}
}
if (myPerms) {
hasPermission = true;
}
}
return hasPermission;
}
private void doCheck(HashMap<ArrayList<String>, Boolean> optionPermissions, ArrayList<String> usedOptions)
throws DisguiseParseException {
if (!passesCheck(optionPermissions, usedOptions)) {
throw new DisguiseParseException(ChatColor.RED + "You do not have the permission to use the option "
+ usedOptions.get(usedOptions.size() - 1));
}
}
private DisguiseParseException parseToException(String expectedValue, String receivedInstead, String methodName) {
return new DisguiseParseException(ChatColor.RED + "Expected " + ChatColor.GREEN + expectedValue + ChatColor.RED
+ ", received " + ChatColor.GREEN + receivedInstead + ChatColor.RED + " instead for " + ChatColor.GREEN
+ methodName);
}
private ItemStack parseToItemstack(String string) throws Exception {
String[] split = string.split(":", -1);
if (isNumeric(split[0])) {
int itemId = Integer.parseInt(split[0]);
short itemDura = 0;
if (split.length > 1) {
if (isNumeric(split[1])) {
itemDura = Short.parseShort(split[1]);
} else {
throw parseToException("item ID:Durability combo", string, "%s");
}
}
return new ItemStack(itemId, 1, itemDura);
} else {
if (split.length == 1) {
throw parseToException("item ID", string, "%s");
} else {
throw parseToException("item ID:Durability combo", string, "%s");
}
}
}
protected abstract void sendCommandUsage(CommandSender sender, HashMap<DisguiseType, HashMap<ArrayList<String>, Boolean>> map);
}

View File

@@ -0,0 +1,70 @@
package me.libraryaddict.disguise.utilities;
import org.bukkit.entity.Entity;
import java.net.URL;
import java.net.URLDecoder;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
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 {
public static ArrayList<Class<?>> getClassesForPackage(String pkgname) {
ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
// String relPath = pkgname.replace('.', '/');
// Get a File object for the package
CodeSource src = Entity.class.getProtectionDomain().getCodeSource();
if (src != null) {
URL resource = src.getLocation();
resource.getPath();
processJarfile(resource, pkgname, classes);
}
return classes;
}
private static Class<?> loadClass(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Unexpected ClassNotFoundException loading class '" + className + "'");
} catch (NoClassDefFoundError e) {
return null;
}
}
private static void processJarfile(URL resource, String pkgname, ArrayList<Class<?>> classes) {
try {
String relPath = pkgname.replace('.', '/');
String resPath = URLDecoder.decode(resource.getPath(), "UTF-8");
String jarPath = resPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", "");
JarFile jarFile = new JarFile(jarPath);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
String className = null;
if (entryName.endsWith(".class") && entryName.startsWith(relPath)
&& entryName.length() > (relPath.length() + "/".length())) {
className = entryName.replace('/', '.').replace('\\', '.').replace(".class", "");
}
if (className != null) {
Class<?> c = loadClass(className);
if (c != null)
classes.add(c);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

View File

@@ -0,0 +1,230 @@
package me.libraryaddict.disguise.utilities;
import java.util.HashMap;
import java.util.HashSet;
import me.libraryaddict.disguise.utilities.ReflectionManager.LibVersion;
import org.bukkit.Sound;
/**
* Only living disguises go in here!
*/
public enum DisguiseSound {
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;
}
public static DisguiseSound getType(String name) {
try {
return valueOf(name);
} catch (Exception ex) {
return null;
}
}
private HashSet<String> cancelSounds = new HashSet<String>();
private float damageSoundVolume = 1F;
private HashMap<SoundType, String> disguiseSounds = new HashMap<SoundType, String>();
private DisguiseSound(Object... sounds) {
for (int i = 0; i < sounds.length; i++) {
Object obj = sounds[i];
String s;
if (obj == null)
continue;
else if (obj instanceof String) {
s = (String) obj;
} else if (obj instanceof Sound) {
s = ReflectionManager.getCraftSound((Sound) obj);
System.out.print("Warning! The sound " + obj + " needs to be converted to a string");
} else {
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;
}
}
}
public float getDamageAndIdleSoundVolume() {
return damageSoundVolume;
}
public String getSound(SoundType type) {
if (type == null || !disguiseSounds.containsKey(type))
return null;
return disguiseSounds.get(type);
}
public HashSet<String> getSoundsToCancel() {
return cancelSounds;
}
/**
* Used to check if this sound name is owned by this disguise sound.
*/
public SoundType getType(String sound, boolean ignoreDamage) {
if (isCancelSound(sound))
return SoundType.CANCEL;
if (disguiseSounds.containsKey(SoundType.STEP) && disguiseSounds.get(SoundType.STEP).startsWith("step.")
&& sound.startsWith("step."))
return SoundType.STEP;
for (SoundType type : SoundType.values()) {
if (!disguiseSounds.containsKey(type) || type == SoundType.DEATH || (ignoreDamage && type == SoundType.HURT))
continue;
String s = disguiseSounds.get(type);
if (s != null) {
if (s.equals(sound))
return type;
}
}
return null;
}
public boolean isCancelSound(String sound) {
return getSoundsToCancel().contains(sound);
}
public void removeSound(SoundType type, Sound sound) {
removeSound(type, ReflectionManager.getCraftSound(sound));
}
public void removeSound(SoundType type, String sound) {
if (type == SoundType.CANCEL)
cancelSounds.remove(sound);
else {
disguiseSounds.remove(type);
}
}
public void setDamageAndIdleSoundVolume(float strength) {
this.damageSoundVolume = strength;
}
public void setSound(SoundType type, Sound sound) {
setSound(type, ReflectionManager.getCraftSound(sound));
}
public void setSound(SoundType type, String sound) {
if (type == SoundType.CANCEL)
cancelSounds.add(sound);
else {
disguiseSounds.put(type, sound);
}
}
}

View File

@@ -0,0 +1,990 @@
package me.libraryaddict.disguise.utilities;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.DisguiseConfig;
import me.libraryaddict.disguise.LibsDisguises;
import me.libraryaddict.disguise.disguisetypes.Disguise;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
import me.libraryaddict.disguise.disguisetypes.FlagWatcher;
import me.libraryaddict.disguise.disguisetypes.PlayerDisguise;
import me.libraryaddict.disguise.disguisetypes.TargetedDisguise;
import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher;
import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher;
import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Zombie;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
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.
*/
private static HashSet<String> addedByPlugins = new HashSet<String>();
private static Object bedChunk;
private static LinkedHashMap<String, Disguise> clonedDisguises = new LinkedHashMap<String, Disguise>();
/**
* A hashmap of the uuid's of entitys, alive and dead. And their disguises in use
**/
private static HashMap<UUID, HashSet<TargetedDisguise>> disguisesInUse = new HashMap<UUID, HashSet<TargetedDisguise>>();
/**
* 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<Integer, HashSet<TargetedDisguise>> futureDisguises = new HashMap<Integer, HashSet<TargetedDisguise>>();
/**
* A hashmap storing the uuid and skin of a playername
*/
private static HashMap<String, WrappedGameProfile> gameProfiles = new HashMap<String, WrappedGameProfile>();
private static LibsDisguises libsDisguises;
private static HashMap<String, ArrayList<Object>> runnables = new HashMap<String, ArrayList<Object>>();
private static HashSet<UUID> selfDisguised = new HashSet<UUID>();
private static Field xChunk, zChunk;
static {
try {
Object server = ReflectionManager.getNmsMethod("MinecraftServer", "getServer").invoke(null);
Object world = ((List) server.getClass().getField("worlds").get(server)).get(0);
bedChunk = ReflectionManager.getNmsClass("Chunk")
.getConstructor(ReflectionManager.getNmsClass("World"), int.class, int.class).newInstance(world, 0, 0);
Field cSection = bedChunk.getClass().getDeclaredField("sections");
cSection.setAccessible(true);
Object chunkSection = ReflectionManager.getNmsClass("ChunkSection").getConstructor(int.class, boolean.class)
.newInstance(0, true);
Object block;
try {
block = ReflectionManager.getNmsClass("Block").getMethod("getById", int.class)
.invoke(null, Material.BED_BLOCK.getId());
} catch (Exception ex) {
block = ((Object[]) ReflectionManager.getNmsField(ReflectionManager.getNmsClass("Block"), "byId").get(null))[Material.BED_BLOCK
.getId()];
}
Method fromLegacyData = block.getClass().getMethod("fromLegacyData", int.class);
Method setType = chunkSection.getClass().getMethod("setType", int.class, int.class, int.class,
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 }) {
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);
}
Object[] array = (Object[]) Array.newInstance(chunkSection.getClass(), 16);
array[0] = chunkSection;
cSection.set(bedChunk, array);
xChunk = bedChunk.getClass().getField("locX");
xChunk.setAccessible(true);
zChunk = bedChunk.getClass().getField("locZ");
zChunk.setAccessible(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static boolean addClonedDisguise(String key, Disguise disguise) {
if (DisguiseConfig.getMaxClonedDisguises() > 0) {
if (clonedDisguises.containsKey(key)) {
clonedDisguises.remove(key);
} else if (DisguiseConfig.getMaxClonedDisguises() == clonedDisguises.size()) {
clonedDisguises.remove(clonedDisguises.keySet().iterator().next());
}
if (DisguiseConfig.getMaxClonedDisguises() > clonedDisguises.size()) {
clonedDisguises.put(key, disguise);
return true;
}
}
return false;
}
public static void addDisguise(UUID entityId, TargetedDisguise disguise) {
if (!getDisguises().containsKey(entityId)) {
getDisguises().put(entityId, new HashSet<TargetedDisguise>());
}
getDisguises().get(entityId).add(disguise);
checkConflicts(disguise, null);
if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS && disguise.isModifyBoundingBox()) {
doBoundingBox(disguise);
}
}
public static void addFutureDisguise(final int entityId, final TargetedDisguise disguise) {
if (!futureDisguises.containsKey(entityId)) {
futureDisguises.put(entityId, new HashSet<TargetedDisguise>());
}
futureDisguises.get(entityId).add(disguise);
final BukkitRunnable runnable = new BukkitRunnable() {
public void run() {
if (futureDisguises.containsKey(entityId) && futureDisguises.get(entityId).contains(disguise)) {
for (World world : Bukkit.getWorlds()) {
for (Entity entity : world.getEntities()) {
if (entity.getEntityId() == entityId) {
UUID uniqueId = entity.getUniqueId();
for (TargetedDisguise disguise : futureDisguises.remove(entityId)) {
addDisguise(uniqueId, disguise);
}
return;
}
}
}
futureDisguises.get(entityId).remove(disguise);
if (futureDisguises.get(entityId).isEmpty()) {
futureDisguises.remove(entityId);
}
}
}
};
runnable.runTaskLater(libsDisguises, 20);
}
public static void addGameProfile(String string, WrappedGameProfile gameProfile) {
getGameProfiles().put(string, gameProfile);
getAddedByPlugins().add(string.toLowerCase());
}
/**
* 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
if (DisguiseAPI.isDisguiseInUse(disguise)) {
Iterator<TargetedDisguise> disguiseItel = getDisguises().get(disguise.getEntity().getUniqueId()).iterator();
// Iterate through the disguises
while (disguiseItel.hasNext()) {
TargetedDisguise d = disguiseItel.next();
// Make sure the disguise isn't the same thing
if (d != disguise) {
// If the loop'd disguise is hiding the disguise to everyone in its list
if (d.getDisguiseTarget() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) {
// If player is a observer in the loop
if (disguise.getDisguiseTarget() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) {
// If player is a observer in the disguise
// Remove them from the loop
if (name != null) {
d.removePlayer(name);
} else {
for (String playername : disguise.getObservers()) {
d.silentlyRemovePlayer(playername);
}
}
} else if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
// If player is not a observer in the loop
if (name != null) {
if (!disguise.getObservers().contains(name)) {
d.removePlayer(name);
}
} else {
for (String playername : new ArrayList<String>(d.getObservers())) {
if (!disguise.getObservers().contains(playername)) {
d.silentlyRemovePlayer(playername);
}
}
}
}
} else if (d.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
// Here you add it to the loop if they see the disguise
if (disguise.getDisguiseTarget() == TargetType.HIDE_DISGUISE_TO_EVERYONE_BUT_THESE_PLAYERS) {
// Everyone who is in the disguise needs to be added to the loop
if (name != null) {
d.addPlayer(name);
} else {
for (String playername : disguise.getObservers()) {
d.silentlyAddPlayer(playername);
}
}
} else if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
// This here is a paradox.
// If fed a name. I can do this.
// But the rest of the time.. Its going to conflict.
// The below is debug output. Most people wouldn't care for it.
// 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();
}
}
}
}
}
}
/**
* Sends entity removal packets, as this disguise was removed
*/
public static void destroyEntity(TargetedDisguise disguise) {
try {
Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity());
if (entityTrackerEntry != null) {
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
entityTrackerEntry);
HashSet cloned = (HashSet) trackedPlayers.clone();
PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
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)) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, destroyPacket);
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void doBoundingBox(TargetedDisguise disguise) {
// TODO Slimes
Entity entity = disguise.getEntity();
if (entity != null) {
if (isDisguiseInUse(disguise)) {
DisguiseValues disguiseValues = DisguiseValues.getDisguiseValues(disguise.getType());
FakeBoundingBox disguiseBox = disguiseValues.getAdultBox();
if (disguiseValues.getBabyBox() != null) {
if ((disguise.getWatcher() instanceof AgeableWatcher && ((AgeableWatcher) disguise.getWatcher()).isBaby())
|| (disguise.getWatcher() instanceof ZombieWatcher && ((ZombieWatcher) disguise.getWatcher())
.isBaby())) {
disguiseBox = disguiseValues.getBabyBox();
}
}
ReflectionManager.setBoundingBox(entity, disguiseBox);
} else {
DisguiseValues entityValues = DisguiseValues.getDisguiseValues(DisguiseType.getType(entity.getType()));
FakeBoundingBox entityBox = entityValues.getAdultBox();
if (entityValues.getBabyBox() != null) {
if ((entity instanceof Ageable && !((Ageable) entity).isAdult())
|| (entity instanceof Zombie && ((Zombie) entity).isBaby())) {
entityBox = entityValues.getBabyBox();
}
}
ReflectionManager.setBoundingBox(entity, entityBox);
}
}
}
public static HashSet<String> getAddedByPlugins() {
return addedByPlugins;
}
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 }) {
if (loc == null) {
continue;
}
try {
int chunkX = (int) Math.floor(loc.getX() / 16D) - 17, chunkZ = (int) Math.floor(loc.getZ() / 16D) - 17;
chunkX -= chunkX % 8;
chunkZ -= chunkZ % 8;
xChunk.set(bedChunk, chunkX);
zChunk.set(bedChunk, chunkZ);
} catch (Exception ex) {
ex.printStackTrace();
}
// Make unload packets
try {
packets[i] = ProtocolLibrary.getProtocolManager()
.createPacketConstructor(PacketType.Play.Server.MAP_CHUNK, bedChunk, true, 0, 40)
.createPacket(bedChunk, true, 0, 48);
} catch (IllegalArgumentException ex) {
packets[i] = ProtocolLibrary.getProtocolManager()
.createPacketConstructor(PacketType.Play.Server.MAP_CHUNK, bedChunk, true, 0)
.createPacket(bedChunk, true, 0);
}
i++;
// Make load packets
if (oldLoc == null || i > 1) {
packets[i] = ProtocolLibrary.getProtocolManager()
.createPacketConstructor(PacketType.Play.Server.MAP_CHUNK_BULK, Arrays.asList(bedChunk))
.createPacket(Arrays.asList(bedChunk));
i++;
}
}
return packets;
}
public static PacketContainer[] getBedPackets(Player player, Location loc, Location playerLocation, PlayerDisguise disguise) {
Entity entity = disguise.getEntity();
PacketContainer setBed = new PacketContainer(PacketType.Play.Server.BED);
StructureModifier<Integer> bedInts = setBed.getIntegers();
bedInts.write(0, entity.getEntityId());
PlayerWatcher watcher = disguise.getWatcher();
int chunkX = (int) Math.floor(playerLocation.getX() / 16D) - 17, chunkZ = (int) Math
.floor(playerLocation.getZ() / 16D) - 17;
chunkX -= chunkX % 8;
chunkZ -= chunkZ % 8;
bedInts.write(1, (chunkX * 16) + 1 + watcher.getSleepingDirection().getModX());
bedInts.write(3, (chunkZ * 16) + 1 + watcher.getSleepingDirection().getModZ());
PacketContainer teleport = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
StructureModifier<Integer> ints = teleport.getIntegers();
ints.write(0, entity.getEntityId());
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 };
}
public static Disguise getClonedDisguise(String key) {
if (clonedDisguises.containsKey(key)) {
return clonedDisguises.get(key).clone();
}
return null;
}
public static PacketContainer getDestroyPacket(int... ids) {
PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
destroyPacket.getIntegerArrays().write(0, ids);
return destroyPacket;
}
public static TargetedDisguise getDisguise(Player observer, Entity entity) {
UUID entityId = entity.getUniqueId();
if (futureDisguises.containsKey(entity.getEntityId())) {
for (TargetedDisguise disguise : futureDisguises.remove(entity.getEntityId())) {
addDisguise(entityId, disguise);
}
}
if (getDisguises().containsKey(entityId)) {
for (TargetedDisguise disguise : getDisguises().get(entityId)) {
if (disguise.canSee(observer)) {
return disguise;
}
}
}
return null;
}
public static HashMap<UUID, HashSet<TargetedDisguise>> getDisguises() {
return disguisesInUse;
}
public static TargetedDisguise[] getDisguises(UUID entityId) {
if (getDisguises().containsKey(entityId)) {
HashSet<TargetedDisguise> disguises = getDisguises().get(entityId);
return disguises.toArray(new TargetedDisguise[disguises.size()]);
}
return new TargetedDisguise[0];
}
public static HashMap<Integer, HashSet<TargetedDisguise>> getFutureDisguises() {
return futureDisguises;
}
public static WrappedGameProfile getGameProfile(String playerName) {
return gameProfiles.get(playerName.toLowerCase());
}
public static HashMap<String, WrappedGameProfile> getGameProfiles() {
return gameProfiles;
}
public static TargetedDisguise getMainDisguise(UUID entityId) {
TargetedDisguise toReturn = null;
if (getDisguises().containsKey(entityId)) {
for (TargetedDisguise disguise : getDisguises().get(entityId)) {
if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS) {
return disguise;
}
toReturn = disguise;
}
}
return toReturn;
}
/**
* Get all EntityPlayers who have this entity in their Entity Tracker And they are in the targetted disguise.
*/
public static ArrayList<Player> getPerverts(Disguise disguise) {
ArrayList<Player> players = new ArrayList<Player>();
try {
Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity());
if (entityTrackerEntry != null) {
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
entityTrackerEntry);
for (Object p : trackedPlayers) {
Player player = (Player) ReflectionManager.getBukkitEntity(p);
if (((TargetedDisguise) disguise).canSee(player)) {
players.add(player);
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return players;
}
public static WrappedGameProfile getProfileFromMojang(final PlayerDisguise disguise) {
final String nameToFetch = disguise.getSkin() != null ? disguise.getSkin() : disguise.getName();
final boolean remove = getAddedByPlugins().contains(nameToFetch.toLowerCase());
return getProfileFromMojang(nameToFetch, new LibsProfileLookup() {
@Override
public void onLookup(WrappedGameProfile gameProfile) {
if (remove) {
getAddedByPlugins().remove(nameToFetch.toLowerCase());
}
if (DisguiseAPI.isDisguiseInUse(disguise)
&& (!gameProfile.getName().equals(
disguise.getSkin() != null ? disguise.getSkin() : disguise.getName())
|| !gameProfile.getProperties().isEmpty())) {
disguise.setGameProfile(gameProfile);
DisguiseUtilities.refreshTrackers(disguise);
}
}
});
}
/**
* 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);
}
private static WrappedGameProfile getProfileFromMojang(final String origName, final Object runnable) {
final String playerName = origName.toLowerCase();
if (gameProfiles.containsKey(playerName)) {
if (gameProfiles.get(playerName) != null) {
return gameProfiles.get(playerName);
}
} else if (Pattern.matches("([A-Za-z0-9_]){1,16}", origName)) {
getAddedByPlugins().add(playerName);
Player player = Bukkit.getPlayerExact(playerName);
if (player != null) {
WrappedGameProfile gameProfile = ReflectionManager.getGameProfile(player);
if (!gameProfile.getProperties().isEmpty()) {
gameProfiles.put(playerName, gameProfile);
return gameProfile;
}
}
// Add null so that if this is called again. I already know I'm doing something about it
gameProfiles.put(playerName, null);
Bukkit.getScheduler().runTaskAsynchronously(libsDisguises, new Runnable() {
public void run() {
try {
final WrappedGameProfile gameProfile = lookupGameProfile(origName);
Bukkit.getScheduler().runTask(libsDisguises, new Runnable() {
public void run() {
if (!gameProfile.getProperties().isEmpty()) {
if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) {
gameProfiles.put(playerName, gameProfile);
}
if (runnables.containsKey(playerName)) {
for (Object obj : runnables.remove(playerName)) {
if (obj instanceof Runnable) {
((Runnable) obj).run();
} else if (obj instanceof LibsProfileLookup) {
((LibsProfileLookup) obj).onLookup(gameProfile);
}
}
}
}
}
});
} catch (Exception e) {
if (gameProfiles.containsKey(playerName) && gameProfiles.get(playerName) == null) {
gameProfiles.remove(playerName);
getAddedByPlugins().remove(playerName);
}
System.out.print("[LibsDisguises] Error when fetching " + playerName + "'s uuid from mojang: "
+ e.getMessage());
}
}
});
} else {
return ReflectionManager.getGameProfile(null, origName);
}
if (runnable != null) {
if (!runnables.containsKey(playerName)) {
runnables.put(playerName, new ArrayList<Object>());
}
runnables.get(playerName).add(runnable);
}
return ReflectionManager.getGameProfile(null, origName);
}
/**
* 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);
}
public static HashSet<UUID> getSelfDisguised() {
return selfDisguised;
}
public static boolean hasGameProfile(String playerName) {
return getGameProfile(playerName) != null;
}
public static void init(LibsDisguises disguises) {
libsDisguises = disguises;
}
public static boolean isDisguiseInUse(Disguise disguise) {
return disguise.getEntity() != null && getDisguises().containsKey(disguise.getEntity().getUniqueId())
&& getDisguises().get(disguise.getEntity().getUniqueId()).contains(disguise);
}
/**
* This is called on a thread as it is thread blocking
*/
public static WrappedGameProfile lookupGameProfile(String playerName) {
return ReflectionManager.getSkullBlob(ReflectionManager.grabProfileAddUUID(playerName));
}
/**
* 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<WrappedWatchableObject> rebuildForVersion(Player player, FlagWatcher watcher,
List<WrappedWatchableObject> list) {
if (true) // Use for future protocol compatibility
return list;
ArrayList<WrappedWatchableObject> rebuiltList = new ArrayList<WrappedWatchableObject>();
ArrayList<WrappedWatchableObject> backups = new ArrayList<WrappedWatchableObject>();
for (WrappedWatchableObject obj : list) {
if (obj.getValue().getClass().getName().startsWith("org.")) {
backups.add(obj);
continue;
}
switch (obj.getIndex()) {
// TODO: Future version support
}
}
Iterator<WrappedWatchableObject> itel = backups.iterator();
while (itel.hasNext()) {
int index = itel.next().getIndex();
for (WrappedWatchableObject obj2 : rebuiltList) {
if (index == obj2.getIndex()) {
itel.remove();
break;
}
}
}
rebuiltList.addAll(backups);
return rebuiltList;
}
/**
* Resends the entity to this specific player
*/
public static void refreshTracker(final TargetedDisguise disguise, String player) {
if (disguise.getEntity() != null && disguise.getEntity().isValid()) {
try {
PacketContainer destroyPacket = getDestroyPacket(disguise.getEntity().getEntityId());
if (disguise.isDisguiseInUse() && disguise.getEntity() instanceof Player
&& ((Player) disguise.getEntity()).getName().equalsIgnoreCase(player)) {
removeSelfDisguise((Player) disguise.getEntity());
if (disguise.isSelfDisguiseVisible())
selfDisguised.add(disguise.getEntity().getUniqueId());
ProtocolLibrary.getProtocolManager().sendServerPacket((Player) disguise.getEntity(), destroyPacket);
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
public void run() {
try {
DisguiseUtilities.sendSelfDisguise((Player) disguise.getEntity(), disguise);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 2);
} else {
final Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity());
if (entityTrackerEntry != null) {
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers")
.get(entityTrackerEntry);
Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear",
ReflectionManager.getNmsClass("EntityPlayer"));
final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer",
ReflectionManager.getNmsClass("EntityPlayer"));
HashSet cloned = (HashSet) trackedPlayers.clone();
for (final Object p : cloned) {
Player pl = (Player) ReflectionManager.getBukkitEntity(p);
if (player.equalsIgnoreCase((pl).getName())) {
clear.invoke(entityTrackerEntry, p);
ProtocolLibrary.getProtocolManager().sendServerPacket(pl, destroyPacket);
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
public void run() {
try {
updatePlayer.invoke(entityTrackerEntry, p);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 2);
break;
}
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
/**
* A convenience method for me to refresh trackers in other plugins
*/
public static void refreshTrackers(Entity entity) {
if (entity.isValid()) {
try {
PacketContainer destroyPacket = getDestroyPacket(entity.getEntityId());
final Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(entity);
if (entityTrackerEntry != null) {
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
entityTrackerEntry);
Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear",
ReflectionManager.getNmsClass("EntityPlayer"));
final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer",
ReflectionManager.getNmsClass("EntityPlayer"));
HashSet cloned = (HashSet) trackedPlayers.clone();
for (final Object p : cloned) {
Player player = (Player) ReflectionManager.getBukkitEntity(p);
if (player != entity) {
clear.invoke(entityTrackerEntry, p);
ProtocolLibrary.getProtocolManager().sendServerPacket(player, destroyPacket);
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
public void run() {
try {
updatePlayer.invoke(entityTrackerEntry, p);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 2);
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
/**
* Resends the entity to all the watching players, which is where the magic begins
*/
public static void refreshTrackers(final TargetedDisguise disguise) {
if (disguise.getEntity().isValid()) {
PacketContainer destroyPacket = getDestroyPacket(disguise.getEntity().getEntityId());
try {
if (selfDisguised.contains(disguise.getEntity().getUniqueId()) && disguise.isDisguiseInUse()) {
removeSelfDisguise((Player) disguise.getEntity());
selfDisguised.add(disguise.getEntity().getUniqueId());
ProtocolLibrary.getProtocolManager().sendServerPacket((Player) disguise.getEntity(), destroyPacket);
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
public void run() {
try {
DisguiseUtilities.sendSelfDisguise((Player) disguise.getEntity(), disguise);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 2);
}
final Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(disguise.getEntity());
if (entityTrackerEntry != null) {
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
entityTrackerEntry);
Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "clear",
ReflectionManager.getNmsClass("EntityPlayer"));
final Method updatePlayer = ReflectionManager.getNmsMethod("EntityTrackerEntry", "updatePlayer",
ReflectionManager.getNmsClass("EntityPlayer"));
HashSet cloned = (HashSet) trackedPlayers.clone();
for (final Object p : cloned) {
Player player = (Player) ReflectionManager.getBukkitEntity(p);
if (disguise.getEntity() != player && disguise.canSee(player)) {
clear.invoke(entityTrackerEntry, p);
ProtocolLibrary.getProtocolManager().sendServerPacket(player, destroyPacket);
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
public void run() {
try {
updatePlayer.invoke(entityTrackerEntry, p);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 2);
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static boolean removeDisguise(TargetedDisguise disguise) {
UUID entityId = disguise.getEntity().getUniqueId();
if (getDisguises().containsKey(entityId) && getDisguises().get(entityId).remove(disguise)) {
if (getDisguises().get(entityId).isEmpty()) {
getDisguises().remove(entityId);
}
if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS && disguise.isModifyBoundingBox()) {
doBoundingBox(disguise);
}
return true;
}
return false;
}
@Deprecated
public static void removeGameprofile(String string) {
removeGameProfile(string);
}
public static void removeGameProfile(String string) {
gameProfiles.remove(string.toLowerCase());
}
public static void removeSelfDisguise(Player player) {
if (selfDisguised.contains(player.getUniqueId())) {
// Send a packet to destroy the fake entity
PacketContainer packet = getDestroyPacket(DisguiseAPI.getSelfDisguiseId());
try {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
} catch (Exception ex) {
ex.printStackTrace();
}
// Remove the fake entity ID from the disguise bin
selfDisguised.remove(player.getUniqueId());
// Get the entity tracker
try {
Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(player);
if (entityTrackerEntry != null) {
HashSet trackedPlayers = (HashSet) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(
entityTrackerEntry);
// If the tracker exists. Remove himself from his tracker
trackedPlayers.remove(ReflectionManager.getNmsEntity(player));
}
} catch (Exception ex) {
ex.printStackTrace();
}
// Resend entity metadata else he will be invisible to himself until its resent
try {
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));
} catch (Exception ex) {
ex.printStackTrace();
}
player.updateInventory();
}
}
/**
* Sends the self disguise to the player
*/
public static void sendSelfDisguise(final Player player, final TargetedDisguise disguise) {
try {
if (!disguise.isDisguiseInUse() || !player.isValid() || !player.isOnline() || !disguise.isSelfDisguiseVisible()
|| !disguise.canSee(player)) {
return;
}
Object entityTrackerEntry = ReflectionManager.getEntityTrackerEntry(player);
if (entityTrackerEntry == null) {
// A check incase the tracker is null.
// If it is, then this method will be run again in one tick. Which is when it should be constructed.
// Else its going to run in a infinite loop hue hue hue..
// At least until this disguise is discarded
Bukkit.getScheduler().runTask(libsDisguises, new Runnable() {
public void run() {
if (DisguiseAPI.getDisguise(player, player) == disguise) {
sendSelfDisguise(player, disguise);
}
}
});
return;
}
// Add himself to his own entity tracker
((HashSet<Object>) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers").get(entityTrackerEntry))
.add(ReflectionManager.getNmsEntity(player));
ProtocolManager manager = ProtocolLibrary.getProtocolManager();
// Send the player a packet with himself being spawned
manager.sendServerPacket(player, manager.createPacketConstructor(PacketType.Play.Server.NAMED_ENTITY_SPAWN, player)
.createPacket(player));
WrappedDataWatcher dataWatcher = WrappedDataWatcher.getEntityWatcher(player);
sendSelfPacket(
player,
manager.createPacketConstructor(PacketType.Play.Server.ENTITY_METADATA, player.getEntityId(), dataWatcher,
true).createPacket(player.getEntityId(), dataWatcher, true));
boolean isMoving = false;
try {
Field field = ReflectionManager.getNmsClass("EntityTrackerEntry").getDeclaredField("isMoving");
field.setAccessible(true);
isMoving = field.getBoolean(entityTrackerEntry);
} catch (Exception ex) {
ex.printStackTrace();
}
// Send the velocity packets
if (isMoving) {
Vector velocity = player.getVelocity();
sendSelfPacket(
player,
manager.createPacketConstructor(PacketType.Play.Server.ENTITY_VELOCITY, player.getEntityId(),
velocity.getX(), velocity.getY(), velocity.getZ()).createPacket(player.getEntityId(),
velocity.getX(), velocity.getY(), velocity.getZ()));
}
// Why the hell would he even need this. Meh.
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()));
} 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));
}
// Resend the armor
for (int i = 0; i < 5; i++) {
ItemStack item;
if (i == 0) {
item = player.getItemInHand();
} else {
item = player.getInventory().getArmorContents()[i - 1];
}
if (item != null && item.getType() != Material.AIR) {
sendSelfPacket(
player,
manager.createPacketConstructor(PacketType.Play.Server.ENTITY_EQUIPMENT, player.getEntityId(), i,
item).createPacket(player.getEntityId(), i, item));
}
}
Location loc = player.getLocation();
// If the disguised is sleeping for w/e reason
if (player.isSleeping()) {
sendSelfPacket(
player,
manager.createPacketConstructor(PacketType.Play.Server.BED, player, loc.getBlockX(), loc.getBlockY(),
loc.getBlockZ()).createPacket(player, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
}
// Resend any active potion effects
for (PotionEffect potionEffect : player.getActivePotionEffects()) {
Object mobEffect = ReflectionManager.createMobEffect(potionEffect);
sendSelfPacket(player,
manager.createPacketConstructor(PacketType.Play.Server.ENTITY_EFFECT, player.getEntityId(), mobEffect)
.createPacket(player.getEntityId(), mobEffect));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Method to send a packet to the self disguise, translate his entity ID to the fake id.
*/
private static void sendSelfPacket(final Player player, PacketContainer packet) {
PacketContainer[][] transformed = PacketsManager.transformPacket(packet, player, player);
PacketContainer[] packets = transformed == null ? null : transformed[0];
final PacketContainer[] delayed = transformed == null ? null : transformed[1];
try {
if (packets == null) {
packets = new PacketContainer[] { packet };
}
for (PacketContainer p : packets) {
p = p.deepClone();
p.getIntegers().write(0, DisguiseAPI.getSelfDisguiseId());
ProtocolLibrary.getProtocolManager().sendServerPacket(player, p, false);
}
if (delayed != null && delayed.length > 0) {
Bukkit.getScheduler().scheduleSyncDelayedTask(libsDisguises, new Runnable() {
public void run() {
try {
for (PacketContainer packet : delayed) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, false);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* Setup it so he can see himself when disguised
*/
public static void setupFakeDisguise(final Disguise disguise) {
Entity e = disguise.getEntity();
// If the disguises entity is null, or the disguised entity isn't a player return
if (e == null || !(e instanceof Player) || !getDisguises().containsKey(e.getUniqueId())
|| !getDisguises().get(e.getUniqueId()).contains(disguise)) {
return;
}
Player player = (Player) e;
// Check if he can even see this..
if (!((TargetedDisguise) disguise).canSee(player)) {
return;
}
// Remove the old disguise, else we have weird disguises around the place
DisguiseUtilities.removeSelfDisguise(player);
// If the disguised player can't see himself. Return
if (!disguise.isSelfDisguiseVisible() || !PacketsManager.isViewDisguisesListenerEnabled() || player.getVehicle() != null) {
return;
}
selfDisguised.add(player.getUniqueId());
sendSelfDisguise(player, (TargetedDisguise) disguise);
if (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf()) {
if (PacketsManager.isInventoryListenerEnabled()) {
player.updateInventory();
}
}
}
}

View File

@@ -0,0 +1,145 @@
package me.libraryaddict.disguise.utilities;
import java.util.HashMap;
import me.libraryaddict.disguise.disguisetypes.DisguiseType;
public class DisguiseValues {
private static HashMap<DisguiseType, DisguiseValues> values = new HashMap<DisguiseType, 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;
}
return values.get(type);
}
public static HashMap<Integer, Object> getMetaValues(DisguiseType type) {
return getDisguiseValues(type).getMetaValues();
}
public static Class getNmsEntityClass(DisguiseType type) {
return getDisguiseValues(type).getNmsEntityClass();
}
private FakeBoundingBox adultBox;
private FakeBoundingBox babyBox;
private float[] entitySize;
private int enumEntitySize;
private double maxHealth;
private HashMap<Integer, Object> metaValues = new HashMap<Integer, Object>();
private Class nmsEntityClass;
public DisguiseValues(DisguiseType type, Class classType, int entitySize, double maxHealth) {
values.put(type, this);
enumEntitySize = entitySize;
nmsEntityClass = classType;
this.maxHealth = maxHealth;
}
public FakeBoundingBox getAdultBox() {
return adultBox;
}
public FakeBoundingBox getBabyBox() {
return babyBox;
}
public float[] getEntitySize() {
return entitySize;
}
public int getEntitySize(double paramDouble) {
double d = paramDouble - (((int) Math.floor(paramDouble)) + 0.5D);
switch (enumEntitySize) {
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.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);
}
return (int) Math.ceil(paramDouble * 32.0D);
default:
break;
}
if (d > 0.0D) {
return (int) Math.ceil(paramDouble * 32.0D);
}
return (int) Math.floor(paramDouble * 32.0D);
}
public double getMaxHealth() {
return maxHealth;
}
public HashMap<Integer, Object> getMetaValues() {
return metaValues;
}
public Class getNmsEntityClass() {
return nmsEntityClass;
}
public void setAdultBox(FakeBoundingBox newBox) {
adultBox = newBox;
}
public void setBabyBox(FakeBoundingBox newBox) {
babyBox = newBox;
}
public void setEntitySize(float[] size) {
this.entitySize = size;
}
public void setMetaValue(int no, Object value) {
metaValues.put(no, value);
}
}

View File

@@ -0,0 +1,26 @@
package me.libraryaddict.disguise.utilities;
public class FakeBoundingBox {
private double xMod;
private double yMod;
private double zMod;
public FakeBoundingBox(double xMod, double yMod, double zMod) {
this.xMod = xMod;
this.yMod = yMod;
this.zMod = zMod;
}
public double getX() {
return xMod / 2;
}
public double getY() {
return yMod;
}
public double getZ() {
return zMod / 2;
}
}

View File

@@ -0,0 +1,8 @@
package me.libraryaddict.disguise.utilities;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
public interface LibsProfileLookup {
public void onLookup(WrappedGameProfile gameProfile);
}

View File

@@ -0,0 +1,24 @@
package me.libraryaddict.disguise.utilities;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.ProfileLookupCallback;
public class LibsProfileLookupCaller implements ProfileLookupCallback {
private WrappedGameProfile gameProfile;
public WrappedGameProfile getGameProfile() {
return gameProfile;
}
@Override
public void onProfileLookupFailed(GameProfile gameProfile, Exception arg1) {
}
@Override
public void onProfileLookupSucceeded(GameProfile profile) {
gameProfile = WrappedGameProfile.fromHandle(profile);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,633 @@
package me.libraryaddict.disguise.utilities;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.collect.ImmutableMap;
import org.bukkit.Art;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
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;
}
public static LibVersion getGameVersion() {
return currentVersion;
}
}
private static final String bukkitVersion = Bukkit.getServer().getClass().getName().split("\\.")[3];
private static final Class<?> craftItemClass;
private static Method damageAndIdleSoundMethod;
private static final Field entitiesField;
private static final Constructor<?> boundingBoxConstructor;
private static final Method setBoundingBoxMethod;
/**
* Map of mc-dev simple class name to fully qualified Forge class name.
*/
private static Map<String, String> ForgeClassMappings;
/**
* Map of Forge fully qualified class names to a map from mc-dev field names to Forge field names.
*/
private static Map<String, Map<String, String>> 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.
*/
private static Map<String, Map<String, Map<String, String>>> ForgeMethodMappings;
private static final Method ihmGet;
private static final boolean isForge = Bukkit.getServer().getName().contains("Cauldron")
|| Bukkit.getServer().getName().contains("MCPC-Plus");
private static final Field pingField;
private static Map<Class<?>, String> primitiveTypes;
private static final Field trackerField;
/*
* This portion of code is originally Copyright (C) 2014-2014 Kane York.
*
* In addition to the implicit license granted to libraryaddict to redistribuite the code, the
* code is also licensed to the public under the BSD 2-clause license.
*
* The publicly licensed version may be viewed here: https://gist.github.com/riking/2f330f831c30e2276df7
*/
static {
final String nameseg_class = "a-zA-Z0-9$_";
final String fqn_class = nameseg_class + "/";
primitiveTypes = ImmutableMap.<Class<?>, 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();
if (isForge) {
// Initialize the maps by reading the srg file
ForgeClassMappings = new HashMap<String, String>();
ForgeFieldMappings = new HashMap<String, Map<String, String>>();
ForgeMethodMappings = new HashMap<String, Map<String, Map<String, String>>>();
try {
InputStream stream = Class.forName("net.minecraftforge.common.MinecraftForge").getClassLoader()
.getResourceAsStream("mappings/" + getBukkitVersion() + "/cb2numpkg.srg");
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
// 1: cb-simpleName
// 2: forge-fullName (Needs dir2fqn())
Pattern classPattern = Pattern.compile("^CL: net/minecraft/server/([" + nameseg_class + "]+) ([" + fqn_class
+ "]+)$");
// 1: cb-simpleName
// 2: cb-fieldName
// 3: forge-fullName (Needs dir2fqn())
// 4: forge-fieldName
Pattern fieldPattern = Pattern.compile("^FD: net/minecraft/server/([" + nameseg_class + "]+)/([" + nameseg_class
+ "]+) ([" + fqn_class + "]+)/([" + nameseg_class + "]+)$");
// 1: cb-simpleName
// 2: cb-methodName
// 3: cb-signature-args
// 4: cb-signature-ret
// 5: forge-fullName (Needs dir2fqn())
// 6: forge-methodName
// 7: forge-signature-args
// 8: forge-signature-ret
Pattern methodPattern = Pattern.compile("^MD: net/minecraft/server/([" + fqn_class + "]+)/([" + nameseg_class
+ "]+) \\(([;\\[" + fqn_class + "]*)\\)([;\\[" + fqn_class + "]+) " + "([" + fqn_class + "]+)/(["
+ nameseg_class + "]+) \\(([;\\[" + fqn_class + "]*)\\)([;\\[" + fqn_class + "]+)$");
String line;
while ((line = reader.readLine()) != null) {
Matcher classMatcher = classPattern.matcher(line);
if (classMatcher.matches()) {
// by CB class name
ForgeClassMappings.put(classMatcher.group(1), dir2fqn(classMatcher.group(2)));
continue;
}
Matcher fieldMatcher = fieldPattern.matcher(line);
if (fieldMatcher.matches()) {
// by CB class name
Map<String, String> innerMap = ForgeFieldMappings.get(dir2fqn(fieldMatcher.group(3)));
if (innerMap == null) {
innerMap = new HashMap<String, String>();
ForgeFieldMappings.put(dir2fqn(fieldMatcher.group(3)), innerMap);
}
// by CB field name to Forge field name
innerMap.put(fieldMatcher.group(2), fieldMatcher.group(4));
continue;
}
Matcher methodMatcher = methodPattern.matcher(line);
if (methodMatcher.matches()) {
// get by CB class name
Map<String, Map<String, String>> middleMap = ForgeMethodMappings.get(dir2fqn(methodMatcher.group(5)));
if (middleMap == null) {
middleMap = new HashMap<String, Map<String, String>>();
ForgeMethodMappings.put(dir2fqn(methodMatcher.group(5)), middleMap);
}
// get by CB method name
Map<String, String> innerMap = middleMap.get(methodMatcher.group(2));
if (innerMap == null) {
innerMap = new HashMap<String, String>();
middleMap.put(methodMatcher.group(2), innerMap);
}
// store the parameter strings
innerMap.put(methodMatcher.group(3), methodMatcher.group(6));
innerMap.put(methodMatcher.group(7), methodMatcher.group(6));
}
}
System.out.println("[LibsDisguises] Loaded in Cauldron/Forge mode");
System.out.println("[LibsDisguises] Loaded " + ForgeClassMappings.size() + " Cauldron class mappings");
System.out.println("[LibsDisguises] Loaded " + ForgeFieldMappings.size() + " Cauldron field mappings");
System.out.println("[LibsDisguises] Loaded " + ForgeMethodMappings.size() + " Cauldron method mappings");
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.err
.println("Warning: Running on Cauldron server, but couldn't load mappings file. LibsDisguises will likely crash!");
} catch (IOException e) {
e.printStackTrace();
System.err
.println("Warning: Running on Cauldron server, but couldn't load mappings file. LibsDisguises will likely crash!");
}
}
}
static {
for (Method method : getNmsClass("EntityLiving").getDeclaredMethods()) {
try {
if (method.getReturnType() == float.class && Modifier.isProtected(method.getModifiers())
&& method.getParameterTypes().length == 0) {
Object entity = createEntityInstance("Cow");
method.setAccessible(true);
float value = (Float) method.invoke(entity);
if (value == 0.4F) {
damageAndIdleSoundMethod = method;
break;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
craftItemClass = getCraftClass("inventory.CraftItemStack");
pingField = getNmsField("EntityPlayer", "ping");
trackerField = getNmsField("WorldServer", "tracker");
entitiesField = getNmsField("EntityTracker", "trackedEntities");
ihmGet = getNmsMethod("IntHashMap", "get", int.class);
boundingBoxConstructor = getNmsConstructor("AxisAlignedBB",double.class, double.class, double.class,
double.class, double.class, double.class);
setBoundingBoxMethod = getNmsMethod("Entity", "a", getNmsClass("AxisAlignedBB"));
}
public static Object createEntityInstance(String entityName) {
try {
Class<?> entityClass = getNmsClass("Entity" + entityName);
Object entityObject;
Object world = getWorld(Bukkit.getWorlds().get(0));
if (entityName.equals("Player")) {
Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null);
Object playerinteractmanager = getNmsClass("PlayerInteractManager").getConstructor(getNmsClass("World"))
.newInstance(world);
WrappedGameProfile gameProfile = getGameProfile(null, "LibsDisguises");
entityObject = entityClass.getConstructor(getNmsClass("MinecraftServer"), getNmsClass("WorldServer"),
gameProfile.getHandleType(), playerinteractmanager.getClass()).newInstance(minecraftServer, world,
gameProfile.getHandle(), playerinteractmanager);
} else if (entityName.equals("EnderPearl")) {
entityObject = entityClass.getConstructor(getNmsClass("World"), getNmsClass("EntityLiving"))
.newInstance(world, createEntityInstance("Cow"));
} else {
entityObject = entityClass.getConstructor(getNmsClass("World")).newInstance(world);
}
return entityObject;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object createMobEffect(int id, int duration, int amplification, boolean ambient, boolean particles) {
try {
return getNmsClass("MobEffect").getConstructor(int.class, int.class, int.class, boolean.class, boolean.class)
.newInstance(id, duration, amplification, ambient, particles);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object createMobEffect(PotionEffect effect) {
return createMobEffect(effect.getType().getId(), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles());
}
private static String dir2fqn(String s) {
return s.replaceAll("/", ".");
}
public static FakeBoundingBox getBoundingBox(Entity entity) {
try {
Object boundingBox = getNmsMethod("Entity", "getBoundingBox").invoke(getNmsEntity(entity));
double x = 0, y = 0, z = 0;
int stage = 0;
for (Field field : boundingBox.getClass().getFields()) {
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??");
}
}
}
return new FakeBoundingBox(x, y, z);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Entity getBukkitEntity(Object nmsEntity) {
try {
return (Entity) getNmsMethod("Entity", "getBukkitEntity").invoke(nmsEntity);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static ItemStack getBukkitItem(Object nmsItem) {
try {
return (ItemStack) craftItemClass.getMethod("asBukkitCopy", getNmsClass("ItemStack")).invoke(null, nmsItem);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String getBukkitVersion() {
return bukkitVersion;
}
public static Class<?> getCraftClass(String className) {
try {
return Class.forName("org.bukkit.craftbukkit." + getBukkitVersion() + "." + className);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String getCraftSound(Sound sound) {
try {
return (String) getCraftClass("CraftSound").getMethod("getSound", Sound.class).invoke(null, sound);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Object getEntityTrackerEntry(Entity target) throws Exception {
Object world = getWorld(target.getWorld());
Object tracker = trackerField.get(world);
Object trackedEntities = entitiesField.get(tracker);
return ihmGet.invoke(trackedEntities, target.getEntityId());
}
public static String getEnumArt(Art art) {
try {
Object enumArt = getCraftClass("CraftArt").getMethod("BukkitToNotch", Art.class).invoke(null, art);
for (Field field : enumArt.getClass().getFields()) {
if (field.getType() == String.class) {
return (String) field.get(enumArt);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Object getBlockPosition(int x, int y, int z) {
try {
return getNmsClass("BlockPosition").getConstructor(int.class, int.class, int.class).newInstance(x, y, z);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Enum getEnumDirection(int direction) {
try {
return (Enum) getNmsMethod("EnumDirection", "fromType2", int.class).invoke(null, direction);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Enum getEnumPlayerInfoAction(int action) {
try {
return (Enum) getNmsClass("PacketPlayOutPlayerInfo$EnumPlayerInfoAction").getEnumConstants()[action];
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Object getPlayerInfoData(Object playerInfoPacket, WrappedGameProfile gameProfile) {
try {
Object playerListName = getNmsClass("ChatComponentText").getConstructor(String.class)
.newInstance(gameProfile.getName());
return getNmsClass("PacketPlayOutPlayerInfo$PlayerInfoData").getConstructor(getNmsClass("PacketPlayOutPlayerInfo"),
gameProfile.getHandleType(), int.class, getNmsClass("WorldSettings$EnumGamemode"), getNmsClass("IChatBaseComponent"))
.newInstance(playerInfoPacket, gameProfile.getHandle(), 0,
getNmsClass("WorldSettings$EnumGamemode").getEnumConstants()[1], playerListName);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static WrappedGameProfile getGameProfile(Player player) {
return WrappedGameProfile.fromPlayer(player);
}
public static WrappedGameProfile getGameProfile(UUID uuid, String playerName) {
try {
return new WrappedGameProfile(uuid != null ? uuid : UUID.randomUUID(), playerName);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static WrappedGameProfile getGameProfileWithThisSkin(UUID uuid, String playerName, WrappedGameProfile profileWithSkin) {
try {
WrappedGameProfile gameProfile = new WrappedGameProfile(uuid != null ? uuid : UUID.randomUUID(), playerName);
gameProfile.getProperties().putAll(profileWithSkin.getProperties());
return gameProfile;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Class getNmsClass(String className) {
if (isForge) {
String forgeName = ForgeClassMappings.get(className);
if (forgeName != null) {
try {
return Class.forName(forgeName);
} catch (ClassNotFoundException ignored) {
}
} else {
// Throw, because the default cannot possibly work
throw new RuntimeException("Missing Forge mapping for " + className);
}
}
try {
return Class.forName("net.minecraft.server." + getBukkitVersion() + "." + className);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Constructor getNmsConstructor(Class clazz, Class<?>... parameters) {
try {
return clazz.getConstructor(parameters);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
public static Constructor getNmsConstructor(String className, Class<?>... parameters) {
return getNmsConstructor(getNmsClass(className), parameters);
}
public static Object getNmsEntity(Entity entity) {
try {
return getCraftClass("entity.CraftEntity").getMethod("getHandle").invoke(entity);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Field getNmsField(Class clazz, String fieldName) {
if (isForge) {
try {
return clazz.getField(ForgeFieldMappings.get(clazz.getName()).get(fieldName));
} catch (NoSuchFieldException ex) {
ex.printStackTrace();
} catch (NullPointerException ignored) {
}
}
try {
return clazz.getField(fieldName);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return null;
}
public static Field getNmsField(String className, String fieldName) {
return getNmsField(getNmsClass(className), fieldName);
}
public static Object getNmsItem(ItemStack itemstack) {
try {
return craftItemClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, itemstack);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Method getNmsMethod(Class<?> clazz, String methodName, Class<?>... parameters) {
if (isForge) {
try {
Map<String, String> innerMap = ForgeMethodMappings.get(clazz.getName()).get(methodName);
StringBuilder sb = new StringBuilder();
for (Class<?> cl : parameters) {
sb.append(methodSignaturePart(cl));
}
return clazz.getMethod(innerMap.get(sb.toString()), parameters);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (NullPointerException ignored) {
}
}
try {
return clazz.getMethod(methodName, parameters);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
public static Method getNmsMethod(String className, String methodName, Class<?>... parameters) {
return getNmsMethod(getNmsClass(className), methodName, parameters);
}
public static double getPing(Player player) {
try {
return (double) pingField.getInt(ReflectionManager.getNmsEntity(player));
} catch (Exception ex) {
ex.printStackTrace();
}
return 0D;
}
public static float[] getSize(Entity entity) {
try {
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 };
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static WrappedGameProfile getSkullBlob(WrappedGameProfile gameProfile) {
try {
Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null);
for (Method method : getNmsClass("MinecraftServer").getMethods()) {
if (method.getReturnType().getSimpleName().equals("MinecraftSessionService")) {
Object session = method.invoke(minecraftServer);
return WrappedGameProfile.fromHandle(session.getClass()
.getMethod("fillProfileProperties", gameProfile.getHandleType(), boolean.class)
.invoke(session, gameProfile.getHandle(), true));
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Float getSoundModifier(Object entity) {
try {
damageAndIdleSoundMethod.setAccessible(true);
return (Float) damageAndIdleSoundMethod.invoke(entity);
} catch (Exception ex) {
}
return null;
}
public static Object getWorld(World world) {
try {
return getCraftClass("CraftWorld").getMethod("getHandle").invoke(world);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static WrappedGameProfile grabProfileAddUUID(String playername) {
try {
Object minecraftServer = getNmsMethod("MinecraftServer", "getServer").invoke(null);
for (Method method : getNmsClass("MinecraftServer").getMethods()) {
if (method.getReturnType().getSimpleName().equals("GameProfileRepository")) {
Object profileRepo = method.invoke(minecraftServer);
Object agent = Class.forName("com.mojang.authlib.Agent").getField("MINECRAFT").get(null);
LibsProfileLookupCaller callback = new LibsProfileLookupCaller();
profileRepo
.getClass()
.getMethod("findProfilesByNames", String[].class, agent.getClass(),
Class.forName("com.mojang.authlib.ProfileLookupCallback"))
.invoke(profileRepo, new String[] { playername }, agent, callback);
if (callback.getGameProfile() != null) {
return callback.getGameProfile();
}
return getGameProfile(null, playername);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static boolean isForge() {
return isForge;
}
private static String methodSignaturePart(Class<?> param) {
if (param.isArray()) {
return "[" + methodSignaturePart(param.getComponentType());
} else if (param.isPrimitive()) {
return primitiveTypes.get(param);
} else {
return "L" + param.getName().replaceAll("\\.", "/") + ";";
}
}
public static void removePlayer(Player player) {
}
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);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void setBoundingBox(Entity entity, FakeBoundingBox newBox) {
try {
Location loc = entity.getLocation();
Object boundingBox = boundingBoxConstructor.newInstance(loc.getX() - newBox.getX(), loc.getY() - newBox.getY(),
loc.getZ() - newBox.getZ(), loc.getX() + newBox.getX(), loc.getY() + newBox.getY(), loc.getZ() + newBox.getZ());
setBoundingBoxMethod.invoke(getNmsEntity(entity), boundingBox);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

View File

@@ -0,0 +1,58 @@
package me.libraryaddict.disguise.utilities;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Pattern;
public class UpdateChecker {
private String latestVersion;
private boolean checkHigher(String currentVersion, String newVersion) {
String current = toReadable(currentVersion);
String newVers = toReadable(newVersion);
return current.compareTo(newVers) < 0;
}
public void checkUpdate(String currentVersion) {
String version = getSpigotVersion();
if (version != null) {
if (checkHigher(currentVersion, version)) {
latestVersion = version;
}
}
}
public String getLatestVersion() {
return latestVersion;
}
/**
* Asks spigot for the version
*/
private String getSpigotVersion() {
try {
HttpURLConnection con = (HttpURLConnection) new URL("http://www.spigotmc.org/api/general.php").openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.getOutputStream().write(
("key=98BE0FE67F88AB82B4C197FAF1DC3B69206EFDCC4D3B80FC83A00037510B99B4&resource=81").getBytes("UTF-8"));
String version = new BufferedReader(new InputStreamReader(con.getInputStream())).readLine();
if (version.length() <= 7) {
return version;
}
} catch (Exception ex) {
System.out.print("[LibsDisguises] Failed to check for a update on spigot. Now checking bukkit..");
}
return null;
}
private String toReadable(String version) {
String[] split = Pattern.compile(".", Pattern.LITERAL).split(version.replace("v", ""));
version = "";
for (String s : split)
version += String.format("%4s", s);
return version;
}
}

View File

@@ -0,0 +1,124 @@
# Shall I notify people of a LibsDisguises update?
NotifyUpdate: true
# Whats the permission to get the notification?
Permission: 'libsdisguises.update'
# Whats the max size allowed for command disguiseradius
DisguiseRadiusMax: 50
# Whats the max size allowed for command undisguiseradius
UndisguiseRadiusMax: 50
# Shall the players view their disguises?
# Best used when viewing yourself in 3rd person
ViewSelfDisguises: false
# Shall I disguise the sounds?
# This turns your damage sound into a MOOOO
DisguiseSounds: true
# Shall the disguised hear their disguise sounds or their damage sounds.
# I disable this as it can be a little confusing when not used with self disguises
HearSelfDisguise: false
# Shall I send the velocity packets? I REALLY recommend you don't disable.
# This is the only thing allowing the mobs to fly without glitching out.
SendVelocity: true
# For self disguises, they need to have the armor and the held item removed
# Else they see floating armor, floating held items.
# This turns the items invisible in the disguised players inventory. It does not actually remove them!
RemoveArmor: true
RemoveHeldItem: false
# If you set a disguise to burning, it will no longer be able to be shown as sneaking or invisible.
# Set this to true if you want the disguise to get the animations of the disguised entity. Such as invisible, on fire, sprinting, sneaking, blocking
# This is only valid if you set a animation on the disguise itself. Because the entitys animations are applied otherwise.
AddEntityAnimations: true
# When a sheep or wolf is right clicked with dye. The client automatically assumes it was successful and displays the sheeps wool or the wolfs collar as dyed.
# This is a option that either prevents that happening, or it changes their color officially in the plugin so that everyone sees it changed.
# Its currently set to false which means that the color is not changed and will refresh itself to the player.
# Please note that this will not remove the dye from their hands. This also does not check if the disguised entity is actually a sheep/wolf and wants a say in its color.
DyeableSheep: false
DyeableWolf: false
# This is only called into action when the disguise is constructed using the commands.
# And when the disguise supports that. This will not be used at all for plugins constructing the disguises for instance.
# Such as prophunt. Its also false because its kind of a retarded feature.
# This is pretty simple. It shows the players displayname (Name as it appears in chat) above their head.
# This also overrides any custom name they have set in their disguise options.
ShowNamesAboveDisguises: false
# This supports the above option.
# If this is true, then the name shown above the head appears regardless of if you are looking at the disguise directly or not.
NameAboveHeadAlwaysVisible: true
# This modifys the bounding box, This is stuff like can a arrow hit them.
# If you turn this to true, arrows will act like they hit the disguise in the right place!
# So someone disguised as a enderdragon will easily get shot down by arrows!
# This WILL conflict with NoCheatPlus. Other plugins may also get problems.
# This shouldn't really be enabled for players as it also interferes with their movement because the server thinks the player is larger than he really is.
# That makes the player unable to approach this building because the server thinks he is trying to glitch inside blocks.
ModifyBoundingBox: false
# This prevents disguised players from being targeted by monsters.
# This doesn't prevent their targeting you if already targeting when disguised
# They will just ignore you unless provoked.
MonstersIgnoreDisguises: false
# Sigh. People are going to want this.
# So lets make your disguise blown if you are attacked..
# Works only for disguised players when attacked by a entity (arrow, monster. etc)
# This will blow all disguises he has on him
BlowDisguises: false
BlownDisguiseMessage: '&cYour disguise was blown!'
# A option to choose how many seconds a DisguiseEntity command is valid for people to right click a entity to disguise it before expiring
DisguiseEntityExpire: 10
# Another option to choose the same thing for DisguiseClone command
DisguiseCloneExpire: 10
# Max disguises to store at a time with the DisguiseClone command
DisguiseCloneSize: 3
# This I don't really recommend turning on as it can make a memory leak..
# 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
# 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.
# Else it will be 1/20 of the boss bar when he is full health.
# Setting this in LivingWatcher overrides both values.
MaxHealthDeterminedByEntity: true
# This here is a option to turn off misc disguises.
# This means you can not have a living entity disguise as a non-living entity.
# This disables the Attributes packet, Non-living entities can still disguise as other non-living
# This means that the above option will not work as it uses the attribute packet.
MiscDisguisesForLiving: true
# Turn this to true to have players undisguised when switching worlds
UndisguiseOnWorldChange: false
# 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

View File

@@ -0,0 +1,79 @@
name: LibsDisguises
main: me.libraryaddict.disguise.LibsDisguises
version: 8.3 Unofficial
author: libraryaddict
authors: [Byteflux, Navid K.]
depend: [ProtocolLib]
commands:
libsdisguises:
permission: libsdisguises.seecmd.libsdisguises
disguise:
aliases: [d, dis]
permission: libsdisguises.seecmd.disguise
disguiseentity:
aliases: [dentity, disentity]
permission: libsdisguises.seecmd.disguiseentity
disguisehelp:
aliases: [dhelp, dishelp]
permission: libsdisguises.seecmd.disguisehelp
disguiseplayer:
aliases: [dplayer, displayer]
permission: libsdisguises.seecmd.disguiseplayer
disguiseradius:
aliases: [disradius, dradius]
permission: libsdisguises.seecmd.disguiseradius
undisguise:
aliases: [u, und, undis]
permission: libsdisguises.seecmd.undisguise
undisguiseentity:
aliases: [undisentity, undentity]
permission: libsdisguises.seecmd.undisguiseentity
undisguiseplayer:
aliases: [undisplayer, undplayer]
permission: libsdisguises.seecmd.undisguiseplayer
undisguiseradius:
aliases: [undisradius, undradius]
permission: libsdisguises.seecmd.undisguiseradius
disguiseclone:
aliases: [disguisec, disc, disclone, dclone, clonedisguise, clonedis, cdisguise, cdis]
permission: libsdisguises.seecmd.disguiseclone
permissions:
libsdisguises.seecmd:
description: See all commands in tab-completion
default: true
children:
libsdisguises.seecmd.libsdisguises: true
libsdisguises.seecmd.disguise: true
libsdisguises.seecmd.disguiseentity: true
libsdisguises.seecmd.disguisehelp: true
libsdisguises.seecmd.disguiseplayer: true
libsdisguises.seecmd.disguiseradius: true
libsdisguises.seecmd.undisguise: true
libsdisguises.seecmd.undisguiseentity: true
libsdisguises.seecmd.undisguiseplayer: true
libsdisguises.seecmd.undisguiseradius: true
libsdisguises.seecmd.disguiseclone: true
libsdisguises.seecmd.libsdisguises:
description: See the /libsdisguises command in tab-completion
libsdisguises.seecmd.disguise:
description: See the /disguise command in tab-completion
libsdisguises.seecmd.disguiseentity:
description: See the /disguiseentity command in tab-completion
libsdisguises.seecmd.disguisehelp:
description: See the /disguisehelp command in tab-completion
libsdisguises.seecmd.disguiseplayer:
description: See the /disguiseplayer command in tab-completion
libsdisguises.seecmd.disguiseradius:
description: See the /disguiseradius command in tab-completion
libsdisguises.seecmd.undisguise:
description: See the /undisguise command in tab-completion
libsdisguises.seecmd.undisguiseentity:
description: See the /undisguiseentity command in tab-completion
libsdisguises.seecmd.undisguiseplayer:
description: See the /undisguiseplayer command in tab-completion
libsdisguises.seecmd.undisguiseradius:
description: See the /undisguiseradius command in tab-completion
libsdisguises.seecmd.disguiseclone:
description: See the /disguiseclone command in tab-completion