diff --git a/pom.xml b/pom.xml index e85a36124..a8e32f12c 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,6 @@ - + 4.0.0 us.myles @@ -9,6 +8,22 @@ 0.4.6 + + org.apache.maven.plugins + maven-shade-plugin + 1.4 + + false + + + + package + + shade + + + + org.apache.maven.plugins maven-compiler-plugin @@ -26,12 +41,12 @@ - - org.spigotmc - spigot - 1.8.8-R0.1-SNAPSHOT - - + + org.spacehq + opennbt + 1.0 + + org.bukkit bukkit 1.8.8-R0.1-SNAPSHOT @@ -61,5 +76,9 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - + + spacehq-repo + https://repo.spacehq.org/content/repositories/releases/ + + diff --git a/src/main/java/us/myles/ViaVersion/api/slot/ItemSlotRewriter.java b/src/main/java/us/myles/ViaVersion/api/slot/ItemSlotRewriter.java index 0c94f4ac3..a25be1362 100644 --- a/src/main/java/us/myles/ViaVersion/api/slot/ItemSlotRewriter.java +++ b/src/main/java/us/myles/ViaVersion/api/slot/ItemSlotRewriter.java @@ -1,33 +1,23 @@ package us.myles.ViaVersion.api.slot; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import java.io.IOException; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.Map.Entry; import org.bukkit.Material; - -import net.minecraft.server.v1_8_R3.EntityTypes; -import net.minecraft.server.v1_8_R3.Item; -import net.minecraft.server.v1_8_R3.ItemStack; -import net.minecraft.server.v1_8_R3.MobEffect; -import net.minecraft.server.v1_8_R3.MobEffectList; -import net.minecraft.server.v1_8_R3.NBTTagCompound; -import net.minecraft.server.v1_8_R3.PotionBrewer; +import org.spacehq.opennbt.tag.builtin.CompoundTag; +import org.spacehq.opennbt.tag.builtin.StringTag; import io.netty.buffer.ByteBuf; import us.myles.ViaVersion.CancelException; -import us.myles.ViaVersion.util.ReflectionUtil; +import us.myles.ViaVersion.util.PacketUtil; public class ItemSlotRewriter { public static void rewrite1_9To1_8(ByteBuf input, ByteBuf output) throws CancelException { try { - Object item = readItemStack(input); + ItemStack item = readItemStack(input); fixIdsFrom1_9To1_8(item); writeItemStack(item, output); } catch (Exception e) { @@ -39,7 +29,7 @@ public class ItemSlotRewriter { public static void rewrite1_8To1_9(ByteBuf input, ByteBuf output) throws CancelException { try { - Object item = readItemStack(input); + ItemStack item = readItemStack(input); fixIdsFrom1_8To1_9(item); writeItemStack(item, output); } catch (Exception e) { @@ -49,120 +39,153 @@ public class ItemSlotRewriter { } } - public static void fixIdsFrom1_9To1_8(Object itemstack) throws NoSuchFieldException, IllegalAccessException { - if (itemstack != null) { - ItemStack stack = (ItemStack) itemstack; - int itemId = Item.getId(stack.getItem()); - if (itemId == Material.MONSTER_EGG.getId() && stack.getData() == 0) { - NBTTagCompound tag = stack.getTag(); + public static void fixIdsFrom1_9To1_8(ItemStack item) { + if (item != null) { + if (item.id == Material.MONSTER_EGG.getId() && item.data == 0) { + CompoundTag tag = item.tag; int data = 0; - if (tag != null && tag.hasKeyOfType("EntityTag", 10)) { - NBTTagCompound entityTag = tag.getCompound("EntityTag"); - if (entityTag.hasKeyOfType("id", 8)) { - String id = entityTag.getString("id"); - Map g = (Map) ReflectionUtil.getStatic(EntityTypes.class, "g", Map.class); - data = g.get(id); + if (tag != null && tag.get("EntityTag") instanceof CompoundTag) { + CompoundTag entityTag = tag.get("EntityTag"); + if (entityTag.get("id") instanceof StringTag) { + StringTag id = entityTag.get("id"); + data = ENTTIY_NAME_TO_ID.get(id.getValue()); } } - stack.setTag(null); - stack.setData(data); - } else if (itemId == Material.POTION.getId() && stack.getData() == 0) { - NBTTagCompound tag = stack.getTag(); - if (tag != null) { - System.out.println("in: " + tag); - } + item.tag = null; + item.data = (short) data; } } } - public static void fixIdsFrom1_8To1_9(Object itemstack) { - if (itemstack != null) { - ItemStack stack = (ItemStack) itemstack; - int itemId = Item.getId(stack.getItem()); - if (itemId == Material.MONSTER_EGG.getId() && stack.getData() != 0) { - NBTTagCompound tag = stack.getTag(); + public static void fixIdsFrom1_8To1_9(ItemStack item) { + if (item != null) { + if (item.id == Material.MONSTER_EGG.getId() && item.data != 0) { + CompoundTag tag = item.tag; if (tag == null) { - tag = new NBTTagCompound(); - } - NBTTagCompound entityTag = new NBTTagCompound(); - entityTag.setString("id", EntityTypes.b(stack.getData())); - tag.set("EntityTag", entityTag); - stack.setTag(tag); - stack.setData(0); - } else if (itemId == Material.POTION.getId() && stack.getData() != 0) { - NBTTagCompound tag = stack.getTag(); - if (tag == null) { - tag = new NBTTagCompound(); - stack.setTag(tag); - } - try { - List effects = PotionBrewer.getEffects(stack.getData(), true); - if (effects != null && effects.size() >= 1) { - MobEffect effect = effects.get(0); - MobEffectList type = MobEffectList.byId[effect.getEffectId()]; - StringBuilder name = new StringBuilder(); - System.out.println(effect.getDuration() + " ?>? " +type.k()); - if (effect.getAmplifier() > 0) { - name.append("strong_"); - } else if (effect.getDuration() > type.k()) { - name.append("long_"); - } - - name.append(POTION_TYPE_TO_KEY.get(effect.getEffectId())); - System.out.println("Rewriting to: " + name.toString()); - tag.setString("Potion", name.toString()); - } else { - System.out.println("Falling back to water for subId: " + stack.getData()); - tag.setString("Potion", "water"); - } - } catch (Exception e) { - e.printStackTrace(); + tag = new CompoundTag("tag"); } + CompoundTag entityTag = new CompoundTag("EntityTag"); + StringTag id = new StringTag("id", ENTTIY_ID_TO_NAME.get(item.data)); + entityTag.put(id); + tag.put(entityTag); + item.tag = tag; + item.data = 0; } } } - public static Object readItemStack(ByteBuf input) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Object serializer = getPacketDataSerializer(input); - return READ_ITEM.invoke(serializer); + public static ItemStack readItemStack(ByteBuf input) throws IOException { + short id = input.readShort(); + if (id < 0) { + return null; + } else { + ItemStack item = new ItemStack(); + item.id = id; + item.amount = input.readByte(); + item.data = input.readShort(); + item.tag = PacketUtil.readNBT(input); + return item; + } } - public static void writeItemStack(Object itemstack, ByteBuf output) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Object serializer = getPacketDataSerializer(output); - WRITE_ITEM.invoke(serializer, itemstack); + public static void writeItemStack(ItemStack item, ByteBuf output) throws IOException { + if (item == null) { + output.writeShort(-1); + } else { + output.writeShort(item.id); + output.writeByte(item.amount); + output.writeShort(item.data); + PacketUtil.writeNBT(output, item.tag); + } } - private static final Map POTION_TYPE_TO_KEY = new HashMap<>(); - private static Constructor SERIALIZER_CONSTRUCTOR; - private static Method WRITE_ITEM; - private static Method READ_ITEM; + public static class ItemStack { + + private short id; + private byte amount; + private short data; + private CompoundTag tag; + + public static ItemStack fromBukkit(org.bukkit.inventory.ItemStack stack) { + ItemStack item = new ItemStack(); + item.id = (short) stack.getTypeId(); + item.amount = (byte) stack.getAmount(); + item.data = stack.getData().getData(); + // TODO: nbt + return item; + } + } + + private static Map ENTTIY_NAME_TO_ID = new HashMap<>(); + private static Map ENTTIY_ID_TO_NAME = new HashMap<>(); static { - try { - Class list = ReflectionUtil.nms("MobEffectList"); - Map map = ReflectionUtil.getStatic(list, "I", Map.class); - for (Entry e : map.entrySet()) { - System.out.println(e.getValue()); - System.out.println(e.getValue().getClass()); - int id = ReflectionUtil.get(e.getValue(), list, "id", int.class); - String type = ReflectionUtil.get(e.getKey(), "b", String.class); - POTION_TYPE_TO_KEY.put(id, type); - } - } catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e1) { - e1.printStackTrace(); - } - try { - Class serializer = ReflectionUtil.nms("PacketDataSerializer"); - Class itemStack = ReflectionUtil.nms("ItemStack"); - SERIALIZER_CONSTRUCTOR = serializer.getDeclaredConstructor(ByteBuf.class); - WRITE_ITEM = serializer.getDeclaredMethod("a", itemStack); - READ_ITEM = serializer.getDeclaredMethod("i"); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { - e.printStackTrace(); - } + register(1, "Item"); + register(2, "XPOrb"); + register(7, "ThrownEgg"); + register(8, "LeashKnot"); + register(9, "Painting"); + register(10, "Arrow"); + register(11, "Snowball"); + register(12, "Fireball"); + register(13, "SmallFireball"); + register(14, "ThrownEnderpearl"); + register(15, "EyeOfEnderSignal"); + register(16, "ThrownPotion"); + register(17, "ThrownExpBottle"); + register(18, "ItemFrame"); + register(19, "WitherSkull"); + register(20, "PrimedTnt"); + register(21, "FallingSand"); + register(22, "FireworksRocketEntity"); + register(30, "ArmorStand"); + register(40, "MinecartCommandBlock"); + register(41, "Boat"); + register(42, "MinecartRideable"); + register(43, "MinecartChest"); + register(44, "MinecartFurnace"); + register(45, "MinecartTNT"); + register(46, "MinecartHopper"); + register(47, "MinecartSpawner"); + register(48, "Mob"); + register(49, "Monster"); + register(50, "Creeper"); + register(51, "Skeleton"); + register(52, "Spider"); + register(53, "Giant"); + register(54, "Zombie"); + register(55, "Slime"); + register(56, "Ghast"); + register(57, "PigZombie"); + register(58, "Enderman"); + register(59, "CaveSpider"); + register(60, "Silverfish"); + register(61, "Blaze"); + register(62, "LavaSlime"); + register(63, "EnderDragon"); + register(64, "WitherBoss"); + register(65, "Bat"); + register(66, "Witch"); + register(67, "Endermite"); + register(68, "Guardian"); + register(90, "Pig"); + register(91, "Sheep"); + register(92, "Cow"); + register(93, "Chicken"); + register(94, "Squid"); + register(95, "Wolf"); + register(96, "MushroomCow"); + register(97, "SnowMan"); + register(98, "Ozelot"); + register(99, "VillagerGolem"); + register(100, "EntityHorse"); + register(101, "Rabbit"); + register(120, "Villager"); + register(200, "EnderCrystal"); } - private static Object getPacketDataSerializer(ByteBuf buf) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - return SERIALIZER_CONSTRUCTOR.newInstance(buf); + private static void register(int id, String name) { + ENTTIY_ID_TO_NAME.put(id, name); + ENTTIY_NAME_TO_ID.put(name, id); } } diff --git a/src/main/java/us/myles/ViaVersion/metadata/MetadataRewriter.java b/src/main/java/us/myles/ViaVersion/metadata/MetadataRewriter.java index fd2467a33..a983a41d3 100644 --- a/src/main/java/us/myles/ViaVersion/metadata/MetadataRewriter.java +++ b/src/main/java/us/myles/ViaVersion/metadata/MetadataRewriter.java @@ -12,6 +12,7 @@ import org.bukkit.util.Vector; import io.netty.buffer.ByteBuf; import us.myles.ViaVersion.api.slot.ItemSlotRewriter; +import us.myles.ViaVersion.api.slot.ItemSlotRewriter.ItemStack; import us.myles.ViaVersion.util.PacketUtil; public class MetadataRewriter { @@ -93,8 +94,9 @@ public class MetadataRewriter { output.writeBoolean(((Byte) value).byteValue() != 0); break; case Slot: - ItemSlotRewriter.fixIdsFrom1_8To1_9(value); - ItemSlotRewriter.writeItemStack(value, output); + ItemStack item = (ItemStack) value; + ItemSlotRewriter.fixIdsFrom1_8To1_9(item); + ItemSlotRewriter.writeItemStack(item, output); break; case Position: Vector vector = (Vector) value; diff --git a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java index 5d1d0a522..e102a4214 100644 --- a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java +++ b/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java @@ -175,25 +175,11 @@ public class IncomingTransformer { int hand = PacketUtil.readVarInt(input); ItemStack inHand = ViaVersionPlugin.getHandItem(info); - Object item = null; try { - Method m = ReflectionUtil.obc("inventory.CraftItemStack").getDeclaredMethod("asNMSCopy", ItemStack.class); - item = m.invoke(null, inHand); + us.myles.ViaVersion.api.slot.ItemSlotRewriter.ItemStack item = us.myles.ViaVersion.api.slot.ItemSlotRewriter.ItemStack.fromBukkit(inHand); ItemSlotRewriter.fixIdsFrom1_9To1_8(item); ItemSlotRewriter.writeItemStack(item, output); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (NoSuchFieldException e) { + } catch (Exception e) { e.printStackTrace(); } @@ -213,25 +199,11 @@ public class IncomingTransformer { output.writeByte(255); // write item in hand ItemStack inHand = ViaVersionPlugin.getHandItem(info); - Object item = null; try { - Method m = ReflectionUtil.obc("inventory.CraftItemStack").getDeclaredMethod("asNMSCopy", ItemStack.class); - item = m.invoke(null, inHand); + us.myles.ViaVersion.api.slot.ItemSlotRewriter.ItemStack item = us.myles.ViaVersion.api.slot.ItemSlotRewriter.ItemStack.fromBukkit(inHand); ItemSlotRewriter.fixIdsFrom1_9To1_8(item); ItemSlotRewriter.writeItemStack(item, output); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (NoSuchFieldException e) { + } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/us/myles/ViaVersion/util/PacketUtil.java b/src/main/java/us/myles/ViaVersion/util/PacketUtil.java index 5d703b4fe..8129e008f 100644 --- a/src/main/java/us/myles/ViaVersion/util/PacketUtil.java +++ b/src/main/java/us/myles/ViaVersion/util/PacketUtil.java @@ -3,6 +3,8 @@ package us.myles.ViaVersion.util; import com.google.common.base.Charsets; import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.MessageToByteEncoder; @@ -11,6 +13,9 @@ import us.myles.ViaVersion.chunks.PacketChunk; import us.myles.ViaVersion.chunks.PacketChunkData; import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.ByteBuffer; @@ -21,6 +26,9 @@ import java.util.BitSet; import java.util.List; import java.util.UUID; +import org.spacehq.opennbt.NBTIO; +import org.spacehq.opennbt.tag.builtin.CompoundTag; + public class PacketUtil { private static Method DECODE_METHOD; private static Method ENCODE_METHOD; @@ -42,6 +50,25 @@ public class PacketUtil { } } + public static CompoundTag readNBT(ByteBuf input) throws IOException { + int readerIndex = input.readerIndex(); + byte b = input.readByte(); + if (b == 0) { + return null; + } else { + input.readerIndex(readerIndex); + return (CompoundTag) NBTIO.readTag(new DataInputStream(new ByteBufInputStream(input))); + } + } + + public static void writeNBT(ByteBuf output, CompoundTag tag) throws IOException { + if (tag == null) { + output.writeByte(0); + } else { + NBTIO.writeTag(new DataOutputStream(new ByteBufOutputStream(output)), tag); + } + } + public static List callDecode(ByteToMessageDecoder decoder, ChannelHandlerContext ctx, Object input) { List output = new ArrayList(); try {