- Changed entire project to gradle
- Updated for 1.8.3 - No more errors, woo
This commit is contained in:
336
src/main/java/me/libraryaddict/disguise/DisguiseAPI.java
Normal file
336
src/main/java/me/libraryaddict/disguise/DisguiseAPI.java
Normal 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() {
|
||||
}
|
||||
}
|
426
src/main/java/me/libraryaddict/disguise/DisguiseConfig.java
Normal file
426
src/main/java/me/libraryaddict/disguise/DisguiseConfig.java
Normal 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() {
|
||||
}
|
||||
}
|
377
src/main/java/me/libraryaddict/disguise/DisguiseListener.java
Normal file
377
src/main/java/me/libraryaddict/disguise/DisguiseListener.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
330
src/main/java/me/libraryaddict/disguise/LibsDisguises.java
Normal file
330
src/main/java/me/libraryaddict/disguise/LibsDisguises.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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 + ")");
|
||||
}
|
||||
}
|
@@ -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>");
|
||||
}
|
||||
}
|
@@ -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>");
|
||||
}
|
||||
|
||||
}
|
@@ -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, "_");
|
||||
}
|
||||
}
|
@@ -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>");
|
||||
}
|
||||
}
|
@@ -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");
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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, " ");
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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));
|
||||
}
|
||||
|
||||
}
|
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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))));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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());
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
package me.libraryaddict.disguise.utilities;
|
||||
|
||||
import com.comphenix.protocol.wrappers.WrappedGameProfile;
|
||||
|
||||
public interface LibsProfileLookup {
|
||||
public void onLookup(WrappedGameProfile gameProfile);
|
||||
|
||||
}
|
@@ -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
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
124
src/main/resources/config.yml
Normal file
124
src/main/resources/config.yml
Normal 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
|
79
src/main/resources/plugin.yml
Normal file
79
src/main/resources/plugin.yml
Normal 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
|
Reference in New Issue
Block a user