Update disguises to use EntityEquipment, makes life easier

Update ItemInHand calls to ItemInMainHand and OffHand
Still not ready for use yet, disguises do not work
This commit is contained in:
NavidK0
2016-03-05 23:14:19 -05:00
parent a94d583f0b
commit cf1b15942c
7 changed files with 247 additions and 102 deletions

View File

@@ -6,6 +6,9 @@ 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.WrappedDataWatcher.Registry;
import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer;
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import me.libraryaddict.disguise.DisguiseAPI;
import me.libraryaddict.disguise.DisguiseConfig;
@@ -25,14 +28,21 @@ import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Zombie;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;
import org.bukkit.scoreboard.Team.Option;
import org.bukkit.scoreboard.Team.OptionStatus;
import org.bukkit.util.Vector;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -265,7 +275,7 @@ public class DisguiseUtilities {
}
public static void doBoundingBox(TargetedDisguise disguise) {
// TODO Slimes
//TODO: Slimes
Entity entity = disguise.getEntity();
if (entity != null) {
if (isDisguiseInUse(disguise)) {
@@ -772,6 +782,16 @@ public class DisguiseUtilities {
} catch (Exception ex) {
ex.printStackTrace(System.out);
}
//Code to stop player pushing in 1.9
//TODO: Check validity
Scoreboard scoreboard = player.getScoreboard();
Team t;
if ((t = scoreboard.getTeam("LDPushing")) != null) {
t.setOption(Option.COLLISION_RULE, OptionStatus.ALWAYS);
t.removeEntry(player.getName());
t.unregister();
}
//Finish up
// Remove the fake entity ID from the disguise bin
selfDisguised.remove(player.getUniqueId());
// Get the entity tracker
@@ -973,6 +993,18 @@ public class DisguiseUtilities {
if (!disguise.isSelfDisguiseVisible() || !PacketsManager.isViewDisguisesListenerEnabled() || player.getVehicle() != null) {
return;
}
//Code to stop player pushing in 1.9
//TODO: Check validity
Scoreboard scoreboard = player.getScoreboard();
Team t;
if ((t = scoreboard.getTeam("LDPushing")) != null) {
t.setOption(Option.COLLISION_RULE, OptionStatus.NEVER);
} else {
t = scoreboard.registerNewTeam("LDPushing");
t.setOption(Option.COLLISION_RULE, OptionStatus.NEVER);
t.addEntry(player.getName());
}
//Finish up
selfDisguised.add(player.getUniqueId());
sendSelfDisguise(player, (TargetedDisguise) disguise);
if (disguise.isHidingArmorFromSelf() || disguise.isHidingHeldItemFromSelf()) {
@@ -981,4 +1013,5 @@ public class DisguiseUtilities {
}
}
}
}

View File

@@ -43,6 +43,7 @@ import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Zombie;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.util.Vector;
@@ -124,25 +125,18 @@ public class PacketsManager {
// This sends the armor packets so that the player isn't naked.
// Please note it only sends the packets that wouldn't be sent normally
if (DisguiseConfig.isEquipmentPacketsEnabled()) {
for (int nmsSlot = 0; nmsSlot < 5; nmsSlot++) {
int armorSlot = nmsSlot - 1;
if (armorSlot < 0)
armorSlot = 4;
ItemStack itemstack = disguise.getWatcher().getItemStack(armorSlot);
for (EquipmentSlot slot : EquipmentSlot.values()) {
ItemStack itemstack = disguise.getWatcher().getItemStack(slot);
if (itemstack != null && itemstack.getTypeId() != 0) {
ItemStack item = null;
if (disguisedEntity instanceof LivingEntity) {
if (nmsSlot == 0) {
item = ((LivingEntity) disguisedEntity).getEquipment().getItemInHand();
} else {
item = ((LivingEntity) disguisedEntity).getEquipment().getArmorContents()[armorSlot];
}
item = ReflectionManager.getEquipment(slot, disguisedEntity);
}
if (item == null || item.getType() == Material.AIR) {
PacketContainer packet = new PacketContainer(Server.ENTITY_EQUIPMENT);
StructureModifier<Object> mods = packet.getModifier();
mods.write(0, disguisedEntity.getEntityId());
mods.write(1, nmsSlot);
mods.write(1, ReflectionManager.createEnumItemSlot(slot));
mods.write(2, ReflectionManager.getNmsItem(itemstack));
packets.add(packet);
}
@@ -281,7 +275,6 @@ public class PacketsManager {
delayedPackets = new PacketContainer[]{delayedPacket};
} else if (disguise.getType().isMob() || disguise.getType() == DisguiseType.ARMOR_STAND) {
DisguiseValues values = DisguiseValues.getDisguiseValues(disguise.getType());
Vector vec = disguisedEntity.getVelocity();
spawnPackets[0] = new PacketContainer(Server.SPAWN_ENTITY_LIVING);
@@ -1404,16 +1397,14 @@ public class PacketsManager {
}
}
} else if (sentPacket.getType() == Server.ENTITY_EQUIPMENT) {
int slot = (Integer) packets[0].getModifier().read(1) - 1;
if (slot < 0)
slot = 4;
org.bukkit.inventory.ItemStack itemstack = disguise.getWatcher().getItemStack(slot);
if (itemstack != null) {
EquipmentSlot slot = ReflectionManager.createEquipmentSlot(packets[0].getModifier().read(1));
org.bukkit.inventory.ItemStack itemStack = disguise.getWatcher().getItemStack(slot);
if (itemStack != null) {
packets[0] = packets[0].shallowClone();
packets[0].getModifier().write(2,
(itemstack.getTypeId() == 0 ? null : ReflectionManager.getNmsItem(itemstack)));
packets[0].getModifier().write(2, (itemStack.getTypeId() == 0 ? null : ReflectionManager.getNmsItem(itemStack)));
}
if (disguise.getWatcher().isRightClicking() && slot == 4) {
//TODO: Add left hand here
if (disguise.getWatcher().isRightClicking() && slot == EquipmentSlot.HAND) {
ItemStack heldItem = packets[0].getItemModifier().read(0);
if (heldItem != null && heldItem.getType() != Material.AIR) {
// Convert the datawatcher

View File

@@ -11,7 +11,10 @@ import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
@@ -476,25 +479,6 @@ public class ReflectionManager {
}
}
/**
* This creates a DataWatcherItem usable with WrappedWatchableObject
* @param id
* @param value
* @return
*/
public static Object createDataWatcherItem(int id, Object value) {
if (value == null) return null;
Serializer serializer = Registry.get(value.getClass());
WrappedDataWatcherObject watcherObject = new WrappedDataWatcherObject(id, serializer);
Constructor construct = ReflectionManager.getNmsConstructor("DataWatcher$Item", getNmsClass("DataWatcherObject"), Object.class);
try {
return construct.newInstance(watcherObject.getHandle(), value);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static void setBoundingBox(Entity entity, FakeBoundingBox newBox) {
try {
Location loc = entity.getLocation();
@@ -506,4 +490,112 @@ public class ReflectionManager {
}
}
/**
* Creates the NMS object EnumItemSlot from an EquipmentSlot.
* @param slot
* @return null if the equipment slot is null
*/
public static Enum createEnumItemSlot(EquipmentSlot slot) {
Class<?> clazz = getNmsClass("EnumItemSlot");
Object[] enums = clazz != null ? clazz.getEnumConstants() : null;
if (enums == null) return null;
switch (slot) {
case HAND:
return (Enum) enums[0];
case OFF_HAND:
return (Enum) enums[1];
case FEET:
return (Enum) enums[2];
case LEGS:
return (Enum) enums[3];
case CHEST:
return (Enum) enums[4];
case HEAD:
return (Enum) enums[5];
default:
return null;
}
}
/**
* Creates the Bukkit object EquipmentSlot from an EnumItemSlot object.
* @return null if the object isn't an nms EnumItemSlot
*/
public static EquipmentSlot createEquipmentSlot(Object enumItemSlot) {
try {
Enum nmsSlot = (Enum) enumItemSlot;
switch (nmsSlot.name()) {
case "MAINHAND":
return EquipmentSlot.HAND;
case "OFFHAND":
return EquipmentSlot.OFF_HAND;
case "FEET":
return EquipmentSlot.FEET;
case "LEGS":
return EquipmentSlot.LEGS;
case "CHEST":
return EquipmentSlot.CHEST;
case "HEAD":
return EquipmentSlot.HAND;
}
} catch (Exception e) {
return null;
}
return null;
}
/**
* Gets equipment from this entity based on the slot given.
* @param slot
* @return null if the disguisedEntity is not an instance of a living entity
*/
public static ItemStack getEquipment(EquipmentSlot slot, Entity disguisedEntity) {
if (!(disguisedEntity instanceof LivingEntity)) return null;
switch (slot) {
case HAND:
return ((LivingEntity) disguisedEntity).getEquipment().getItemInMainHand();
case OFF_HAND:
return ((LivingEntity) disguisedEntity).getEquipment().getItemInOffHand();
case FEET:
return ((LivingEntity) disguisedEntity).getEquipment().getBoots();
case LEGS:
return ((LivingEntity) disguisedEntity).getEquipment().getLeggings();
case CHEST:
return ((LivingEntity) disguisedEntity).getEquipment().getChestplate();
case HEAD:
return ((LivingEntity) disguisedEntity).getEquipment().getHelmet();
default:
return null;
}
}
/**
* This creates a DataWatcherItem usable with WrappedWatchableObject
* @param id
* @param value
* @return
*/
public static Object createDataWatcherItem(int id, Object value) {
if (value == null) return null;
Serializer serializer = Registry.get(value.getClass());
WrappedDataWatcherObject watcherObject = new WrappedDataWatcherObject(id, serializer);
Constructor construct = getNmsConstructor("DataWatcher$Item", getNmsClass("DataWatcherObject"), Object.class);
try {
return construct.newInstance(watcherObject.getHandle(), value);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
public static EntityEquipment createEntityEquipment(Entity entity) {
if (!(entity instanceof LivingEntity)) return null;
Constructor construct = getNmsConstructor("CraftEntityEquipment", getNmsClass("CraftLivingEntity"));
try {
return (EntityEquipment) construct.newInstance((LivingEntity) entity);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | ClassCastException e) {
e.printStackTrace();
}
return null;
}
}