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

@ -63,7 +63,7 @@ public class DisguiseAPI {
if (doEquipment && entity instanceof LivingEntity) {
EntityEquipment equip = ((LivingEntity) entity).getEquipment();
watcher.setArmor(equip.getArmorContents());
watcher.setItemInHand(equip.getItemInHand());
watcher.setItemInMainHand(equip.getItemInMainHand());
if (disguiseType.getEntityType() == EntityType.HORSE) {
Horse horse = (Horse) entity;
HorseInventory horseInventory = horse.getInventory();

View File

@ -228,8 +228,16 @@ public class LibsDisguises extends JavaPlugin {
for (WrappedWatchableObject watch : watcher.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());
//TODO: Recomment this section when finished
int id = watch.getIndex();
Object val = watch.getValue();
Class<?> valClazz = val != null ? watch.getValue().getClass() : null;
try {
val = val.toString();
} catch (Exception e) {
val = val != null ? val.getClass() : "null";
}
System.out.println("Disguise: " + disguiseType + ", ID: " + id + ", Class: " + (val == null ? "null" : valClazz) + ", Value: " + val);
}
DisguiseSound sound = DisguiseSound.getType(disguiseType.name());
if (sound != null) {

View File

@ -13,6 +13,7 @@ import me.libraryaddict.disguise.utilities.ReflectionManager;
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 java.lang.reflect.InvocationTargetException;
@ -23,35 +24,21 @@ import java.util.List;
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;
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..
* These are the entity values I need to add else it could crash them..
*/
private HashMap<Integer, Object> backupEntityValues = new HashMap<>();
private TargetedDisguise disguise;
private HashMap<Integer, Object> entityValues = new HashMap<>();
private boolean hasDied;
private ItemStack[] items = new ItemStack[5];
public EntityEquipment equipment;
private HashSet<Integer> modifiedEntityAnimations = new HashSet<>();
private List<WrappedWatchableObject> watchableObjects;
public FlagWatcher(Disguise disguise) {
this.disguise = (TargetedDisguise) disguise;
equipment = ReflectionManager.createEntityEquipment(disguise.getEntity());
}
private byte addEntityAnimations(byte originalValue, byte entityValue) {
@ -74,7 +61,7 @@ public class FlagWatcher {
cloned = new FlagWatcher(getDisguise());
}
cloned.entityValues = (HashMap<Integer, Object>) entityValues.clone();
cloned.items = items.clone();
cloned.equipment = ReflectionManager.createEntityEquipment(cloned.getDisguise().getEntity());
cloned.modifiedEntityAnimations = (HashSet<Integer>) modifiedEntityAnimations.clone();
cloned.addEntityAnimations = addEntityAnimations;
return cloned;
@ -160,7 +147,7 @@ public class FlagWatcher {
public ItemStack[] getArmor() {
ItemStack[] armor = new ItemStack[4];
System.arraycopy(items, 0, armor, 0, 4);
System.arraycopy(armor, 0, armor, 0, 4);
return armor;
}
@ -176,16 +163,18 @@ public class FlagWatcher {
return ((byte) getValue(0, (byte) 0) & 1 << byteValue) != 0;
}
public ItemStack getItemInHand() {
return getItemStack(SlotType.HELD_ITEM);
public ItemStack getItemInMainHand() {
if (equipment == null) return null;
return equipment.getItemInMainHand();
}
public ItemStack getItemStack(int slot) {
return items[slot];
public ItemStack getItemInOffHand() {
if (equipment == null) return null;
return equipment.getItemInOffHand();
}
public ItemStack getItemStack(SlotType slot) {
return getItemStack(slot.getSlot());
public EntityEquipment getEquipment() {
return equipment;
}
protected Object getValue(int no, Object backup) {
@ -289,9 +278,10 @@ public class FlagWatcher {
}
public void setArmor(ItemStack[] itemstack) {
for (int i = 0; i < itemstack.length; i++) {
setItemStack(i, itemstack[i]);
}
setItemStack(EquipmentSlot.HEAD, itemstack[0]);
setItemStack(EquipmentSlot.CHEST, itemstack[1]);
setItemStack(EquipmentSlot.LEGS, itemstack[2]);
setItemStack(EquipmentSlot.FEET, itemstack[3]);
}
protected void setBackupValue(int no, Object value) {
@ -331,41 +321,43 @@ public class FlagWatcher {
sendData(0);
}
/**
* Don't use this, use setItemInMainHand instead
* @param itemstack
*/
@Deprecated
public void setItemInHand(ItemStack itemstack) {
setItemStack(SlotType.HELD_ITEM, itemstack);
setItemInMainHand(itemstack);
}
public void setItemStack(int slot, ItemStack itemStack) {
public void setItemInMainHand(ItemStack itemstack) {
setItemStack(EquipmentSlot.HAND, itemstack);
}
public void setItemInOffHand(ItemStack itemstack) {
setItemStack(EquipmentSlot.OFF_HAND, itemstack);
}
public void setItemStack(EquipmentSlot slot, ItemStack itemStack) {
if (equipment == null) return;
// 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;
}
setItemStack(equipment, slot, itemStack);
}
}
Object itemToSend = null;
if (itemStack != null && itemStack.getTypeId() != 0) {
itemToSend = ReflectionManager.getNmsItem(itemStack);
}
items[slot] = itemStack;
setItemStack(equipment, slot, itemStack);
if (DisguiseAPI.isDisguiseInUse(getDisguise()) && getDisguise().getWatcher() == this) {
slot++;
if (slot > 4) {
slot = 0;
}
PacketContainer packet = new PacketContainer(Server.ENTITY_EQUIPMENT);
StructureModifier<Object> mods = packet.getModifier();
mods.write(0, getDisguise().getEntity().getEntityId());
mods.write(1, slot);
mods.write(1, ReflectionManager.createEnumItemSlot(slot));
mods.write(2, itemToSend);
for (Player player : DisguiseUtilities.getPerverts(getDisguise())) {
try {
@ -377,8 +369,47 @@ public class FlagWatcher {
}
}
public void setItemStack(SlotType slot, ItemStack itemStack) {
setItemStack(slot.getSlot(), itemStack);
private void setItemStack(EntityEquipment equipment, EquipmentSlot slot, ItemStack itemStack) {
if (equipment == null) return;
switch (slot) {
case CHEST:
equipment.setChestplate(itemStack);
break;
case FEET:
equipment.setBoots(itemStack);
break;
case HAND:
equipment.setItemInMainHand(itemStack);
break;
case HEAD:
equipment.setHelmet(itemStack);
break;
case LEGS:
equipment.setLeggings(itemStack);
break;
case OFF_HAND:
equipment.setItemInOffHand(itemStack);
break;
}
}
public ItemStack getItemStack(EquipmentSlot slot) {
if (equipment == null) return null;
switch (slot) {
case CHEST:
return equipment.getChestplate();
case FEET:
return equipment.getBoots();
case HAND:
return equipment.getItemInMainHand();
case HEAD:
return equipment.getHelmet();
case LEGS:
return equipment.getLeggings();
case OFF_HAND:
return equipment.getItemInOffHand();
}
return null;
}
public void setRightClicking(boolean setRightClicking) {

View File

@ -10,7 +10,7 @@ public class EndermanWatcher extends LivingWatcher {
}
@Override
public ItemStack getItemInHand() {
public ItemStack getItemInMainHand() {
return new ItemStack((byte) getValue(16, (byte) 0), 1, ((byte) getValue(17, (byte) 0)));
}
@ -18,23 +18,13 @@ public class EndermanWatcher extends LivingWatcher {
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) {
public void setItemInMainHand(ItemStack itemstack) {
setValue(16, (short) (itemstack.getTypeId() & 255));
setValue(17, (byte) (itemstack.getDurability() & 255));
}

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;
}
}