diff --git a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java index c0290096a..3dd87b699 100644 --- a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java +++ b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java @@ -2,13 +2,15 @@ package us.myles.ViaVersion.transformers; import com.google.gson.Gson; import com.google.gson.JsonObject; +import com.sun.xml.internal.bind.v2.runtime.reflect.Lister; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; -import org.bukkit.Bukkit; -import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; import org.spacehq.mc.protocol.data.game.chunk.Column; import org.spacehq.mc.protocol.util.NetUtil; -import us.myles.ViaVersion.*; +import us.myles.ViaVersion.CancelException; +import us.myles.ViaVersion.ConnectionInfo; +import us.myles.ViaVersion.ViaVersionPlugin; import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.handlers.ViaVersionInitializer; import us.myles.ViaVersion.metadata.MetaIndex; @@ -23,7 +25,6 @@ import us.myles.ViaVersion.util.ReflectionUtil; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.*; import static us.myles.ViaVersion.util.PacketUtil.*; @@ -36,6 +37,7 @@ public class OutgoingTransformer { private final ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); private boolean cancel = false; private Map uuidMap = new HashMap(); + private Map clientEntityTypes = new HashMap(); public OutgoingTransformer(Channel channel, ConnectionInfo info, ViaVersionInitializer init) { this.channel = channel; @@ -212,13 +214,7 @@ public class OutgoingTransformer { try { List dw = ReflectionUtil.get(info.getLastPacket(), "b", List.class); // get entity via entityID, not preferred but we need it. - Entity entity = ViaVersionPlugin.getEntity(info.getUUID(), id); - if (entity != null) { - transformMetadata(entity, dw, output); - } else { - // Died before we could get to it. rip - throw new CancelException(); - } + transformMetadata(id, dw, output); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { @@ -226,13 +222,41 @@ public class OutgoingTransformer { } return; } - if (packet == PacketType.PLAY_SPAWN_OBJECT) { + if (packet == PacketType.PLAY_SPAWN_GLOBAL_ENTITY) { int id = PacketUtil.readVarInt(input); PacketUtil.writeVarInt(id, output); + // only used for lightning + byte type = input.readByte(); + clientEntityTypes.put(id, EntityType.LIGHTNING); + output.writeByte(type); + + double x = input.readInt(); + output.writeDouble(x / 32D); + double y = input.readInt(); + output.writeDouble(y / 32D); + double z = input.readInt(); + output.writeDouble(z / 32D); + return; + } + if (packet == PacketType.PLAY_DESTROY_ENTITIES) { + int count = PacketUtil.readVarInt(input); + PacketUtil.writeVarInt(count, output); + + int[] toDestroy = PacketUtil.readVarInts(count, input); + for (int entityID : toDestroy) { + clientEntityTypes.remove(entityID); + PacketUtil.writeVarInt(entityID, output); + } + return; + } + if (packet == PacketType.PLAY_SPAWN_OBJECT) { + int id = PacketUtil.readVarInt(input); + PacketUtil.writeVarInt(id, output); PacketUtil.writeUUID(getUUID(id), output); byte type = input.readByte(); + clientEntityTypes.put(id, EntityUtil.getTypeFromID(type, true)); output.writeByte(type); double x = input.readInt(); @@ -258,8 +282,9 @@ public class OutgoingTransformer { return; } - if (packet == PacketType.PLAY_SPAWN_XP_ORB) { // TODO: Verify + if (packet == PacketType.PLAY_SPAWN_XP_ORB) { int id = PacketUtil.readVarInt(input); + clientEntityTypes.put(id, EntityType.EXPERIENCE_ORB); PacketUtil.writeVarInt(id, output); double x = input.readInt(); @@ -276,6 +301,7 @@ public class OutgoingTransformer { } if (packet == PacketType.PLAY_SPAWN_PAINTING) { int id = PacketUtil.readVarInt(input); + clientEntityTypes.put(id, EntityType.PAINTING); PacketUtil.writeVarInt(id, output); PacketUtil.writeUUID(getUUID(id), output); @@ -308,7 +334,9 @@ public class OutgoingTransformer { PacketUtil.writeUUID(getUUID(id), output); short type = input.readUnsignedByte(); + clientEntityTypes.put(id, EntityUtil.getTypeFromID(type, false)); output.writeByte(type); + double x = input.readInt(); output.writeDouble(x / 32D); double y = input.readInt(); @@ -330,7 +358,7 @@ public class OutgoingTransformer { output.writeShort(vZ); try { Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "l", ReflectionUtil.nms("DataWatcher")); - transformMetadata(dataWatcher, output); + transformMetadata(id, dataWatcher, output); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { @@ -348,10 +376,17 @@ public class OutgoingTransformer { PacketUtil.writeString(fixJson(line), output); } } + if (packet == PacketType.PLAY_JOIN_GAME) { + int id = input.readInt(); + clientEntityTypes.put(id, EntityType.PLAYER); + output.writeInt(id); + output.writeBytes(input); + return; + } if (packet == PacketType.PLAY_SPAWN_PLAYER) { int id = PacketUtil.readVarInt(input); PacketUtil.writeVarInt(id, output); - + clientEntityTypes.put(id, EntityType.PLAYER); UUID playerUUID = PacketUtil.readUUID(input); PacketUtil.writeUUID(playerUUID, output); @@ -368,7 +403,7 @@ public class OutgoingTransformer { output.writeByte(yaw); try { Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "i", ReflectionUtil.nms("DataWatcher")); - transformMetadata(dataWatcher, output); + transformMetadata(id, dataWatcher, output); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { @@ -469,30 +504,25 @@ public class OutgoingTransformer { return line; } - private void transformMetadata(Object dw, ByteBuf output) { + private void transformMetadata(int entityID, Object dw, ByteBuf output) { // get entity try { - Class nmsClass = ReflectionUtil.nms("Entity"); - Object nmsEntity = ReflectionUtil.get(dw, "a", nmsClass); - Class craftClass = ReflectionUtil.obc("entity.CraftEntity"); - Method bukkitMethod = craftClass.getDeclaredMethod("getEntity", ReflectionUtil.obc("CraftServer"), nmsClass); - - Object entity = bukkitMethod.invoke(null, Bukkit.getServer(), nmsEntity); - transformMetadata((Entity) entity, (List) ReflectionUtil.invoke(dw, "b"), output); - } catch (NoSuchFieldException e) { - e.printStackTrace(); + transformMetadata(entityID, (List) ReflectionUtil.invoke(dw, "b"), output); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); } } - private void transformMetadata(Entity entity, List dw, ByteBuf output) { + private void transformMetadata(int entityID, List dw, ByteBuf output) { + EntityType type = clientEntityTypes.get(entityID); + if (type == null) { + System.out.println("Unable to get entity for ID: " + entityID); + return; + } if (dw != null) { short id = -1; int data = -1; @@ -502,7 +532,7 @@ public class OutgoingTransformer { Object watchableObj = iterator.next(); // MetaIndex metaIndex = null; try { - metaIndex = MetaIndex.getIndex(entity, (int) ReflectionUtil.invoke(watchableObj, "a")); + metaIndex = MetaIndex.getIndex(type, (int) ReflectionUtil.invoke(watchableObj, "a")); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { @@ -592,8 +622,8 @@ public class OutgoingTransformer { } } catch (Exception e) { - if (entity != null) { - System.out.println("An error occurred with entity meta data for " + entity.getType()); + if (type != null) { + System.out.println("An error occurred with entity meta data for " + type); System.out.println("Old ID: " + metaIndex.getIndex() + " New ID: " + metaIndex.getNewIndex()); System.out.println("Old Type: " + metaIndex.getOldType() + " New Type: " + metaIndex.getNewType()); } diff --git a/src/main/java/us/myles/ViaVersion/util/PacketUtil.java b/src/main/java/us/myles/ViaVersion/util/PacketUtil.java index 8a734b124..8da0ede76 100644 --- a/src/main/java/us/myles/ViaVersion/util/PacketUtil.java +++ b/src/main/java/us/myles/ViaVersion/util/PacketUtil.java @@ -376,4 +376,13 @@ public class PacketUtil { public static void writeBlockPosition(ByteBuf buf, long x, long y, long z) { buf.writeLong(((x & 0x3ffffff) << 38) | ((y & 0xfff) << 26) | (z & 0x3ffffff)); } + + public static int[] readVarInts(int amount, ByteBuf input) { + int data[] = new int[amount]; + for (int index = 0; index < amount; index++) { + data[index] = PacketUtil.readVarInt(input); + } + + return data; + } }