Added ability to set the max health of a disguise using attributes
This commit is contained in:
		| @@ -64,6 +64,12 @@ 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. | ||||
| @@ -91,6 +97,7 @@ PacketsEnabled: | ||||
|   # 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 | ||||
|   Movement: true | ||||
|   | ||||
							
								
								
									
										15
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -75,16 +75,21 @@ | ||||
| 	</repositories> | ||||
|  | ||||
| 	<dependencies> | ||||
| 		<dependency> | ||||
| 			<groupId>org.bukkit</groupId> | ||||
| 			<artifactId>craftbukkit</artifactId> | ||||
| 			<version>1.7.8-R0.1-SNAPSHOT</version> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>com.comphenix.protocol</groupId> | ||||
| 			<artifactId>ProtocolLib</artifactId> | ||||
| 			<version>3.1.0</version> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.spigotmc</groupId> | ||||
| 			<artifactId>spigot-api</artifactId> | ||||
| 			<version>1.7.8-R0.1-SNAPSHOT</version> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.spigotmc</groupId> | ||||
| 			<artifactId>spigot</artifactId> | ||||
| 			<version>1.7.8-R0.1-SNAPSHOT</version> | ||||
| 		</dependency> | ||||
| 	</dependencies> | ||||
|  | ||||
| 	<distributionManagement> | ||||
|   | ||||
| @@ -17,6 +17,7 @@ public class DisguiseConfig { | ||||
|     private static boolean keepDisguiseEntityDespawn; | ||||
|     private static boolean keepDisguisePlayerDeath; | ||||
|     private static boolean keepDisguisePlayerLogout; | ||||
|     private static boolean maxHealthIsDisguisedEntity; | ||||
|     private static boolean miscDisguisesForLivingEnabled; | ||||
|     private static boolean modifyBoundingBox; | ||||
|     private static boolean movementEnabled; | ||||
| @@ -87,6 +88,10 @@ public class DisguiseConfig { | ||||
|         return keepDisguisePlayerLogout; | ||||
|     } | ||||
|  | ||||
|     public static boolean isMaxHealthDeterminedByDisguisedEntity() { | ||||
|         return maxHealthIsDisguisedEntity; | ||||
|     } | ||||
|  | ||||
|     public static boolean isMetadataPacketsEnabled() { | ||||
|         return sendsEntityMetadata; | ||||
|     } | ||||
| @@ -240,6 +245,10 @@ public class DisguiseConfig { | ||||
|         keepDisguisePlayerLogout = keepDisguise; | ||||
|     } | ||||
|  | ||||
|     public static void setMaxHealthDeterminedByDisguisedEntity(boolean isDetermined) { | ||||
|         maxHealthIsDisguisedEntity = isDetermined; | ||||
|     } | ||||
|  | ||||
|     public static void setMetadataPacketsEnabled(boolean enabled) { | ||||
|         sendsEntityMetadata = enabled; | ||||
|     } | ||||
|   | ||||
| @@ -27,6 +27,7 @@ import org.bukkit.configuration.ConfigurationSection; | ||||
| import org.bukkit.configuration.file.FileConfiguration; | ||||
| import org.bukkit.configuration.file.YamlConfiguration; | ||||
| import org.bukkit.entity.Ageable; | ||||
| import org.bukkit.entity.Damageable; | ||||
| import org.bukkit.entity.Entity; | ||||
| import org.bukkit.entity.LivingEntity; | ||||
| import org.bukkit.entity.Zombie; | ||||
| @@ -107,6 +108,7 @@ public class LibsDisguises extends JavaPlugin { | ||||
|         DisguiseConfig.setEntityStatusPacketsEnabled(getConfig().getBoolean("PacketsEnabled.EntityStatus")); | ||||
|         DisguiseConfig.setCollectPacketsEnabled(getConfig().getBoolean("PacketsEnabled.Collect")); | ||||
|         DisguiseConfig.setMetadataPacketsEnabled(getConfig().getBoolean("PacketsEnabled.Metadata")); | ||||
|         DisguiseConfig.setMaxHealthDeterminedByDisguisedEntity(getConfig().getBoolean("MaxHealthDeterminedByEntity")); | ||||
|         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. | ||||
| @@ -234,7 +236,8 @@ public class LibsDisguises extends JavaPlugin { | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|                 DisguiseValues disguiseValues = new DisguiseValues(disguiseType, nmsEntity.getClass(), entitySize); | ||||
|                 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.. | ||||
|   | ||||
| @@ -31,6 +31,8 @@ public class LivingWatcher extends FlagWatcher { | ||||
|             ex.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|     private double maxHealth; | ||||
|     private boolean maxHealthSet; | ||||
|     private HashSet<Integer> potionEffects = new HashSet<Integer>(); | ||||
|  | ||||
|     public LivingWatcher(Disguise disguise) { | ||||
| @@ -48,6 +50,8 @@ public class LivingWatcher extends FlagWatcher { | ||||
|     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; | ||||
|     } | ||||
|  | ||||
| @@ -59,6 +63,10 @@ public class LivingWatcher extends FlagWatcher { | ||||
|         return (Float) getValue(6, 0F); | ||||
|     } | ||||
|  | ||||
|     public double getMaxHealth() { | ||||
|         return maxHealth; | ||||
|     } | ||||
|  | ||||
|     public boolean getPotionParticlesRemoved() { | ||||
|         return (Byte) getValue(8, (byte) 0) == 1; | ||||
|     } | ||||
| @@ -105,6 +113,10 @@ public class LivingWatcher extends FlagWatcher { | ||||
|         return (Byte) getValue(11, (byte) 0) == 1; | ||||
|     } | ||||
|  | ||||
|     public boolean isMaxHealthSet() { | ||||
|         return maxHealthSet; | ||||
|     } | ||||
|  | ||||
|     public void removePotionEffect(PotionEffectType type) { | ||||
|         if (potionEffects.contains(type.getId())) { | ||||
|             potionEffects.remove(type.getId()); | ||||
| @@ -139,4 +151,10 @@ public class LivingWatcher extends FlagWatcher { | ||||
|         sendData(6); | ||||
|     } | ||||
|  | ||||
|     public void setMaxHealth(double newHealth) { | ||||
|         this.maxHealth = newHealth; | ||||
|         maxHealthSet = true; | ||||
|         // TODO Send packet | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -47,13 +47,15 @@ public class DisguiseValues { | ||||
|     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) { | ||||
|     public DisguiseValues(DisguiseType type, Class classType, int entitySize, double maxHealth) { | ||||
|         values.put(type, this); | ||||
|         enumEntitySize = entitySize; | ||||
|         nmsEntityClass = classType; | ||||
|         this.maxHealth = maxHealth; | ||||
|     } | ||||
|  | ||||
|     public FakeBoundingBox getAdultBox() { | ||||
| @@ -112,6 +114,10 @@ public class DisguiseValues { | ||||
|         return (int) Math.floor(paramDouble * 32.0D); | ||||
|     } | ||||
|  | ||||
|     public double getMaxHealth() { | ||||
|         return maxHealth; | ||||
|     } | ||||
|  | ||||
|     public HashMap<Integer, Object> getMetaValues() { | ||||
|         return metaValues; | ||||
|     } | ||||
|   | ||||
| @@ -15,6 +15,7 @@ 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.watchers.LivingWatcher; | ||||
| import me.libraryaddict.disguise.disguisetypes.watchers.PlayerWatcher; | ||||
| import me.libraryaddict.disguise.utilities.DisguiseSound.SoundType; | ||||
| import me.libraryaddict.disguise.utilities.ReflectionManager.LibVersion; | ||||
| @@ -43,6 +44,8 @@ import com.comphenix.protocol.events.PacketContainer; | ||||
| import com.comphenix.protocol.events.PacketEvent; | ||||
| import com.comphenix.protocol.events.PacketListener; | ||||
| import com.comphenix.protocol.reflect.StructureModifier; | ||||
| import com.comphenix.protocol.wrappers.WrappedAttribute; | ||||
| import com.comphenix.protocol.wrappers.WrappedAttribute.Builder; | ||||
| import com.comphenix.protocol.wrappers.WrappedDataWatcher; | ||||
| import com.comphenix.protocol.wrappers.WrappedWatchableObject; | ||||
|  | ||||
| @@ -1173,10 +1176,39 @@ public class PacketsManager { | ||||
|             if (disguise != null) { | ||||
|                 packets = new PacketContainer[] { sentPacket }; | ||||
|  | ||||
|                 // If packet is PacketType.Play.Server.UPDATE_ATTRIBUTES | ||||
|                 // This packet sends attributes | ||||
|                 if (sentPacket.getType() == PacketType.Play.Server.UPDATE_ATTRIBUTES) { | ||||
|                     packets = new PacketContainer[0]; | ||||
|                     if (disguise.isMiscDisguise()) { | ||||
|                         packets = new PacketContainer[0]; | ||||
|                     } else { | ||||
|                         List<WrappedAttribute> attributes = new ArrayList<WrappedAttribute>(); | ||||
|                         for (WrappedAttribute attribute : sentPacket.getAttributeCollectionModifier().read(0)) { | ||||
|                             if (attribute.getAttributeKey().equals("generic.maxHealth")) { | ||||
|                                 packets[0] = new PacketContainer(PacketType.Play.Server.UPDATE_ATTRIBUTES); | ||||
|                                 Builder builder; | ||||
|                                 if (((LivingWatcher) disguise.getWatcher()).isMaxHealthSet()) { | ||||
|                                     builder = WrappedAttribute.newBuilder(); | ||||
|                                     builder.attributeKey("generic.maxHealth"); | ||||
|                                     builder.baseValue(((LivingWatcher) disguise.getWatcher()).getMaxHealth()); | ||||
|                                 } else if (DisguiseConfig.isMaxHealthDeterminedByDisguisedEntity()) { | ||||
|                                     builder = WrappedAttribute.newBuilder(attribute); | ||||
|                                 } else { | ||||
|                                     builder = WrappedAttribute.newBuilder(); | ||||
|                                     builder.attributeKey("generic.maxHealth"); | ||||
|                                     builder.baseValue(DisguiseValues.getDisguiseValues(disguise.getType()).getMaxHealth()); | ||||
|                                 } | ||||
|                                 builder.packet(packets[0]); | ||||
|                                 attributes.add(builder.build()); | ||||
|                                 break; | ||||
|                             } | ||||
|                         } | ||||
|                         if (!attributes.isEmpty()) { | ||||
|                             packets[0].getIntegers().write(0, entity.getEntityId()); | ||||
|                             packets[0].getAttributeCollectionModifier().write(0, attributes); | ||||
|                         } else { | ||||
|                             packets = new PacketContainer[0]; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 else if (sentPacket.getType() == PacketType.Play.Server.ATTACH_ENTITY) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user