diff --git a/config.yml b/config.yml index 9427d2e4..18561af1 100644 --- a/config.yml +++ b/config.yml @@ -40,4 +40,8 @@ RemoveUnusedDisguises: true 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 \ No newline at end of file +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! +ModifyBoundingBox: true \ No newline at end of file diff --git a/src/me/libraryaddict/disguise/DisguiseAPI.java b/src/me/libraryaddict/disguise/DisguiseAPI.java index ba9a2b3e..56d7c1d4 100644 --- a/src/me/libraryaddict/disguise/DisguiseAPI.java +++ b/src/me/libraryaddict/disguise/DisguiseAPI.java @@ -22,6 +22,7 @@ public class DisguiseAPI { private static boolean hidingArmor; private static boolean hidingHeldItem; private static boolean isEntityAnimationsAdded; + private static boolean modifyBoundingBox; private static boolean removeUnseenDisguises; private static boolean sendVelocity; private static boolean showNameAboveHead; @@ -191,6 +192,10 @@ public class DisguiseAPI { return hidingHeldItem; } + public static boolean isModifyBoundingBox() { + return modifyBoundingBox; + } + public static boolean isNameAboveHeadAlwaysVisible() { return showNameAboveHeadAlwaysVisible; } @@ -261,6 +266,10 @@ public class DisguiseAPI { } } + public static void setModifyBoundingBox(boolean modifyBounding) { + modifyBoundingBox = modifyBounding; + } + public static void setNameAboveHeadAlwaysVisible(boolean alwaysVisible) { showNameAboveHeadAlwaysVisible = alwaysVisible; } diff --git a/src/me/libraryaddict/disguise/LibsDisguises.java b/src/me/libraryaddict/disguise/LibsDisguises.java index 9039e7ce..c8fa56e8 100644 --- a/src/me/libraryaddict/disguise/LibsDisguises.java +++ b/src/me/libraryaddict/disguise/LibsDisguises.java @@ -67,6 +67,7 @@ public class LibsDisguises extends JavaPlugin { DisguiseAPI.setAddEntityAnimations(getConfig().getBoolean("AddEntityAnimations")); DisguiseAPI.setNameOfPlayerShownAboveDisguise(getConfig().getBoolean("ShowNamesAboveDisguises")); DisguiseAPI.setNameAboveHeadAlwaysVisible(getConfig().getBoolean("NameAboveHeadAlwaysVisible")); + DisguiseAPI.setModifyBoundingBox(getConfig().getBoolean("ModifyBoundingBox")); 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 object. diff --git a/src/me/libraryaddict/disguise/disguisetypes/Disguise.java b/src/me/libraryaddict/disguise/disguisetypes/Disguise.java index b24baead..b16b25ee 100644 --- a/src/me/libraryaddict/disguise/disguisetypes/Disguise.java +++ b/src/me/libraryaddict/disguise/disguisetypes/Disguise.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import me.libraryaddict.disguise.DisguiseAPI; +import me.libraryaddict.disguise.disguisetypes.TargetedDisguise.TargetType; import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.HorseWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.ZombieWatcher; @@ -35,6 +36,7 @@ public abstract class Disguise { private boolean hearSelfDisguise = DisguiseAPI.isSelfDisguisesSoundsReplaced(); private boolean hideArmorFromSelf = DisguiseAPI.isHidingArmorFromSelf(); private boolean hideHeldItemFromSelf = DisguiseAPI.isHidingHeldItemFromSelf(); + private boolean modifyBoundingBox = DisguiseAPI.isModifyBoundingBox(); private boolean replaceSounds = DisguiseAPI.isSoundEnabled(); private BukkitRunnable velocityRunnable; private boolean velocitySent = DisguiseAPI.isVelocitySent(); @@ -56,8 +58,10 @@ public abstract class Disguise { 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"); + 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; @@ -179,7 +183,7 @@ public abstract class Disguise { final boolean sendMovementPacket = movement; final double vectorY = fallSpeed; final boolean alwaysSendVelocity = alwaysSend; - final TargetedDisguise disguise=(TargetedDisguise) this; + final TargetedDisguise disguise = (TargetedDisguise) this; // A scheduler to clean up any unused disguises. velocityRunnable = new BukkitRunnable() { private int i = 0; @@ -344,6 +348,10 @@ public abstract class Disguise { return false; } + public boolean isModifyBoundingBox() { + return modifyBoundingBox; + } + public boolean isPlayerDisguise() { return false; } @@ -439,6 +447,19 @@ public abstract class Disguise { } } + public void 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); + } + } + } + public void setReplaceSounds(boolean areSoundsReplaced) { replaceSounds = areSoundsReplaced; } diff --git a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index 41876296..1e1ea68d 100644 --- a/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -11,14 +11,19 @@ import java.util.List; import me.libraryaddict.disguise.DisguiseAPI; import me.libraryaddict.disguise.LibsDisguises; import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.TargetedDisguise; +import me.libraryaddict.disguise.disguisetypes.watchers.AgeableWatcher; +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.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.util.Vector; @@ -38,13 +43,14 @@ public class DisguiseUtilities { private static HashMap> targetedDisguises = new HashMap>(); public static void addDisguise(int entityId, TargetedDisguise disguise) { - // TODO Make sure that the disguised entity doesn't have the player looking at other girls - // ^ Done? if (!getDisguises().containsKey(entityId)) { getDisguises().put(entityId, new HashSet()); } getDisguises().get(entityId).add(disguise); checkConflicts(disguise, null); + if (disguise.getDisguiseTarget() == TargetType.SHOW_TO_EVERYONE_BUT_THESE_PLAYERS && disguise.isModifyBoundingBox()) { + doBoundingBox(disguise); + } } /** @@ -126,6 +132,36 @@ public class DisguiseUtilities { } } + public static void doBoundingBox(TargetedDisguise disguise) { + // TODO Slimes + Entity entity = disguise.getEntity(); + if (entity != null) { + if (isDisguiseInUse(disguise)) { + DisguiseValues values = DisguiseValues.getDisguiseValues(disguise.getType()); + FakeBoundingBox fakeBox = values.getAdultBox(); + if (values.getBabyBox() != null) { + if (disguise.getWatcher() instanceof AgeableWatcher + && (((AgeableWatcher) disguise.getWatcher()).isBaby()) + || (disguise.getWatcher() instanceof ZombieWatcher && ((ZombieWatcher) disguise.getWatcher()) + .isBaby())) { + fakeBox = values.getBabyBox(); + } + } + ReflectionManager.setBoundingBox(entity, fakeBox.getX(), fakeBox.getY(), fakeBox.getZ()); + } else { + DisguiseValues values = DisguiseValues.getDisguiseValues(DisguiseType.getType(entity.getType())); + FakeBoundingBox fakeBox = values.getAdultBox(); + if (values.getBabyBox() != null) { + if (entity instanceof Ageable && !(((Ageable) entity).isAdult()) + || (entity instanceof Zombie && ((Zombie) entity).isBaby())) { + fakeBox = values.getBabyBox(); + } + } + ReflectionManager.setBoundingBox(disguise.getEntity(), fakeBox.getX(), fakeBox.getY(), fakeBox.getZ()); + } + } + } + @Deprecated public static TargetedDisguise getDisguise(int entityId) { TargetedDisguise toReturn = null; @@ -275,6 +311,9 @@ public class DisguiseUtilities { 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; diff --git a/src/me/libraryaddict/disguise/utilities/DisguiseValues.java b/src/me/libraryaddict/disguise/utilities/DisguiseValues.java index 34d5b958..8faeb374 100644 --- a/src/me/libraryaddict/disguise/utilities/DisguiseValues.java +++ b/src/me/libraryaddict/disguise/utilities/DisguiseValues.java @@ -43,11 +43,11 @@ public class DisguiseValues { return getDisguiseValues(type).getNmsEntityClass(); } + private FakeBoundingBox adultBox; + private FakeBoundingBox babyBox; private int enumEntitySize; private HashMap metaValues = new HashMap(); private Class nmsEntityClass; - private FakeBoundingBox adultBox; - private FakeBoundingBox babyBox; public DisguiseValues(DisguiseType type, Class classType, int entitySize) { values.put(type, this); @@ -55,22 +55,14 @@ public class DisguiseValues { nmsEntityClass = classType; } - public FakeBoundingBox getBabyBox() { - return babyBox; - } - - public void setAdultBox(FakeBoundingBox newBox) { - adultBox = newBox; - } - - public void setBabyBox(FakeBoundingBox newBox) { - babyBox = newBox; - } - public FakeBoundingBox getAdultBox() { return adultBox; } + public FakeBoundingBox getBabyBox() { + return babyBox; + } + public int getEntitySize(double paramDouble) { double d = paramDouble - (((int) Math.floor(paramDouble)) + 0.5D); @@ -123,6 +115,14 @@ public class DisguiseValues { return nmsEntityClass; } + public void setAdultBox(FakeBoundingBox newBox) { + adultBox = newBox; + } + + public void setBabyBox(FakeBoundingBox newBox) { + babyBox = newBox; + } + public void setMetaValue(int no, Object value) { metaValues.put(no, value); } diff --git a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java index e0ebb16d..6a6b0611 100644 --- a/src/me/libraryaddict/disguise/utilities/ReflectionManager.java +++ b/src/me/libraryaddict/disguise/utilities/ReflectionManager.java @@ -55,6 +55,35 @@ public class ReflectionManager { } } + 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 = getNmsClass("MinecraftServer").getMethod("getServer").invoke(null); + Object playerinteractmanager = getNmsClass("PlayerInteractManager").getConstructor(getNmsClass("World")) + .newInstance(world); + if (isAfter17()) { + Object gameProfile = getGameProfile("LibsDisguises"); + entityObject = entityClass.getConstructor(getNmsClass("MinecraftServer"), getNmsClass("WorldServer"), + gameProfile.getClass(), playerinteractmanager.getClass()).newInstance(minecraftServer, world, + gameProfile, playerinteractmanager); + } else { + entityObject = entityClass.getConstructor(getNmsClass("MinecraftServer"), getNmsClass("World"), String.class, + playerinteractmanager.getClass()).newInstance(minecraftServer, world, "LibsDisguises", + playerinteractmanager); + } + } else { + entityObject = entityClass.getConstructor(getNmsClass("World")).newInstance(world); + } + return entityObject; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + public static FakeBoundingBox getBoundingBox(Entity entity) { try { Object boundingBox = getNmsClass("Entity").getField("boundingBox").get(getNmsEntity(entity)); @@ -94,72 +123,6 @@ public class ReflectionManager { return null; } - public static void setBoundingBox(Entity entity, double newX, double newY, double newZ) { - try { - Object boundingBox = getNmsClass("Entity").getField("boundingBox").get(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: - field.setDouble(boundingBox, x); - break; - case 5: - field.setDouble(boundingBox, y); - break; - case 6: - field.setDouble(boundingBox, z); - break; - default: - throw new Exception("Error while setting the bounding box, more doubles than I thought??"); - } - } - } - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - 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 = getNmsClass("MinecraftServer").getMethod("getServer").invoke(null); - Object playerinteractmanager = getNmsClass("PlayerInteractManager").getConstructor(getNmsClass("World")) - .newInstance(world); - if (isAfter17()) { - Object gameProfile = getGameProfile("LibsDisguises"); - entityObject = entityClass.getConstructor(getNmsClass("MinecraftServer"), getNmsClass("WorldServer"), - gameProfile.getClass(), playerinteractmanager.getClass()).newInstance(minecraftServer, world, - gameProfile, playerinteractmanager); - } else { - entityObject = entityClass.getConstructor(getNmsClass("MinecraftServer"), getNmsClass("World"), String.class, - playerinteractmanager.getClass()).newInstance(minecraftServer, world, "LibsDisguises", - playerinteractmanager); - } - } else { - entityObject = entityClass.getConstructor(getNmsClass("World")).newInstance(world); - } - return entityObject; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - public static Entity getBukkitEntity(Object nmsEntity) { try { Entity bukkitEntity = (Entity) ReflectionManager.getNmsClass("Entity").getMethod("getBukkitEntity").invoke(nmsEntity); @@ -272,4 +235,41 @@ public class ReflectionManager { return after17; } + public static void setBoundingBox(Entity entity, double newX, double newY, double newZ) { + try { + Object boundingBox = getNmsClass("Entity").getField("boundingBox").get(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: + field.setDouble(boundingBox, x); + break; + case 5: + field.setDouble(boundingBox, y); + break; + case 6: + field.setDouble(boundingBox, z); + break; + default: + throw new Exception("Error while setting the bounding box, more doubles than I thought??"); + } + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }