From 658c3f060259c6a5b4208380fa3f83fa6719301c Mon Sep 17 00:00:00 2001 From: libraryaddict Date: Tue, 9 Jul 2019 20:52:00 +1200 Subject: [PATCH] Fix invalid serializer for empty optionals, add serializer to MetaIndex and require for all datawatcher objects constructions --- .../disguise/disguisetypes/FlagWatcher.java | 14 ++-- .../disguise/disguisetypes/MetaIndex.java | 20 +++++ .../disguise/utilities/DisguiseUtilities.java | 52 ++++++++++--- .../PacketHandlerEquipment.java | 3 +- .../PacketListenerViewSelfDisguise.java | 3 +- .../reflection/ReflectionManager.java | 75 ++++++++----------- 6 files changed, 107 insertions(+), 60 deletions(-) diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java index e4228e30..d862415b 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/FlagWatcher.java @@ -112,7 +112,7 @@ public class FlagWatcher { boolean isDirty = watch.getDirtyState(); - watch = ReflectionManager.createWatchable(id, value); + watch = ReflectionManager.createWatchable(MetaIndex.getMetaIndex(this, id), value); if (watch == null) continue; @@ -123,7 +123,7 @@ public class FlagWatcher { } else { boolean isDirty = watch.getDirtyState(); - watch = ReflectionManager.createWatchable(id, watch.getValue()); + watch = ReflectionManager.createWatchable(MetaIndex.getMetaIndex(this, id), watch.getValue()); if (watch == null) continue; @@ -149,7 +149,8 @@ public class FlagWatcher { continue; } - WrappedWatchableObject watch = ReflectionManager.createWatchable(id, value); + WrappedWatchableObject watch = ReflectionManager + .createWatchable(MetaIndex.getMetaIndex(this, id), value); if (watch == null) continue; @@ -317,9 +318,10 @@ public class FlagWatcher { WrappedWatchableObject watchable; if (entityValues.containsKey(i) && entityValues.get(i) != null) { - watchable = ReflectionManager.createWatchable(i, entityValues.get(i)); + watchable = ReflectionManager.createWatchable(MetaIndex.getMetaIndex(this, i), entityValues.get(i)); } else if (backupEntityValues.containsKey(i) && backupEntityValues.get(i) != null) { - watchable = ReflectionManager.createWatchable(i, backupEntityValues.get(i)); + watchable = ReflectionManager + .createWatchable(MetaIndex.getMetaIndex(this, i), backupEntityValues.get(i)); } else { continue; } @@ -354,7 +356,7 @@ public class FlagWatcher { WrappedDataWatcher.getEntityWatcher(disguise.getEntity()).getByte(0)); } - WrappedWatchableObject watch = ReflectionManager.createWatchable(data.getIndex(), value); + WrappedWatchableObject watch = ReflectionManager.createWatchable(data, value); if (watch == null) continue; diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java index 26a9d79b..f37a4bff 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/MetaIndex.java @@ -7,6 +7,7 @@ import com.comphenix.protocol.wrappers.nbt.NbtFactory; import com.comphenix.protocol.wrappers.nbt.NbtType; import me.libraryaddict.disguise.disguisetypes.watchers.*; import me.libraryaddict.disguise.utilities.DisguiseUtilities; +import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.Particle; @@ -657,6 +658,15 @@ public class MetaIndex { } } + /** + * @param watcher - A FlagWatcher class + * @param flagNo - The meta index number + * @return The MetaIndex which corresponds to that FlagWatcher at that index + */ + public static MetaIndex getMetaIndex(FlagWatcher watcher, int flagNo) { + return getMetaIndex(watcher.getClass(), flagNo); + } + /** * @param watcherClass - A FlagWatcher class * @param flagNo - The meta index number @@ -793,6 +803,8 @@ public class MetaIndex { _values = Arrays.copyOf(_values, _values.length + 1); _values[_values.length - 1] = index; + + index.serializer = DisguiseUtilities.getSerializer(index); } } catch (Exception e) { @@ -823,6 +835,7 @@ public class MetaIndex { private Y _defaultValue; private int _index; private Class _watcher; + private WrappedDataWatcher.Serializer serializer; public MetaIndex(Class watcher, int index, Y defaultValue) { _index = index; @@ -834,6 +847,13 @@ public class MetaIndex { return _defaultValue; } + /** + * Used for serializing values to a packet stream + */ + public WrappedDataWatcher.Serializer getSerializer() { + return serializer; + } + public Class getFlagWatcher() { return _watcher; } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java index c09a9a1b..1cb86111 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/DisguiseUtilities.java @@ -28,10 +28,7 @@ import me.libraryaddict.disguise.utilities.reflection.LibsProfileLookup; import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; import me.libraryaddict.disguise.utilities.translations.LibsMsg; import org.apache.logging.log4j.util.Strings; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; +import org.bukkit.*; import org.bukkit.block.BlockFace; import org.bukkit.craftbukkit.libs.org.apache.commons.io.FileUtils; import org.bukkit.entity.*; @@ -920,8 +917,7 @@ public class DisguiseUtilities { Field cSection = chunkClass.getDeclaredField("sections"); cSection.setAccessible(true); - Object chunkSection = ReflectionManager.getNmsClass("ChunkSection").getConstructor(int.class) - .newInstance(0); + Object chunkSection = ReflectionManager.getNmsClass("ChunkSection").getConstructor(int.class).newInstance(0); Class blockClass = ReflectionManager.getNmsClass("Block"); Object REGISTRY = ReflectionManager.getNmsField("IRegistry", "BLOCK").get(null); @@ -1036,8 +1032,7 @@ public class DisguiseUtilities { Set trackedPlayers = (Set) ReflectionManager.getNmsField("EntityTrackerEntry", "trackedPlayers") .get(entityTrackerEntry); - Method clear = ReflectionManager - .getNmsMethod("EntityTrackerEntry", "a", ReflectionManager.getNmsClass("EntityPlayer")); + Method clear = ReflectionManager.getNmsMethod("EntityTrackerEntry", "a", ReflectionManager.getNmsClass("EntityPlayer")); final Method updatePlayer = ReflectionManager .getNmsMethod("EntityTrackerEntry", "b", ReflectionManager.getNmsClass("EntityPlayer")); @@ -1733,6 +1728,44 @@ public class DisguiseUtilities { } } + public static WrappedDataWatcher.Serializer getSerializer(MetaIndex index) { + if (index.getSerializer() != null) { + return index.getSerializer(); + } + + if (index.getDefault() instanceof Optional) { + for (Field f : MetaIndex.class.getFields()) { + try { + if (f.get(null) != index) { + continue; + } + } + catch (IllegalAccessException e) { + e.printStackTrace(); + } + + Type type = f.getGenericType(); + Type opt = ((ParameterizedType) type).getActualTypeArguments()[0]; + + if (opt instanceof ParameterizedType) { + Type val = ((ParameterizedType) opt).getActualTypeArguments()[0]; + + return WrappedDataWatcher.Registry.get(ReflectionManager.getNmsClass((Class) val), true); + } + } + } else { + return WrappedDataWatcher.Registry.get(ReflectionManager.getNmsClass(index.getDefault().getClass())); + } + + Object value = index.getDefault(); + + throw new IllegalArgumentException("Unable to find Serializer for " + value + + (value instanceof Optional && ((Optional) value).isPresent() ? + " (" + ((Optional) value).get().getClass().getName() + ")" : + value instanceof Optional || value == null ? "" : " " + value.getClass().getName()) + + "! Are you running " + "the latest " + "version of " + "ProtocolLib?"); + } + /** * Create a new datawatcher but with the 'correct' values */ @@ -1753,7 +1786,8 @@ public class DisguiseUtilities { continue; WrappedDataWatcher.WrappedDataWatcherObject obj = ReflectionManager - .createDataWatcherObject(watchableObject.getIndex(), watchableObject.getValue()); + .createDataWatcherObject(MetaIndex.getMetaIndex(disguiseWatcher, watchableObject.getIndex()), + watchableObject.getValue()); newWatcher.setObject(obj, watchableObject.getValue()); } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/packets/packethandlers/PacketHandlerEquipment.java b/src/main/java/me/libraryaddict/disguise/utilities/packets/packethandlers/PacketHandlerEquipment.java index 22d9b103..e8cea10a 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/packets/packethandlers/PacketHandlerEquipment.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/packets/packethandlers/PacketHandlerEquipment.java @@ -6,6 +6,7 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher; import com.comphenix.protocol.wrappers.WrappedWatchableObject; import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.MetaIndex; import me.libraryaddict.disguise.utilities.packets.IPacketHandler; import me.libraryaddict.disguise.utilities.packets.LibsPackets; import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; @@ -56,7 +57,7 @@ public class PacketHandlerEquipment implements IPacketHandler { if (DisguiseConfig.isMetadataPacketsEnabled()) { WrappedWatchableObject watch = ReflectionManager - .createWatchable(0, WrappedDataWatcher.getEntityWatcher(entity).getByte(0)); + .createWatchable(MetaIndex.ENTITY_META, WrappedDataWatcher.getEntityWatcher(entity).getByte(0)); if (watch != null) list.add(watch); diff --git a/src/main/java/me/libraryaddict/disguise/utilities/packets/packetlisteners/PacketListenerViewSelfDisguise.java b/src/main/java/me/libraryaddict/disguise/utilities/packets/packetlisteners/PacketListenerViewSelfDisguise.java index 42a7c197..ca46a097 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/packets/packetlisteners/PacketListenerViewSelfDisguise.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/packets/packetlisteners/PacketListenerViewSelfDisguise.java @@ -12,6 +12,7 @@ import com.comphenix.protocol.wrappers.WrappedWatchableObject; import me.libraryaddict.disguise.DisguiseAPI; import me.libraryaddict.disguise.LibsDisguises; import me.libraryaddict.disguise.disguisetypes.Disguise; +import me.libraryaddict.disguise.disguisetypes.MetaIndex; import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.packets.LibsPackets; import me.libraryaddict.disguise.utilities.packets.PacketsManager; @@ -140,7 +141,7 @@ public class PacketListenerViewSelfDisguise extends PacketAdapter { if (observer.isSprinting()) b = (byte) (b | 1 << 3); - WrappedWatchableObject watch = ReflectionManager.createWatchable(0, b); + WrappedWatchableObject watch = ReflectionManager.createWatchable(MetaIndex.ENTITY_META, b); if (watch != null) watchableList.add(watch); diff --git a/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java b/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java index f93e00f9..9d2018e8 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java @@ -13,6 +13,7 @@ import com.mojang.datafixers.Dynamic; import me.libraryaddict.disguise.DisguiseConfig; import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.EntityPose; +import me.libraryaddict.disguise.disguisetypes.MetaIndex; import me.libraryaddict.disguise.disguisetypes.VillagerData; import me.libraryaddict.disguise.utilities.DisguiseUtilities; import net.minecraft.server.v1_14_R1.IRegistry; @@ -26,6 +27,7 @@ import org.bukkit.entity.*; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; +import org.bukkit.util.EulerAngle; import org.bukkit.util.Vector; import java.io.IOException; @@ -836,6 +838,32 @@ public class ReflectionManager { return null; } + public static Class getNmsClass(Class cl) { + if (VillagerData.class.isAssignableFrom(cl)) { + return getNmsClass("VillagerData"); + } else if (BlockPosition.class.isAssignableFrom(cl)) { + return getNmsClass("BlockPosition"); + } else if (WrappedBlockData.class.isAssignableFrom(cl)) { + return getNmsClass("IBlockData"); + } else if (ItemStack.class.isAssignableFrom(cl)) { + return getNmsClass("ItemStack"); + } else if (WrappedChatComponent.class.isAssignableFrom(cl)) { + return getNmsClass("IChatBaseComponent"); + } else if (Vector3F.class.isAssignableFrom(cl)) { + return getNmsClass("Vector3f"); + } else if (Direction.class.isAssignableFrom(cl)) { + return getNmsClass("EnumDirection"); + } else if (WrappedParticle.class.isAssignableFrom(cl)) { + return getNmsClass("ParticleParam"); + } else if (EntityPose.class.isAssignableFrom(cl)) { + return getNmsClass("EntityPose"); + } else if (NbtWrapper.class.isAssignableFrom(cl)) { + return getNmsClass("NBTTagCompound"); + } + + return cl; + } + public static Object convertInvalidMeta(Object value) { if (value instanceof Optional) { Optional opt = (Optional) value; @@ -972,52 +1000,13 @@ public class ReflectionManager { return version; } - public static WrappedDataWatcherObject createDataWatcherObject(int id, Object value) { + public static WrappedDataWatcherObject createDataWatcherObject(MetaIndex index, Object value) { if (value == null) return null; value = convertInvalidMeta(value); - Serializer serializer; - - if (value instanceof Optional) { - Optional opt = (Optional) value; - - if (opt.isPresent()) { - Object val = opt.get(); - Class cl; - Class iBlockData = getNmsClass("IBlockData"); - Class iChat = getNmsClass("IChatBaseComponent"); - - if (iBlockData.isInstance(val)) { - cl = iBlockData; - } else if (iChat.isInstance(val)) { - cl = iChat; - } else { - cl = val.getClass(); - } - - serializer = Registry.get(cl, true); - } else { - serializer = Registry.get(UUID.class, true); - } - } else { - serializer = Registry.get(getNmsClass("ParticleParam").isInstance(value) ? getNmsClass("ParticleParam") : - value.getClass()); - } - - if (serializer == null) { - if (value.getClass().getSimpleName().equals("NBTTagCompound")) - return null; // Handle PaperSpigot's bad coding - - throw new IllegalArgumentException("Unable to find Serializer for " + value + - (value instanceof Optional && ((Optional) value).isPresent() ? - " (" + ((Optional) value).get().getClass().getName() + ")" : - value instanceof Optional || value == null ? "" : " " + value.getClass().getName()) + - "! Are you running " + "the latest " + "version of " + "ProtocolLib?"); - } - - return new WrappedDataWatcherObject(id, serializer); + return new WrappedDataWatcherObject(index.getIndex(), index.getSerializer()); } /** @@ -1027,7 +1016,7 @@ public class ReflectionManager { * @param value * @return */ - public static Object createDataWatcherItem(int id, Object value) { + public static Object createDataWatcherItem(MetaIndex id, Object value) { WrappedDataWatcherObject watcherObject = createDataWatcherObject(id, value); Constructor construct = getNmsConstructor("DataWatcher$Item", getNmsClass("DataWatcherObject"), Object.class); @@ -1106,7 +1095,7 @@ public class ReflectionManager { return EntityPose.valueOf(((Enum) nmsEntityPose).name()); } - public static WrappedWatchableObject createWatchable(int index, Object obj) { + public static WrappedWatchableObject createWatchable(MetaIndex index, Object obj) { Object watcherItem = createDataWatcherItem(index, obj); if (watcherItem == null)