From f71e51c85e9834099610e19755346e3b8d6b5155 Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 4 Mar 2016 19:24:44 +0000 Subject: [PATCH 1/4] Add packet sending to API --- .../us/myles/ViaVersion/ConnectionInfo.java | 7 +++++ .../us/myles/ViaVersion/ViaVersionPlugin.java | 30 ++++++++++++------- .../myles/ViaVersion/api/ViaVersionAPI.java | 16 +++++++++- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/main/java/us/myles/ViaVersion/ConnectionInfo.java b/src/main/java/us/myles/ViaVersion/ConnectionInfo.java index 4516fe804..dd1db8b1c 100644 --- a/src/main/java/us/myles/ViaVersion/ConnectionInfo.java +++ b/src/main/java/us/myles/ViaVersion/ConnectionInfo.java @@ -1,5 +1,7 @@ package us.myles.ViaVersion; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler; import io.netty.channel.socket.SocketChannel; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -75,4 +77,9 @@ public class ConnectionInfo { public void setActive(boolean active) { this.active = active; } + + public void sendRawPacket(ByteBuf packet) { + ChannelHandler handler = channel.pipeline().get("encoder"); + channel.pipeline().context(handler).writeAndFlush(packet); + } } diff --git a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java b/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java index 5c6903e9e..e21122dc9 100644 --- a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java +++ b/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java @@ -1,5 +1,6 @@ package us.myles.ViaVersion; +import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelInitializer; @@ -16,12 +17,12 @@ import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.api.ViaVersionAPI; import us.myles.ViaVersion.commands.ViaVersionCommand; import us.myles.ViaVersion.handlers.ViaVersionInitializer; +import us.myles.ViaVersion.listeners.ArmorFix; import us.myles.ViaVersion.util.ReflectionUtil; import java.lang.reflect.Field; -import java.util.Collections; import java.util.List; -import java.util.Set; +import java.util.Map; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; @@ -29,7 +30,7 @@ import java.util.concurrent.TimeUnit; public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI { - private final Set portedPlayers = Collections.newSetFromMap(new ConcurrentHashMap()); + private final Map portedPlayers = new ConcurrentHashMap(); @Override public void onEnable() { @@ -50,9 +51,10 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI { Bukkit.getPluginManager().registerEvents(new Listener() { @EventHandler public void onPlayerQuit(PlayerQuitEvent e) { - setPorted(e.getPlayer().getUniqueId(), false); + removePortedClient(e.getPlayer().getUniqueId()); } }, this); + Bukkit.getPluginManager().registerEvents(new ArmorFix(), this); getCommand("viaversion").setExecutor(new ViaVersionCommand()); } @@ -88,7 +90,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI { @Override public boolean isPorted(Player player) { - return portedPlayers.contains(player.getUniqueId()); + return portedPlayers.containsKey(player.getUniqueId()); } @Override @@ -96,12 +98,18 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI { return getDescription().getVersion(); } - public void setPorted(UUID id, boolean value) { - if (value) { - portedPlayers.add(id); - } else { - portedPlayers.remove(id); - } + public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException { + if (!isPorted(player)) throw new IllegalArgumentException("This player is not on 1.9"); + ConnectionInfo ci = portedPlayers.get(player.getUniqueId()); + ci.sendRawPacket(packet); + } + + public void addPortedClient(ConnectionInfo info) { + portedPlayers.put(info.getUUID(), info); + } + + public void removePortedClient(UUID clientID) { + portedPlayers.remove(clientID); } public static ItemStack getHandItem(final ConnectionInfo info) { diff --git a/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java b/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java index ba3fe0b0e..d957ead38 100644 --- a/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java +++ b/src/main/java/us/myles/ViaVersion/api/ViaVersionAPI.java @@ -1,13 +1,27 @@ package us.myles.ViaVersion.api; +import io.netty.buffer.ByteBuf; import org.bukkit.entity.Player; public interface ViaVersionAPI { /** * Is player using 1.9? * @param player - * @return + * @return True if the client is on 1.9 */ boolean isPorted(Player player); + + /** + * Get the version of the plugin + * @return Plugin version + */ String getVersion(); + + /** + * Send a raw packet to the player (Use new IDs) + * @param player The player to send packet + * @param packet The packet, you need a VarInt ID then the packet contents. + * @throws IllegalArgumentException If not on 1.9 throws IllegalArg + */ + void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException; } From fb5dace6a6cbd4de8d1ac775b94e1e37ea51ab08 Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 4 Mar 2016 20:03:46 +0000 Subject: [PATCH 2/4] Add armour, based on HugoDaBoss code but modified to work correctly with shift click. Also fix small issue from last commit. --- .../us/myles/ViaVersion/ConnectionInfo.java | 11 +- .../us/myles/ViaVersion/ViaVersionPlugin.java | 7 +- .../myles/ViaVersion/armor/ArmorListener.java | 106 ++++++++++++++++++ .../us/myles/ViaVersion/armor/ArmorType.java | 91 +++++++++++++++ .../transformers/IncomingTransformer.java | 8 +- .../transformers/OutgoingTransformer.java | 9 +- 6 files changed, 214 insertions(+), 18 deletions(-) create mode 100644 src/main/java/us/myles/ViaVersion/armor/ArmorListener.java create mode 100644 src/main/java/us/myles/ViaVersion/armor/ArmorType.java diff --git a/src/main/java/us/myles/ViaVersion/ConnectionInfo.java b/src/main/java/us/myles/ViaVersion/ConnectionInfo.java index dd1db8b1c..1ee032a6b 100644 --- a/src/main/java/us/myles/ViaVersion/ConnectionInfo.java +++ b/src/main/java/us/myles/ViaVersion/ConnectionInfo.java @@ -78,8 +78,13 @@ public class ConnectionInfo { this.active = active; } - public void sendRawPacket(ByteBuf packet) { - ChannelHandler handler = channel.pipeline().get("encoder"); - channel.pipeline().context(handler).writeAndFlush(packet); + public void sendRawPacket(final ByteBuf packet) { + final ChannelHandler handler = channel.pipeline().get("encoder"); + channel.eventLoop().submit(new Runnable() { + @Override + public void run() { + channel.pipeline().context(handler).writeAndFlush(packet); + } + }); } } diff --git a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java b/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java index e21122dc9..a84e350bc 100644 --- a/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java +++ b/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java @@ -15,9 +15,9 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.api.ViaVersionAPI; +import us.myles.ViaVersion.armor.ArmorListener; import us.myles.ViaVersion.commands.ViaVersionCommand; import us.myles.ViaVersion.handlers.ViaVersionInitializer; -import us.myles.ViaVersion.listeners.ArmorFix; import us.myles.ViaVersion.util.ReflectionUtil; import java.lang.reflect.Field; @@ -48,13 +48,16 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI { getLogger().severe("Unable to inject handlers, are you on 1.8? "); e.printStackTrace(); } + Bukkit.getPluginManager().registerEvents(new Listener() { @EventHandler public void onPlayerQuit(PlayerQuitEvent e) { removePortedClient(e.getPlayer().getUniqueId()); } }, this); - Bukkit.getPluginManager().registerEvents(new ArmorFix(), this); + + Bukkit.getPluginManager().registerEvents(new ArmorListener(this), this); + getCommand("viaversion").setExecutor(new ViaVersionCommand()); } diff --git a/src/main/java/us/myles/ViaVersion/armor/ArmorListener.java b/src/main/java/us/myles/ViaVersion/armor/ArmorListener.java new file mode 100644 index 000000000..a86542f5d --- /dev/null +++ b/src/main/java/us/myles/ViaVersion/armor/ArmorListener.java @@ -0,0 +1,106 @@ +package us.myles.ViaVersion.armor; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.bukkit.Bukkit; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.inventory.CraftingInventory; +import us.myles.ViaVersion.ViaVersionPlugin; +import us.myles.ViaVersion.api.ViaVersion; +import us.myles.ViaVersion.packets.PacketType; + +import java.util.UUID; + +import static us.myles.ViaVersion.util.PacketUtil.*; + +public class ArmorListener implements Listener { + + private final ViaVersionPlugin plugin; + + private static UUID armorAttribute = UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150"); + + public ArmorListener(ViaVersionPlugin plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onInventoryClick(InventoryClickEvent e) { + HumanEntity human = e.getWhoClicked(); + if (human instanceof Player && e.getInventory() instanceof CraftingInventory) { + final Player player = (Player) human; + if (ViaVersion.getInstance().isPorted(player)) { + if (e.getCurrentItem() != null) { + if (ArmorType.isArmor(e.getCurrentItem().getType())) { + sendDelayedArmorUpdate(player); + return; + } + } + if (e.getRawSlot() >= 5 && e.getRawSlot() <= 8) { + sendDelayedArmorUpdate(player); + return; + } + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onInteract(PlayerInteractEvent e) { + if (e.getItem() != null) { + if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (ArmorType.isArmor(e.getMaterial())) { + final Player player = e.getPlayer(); + // Due to odd bugs it's 3 ticks later + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + @Override + public void run() { + if (ViaVersion.getInstance().isPorted(player)) { + sendArmorUpdate(player); + } + } + }, 3L); + } + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onJoin(PlayerJoinEvent e) { + sendDelayedArmorUpdate(e.getPlayer()); + } + + public void sendDelayedArmorUpdate(final Player player) { + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + @Override + public void run() { + if (ViaVersion.getInstance().isPorted(player)) { + sendArmorUpdate(player); + } + } + }); + } + + public static void sendArmorUpdate(Player player) { + int armor = ArmorType.calculateArmorPoints(player.getInventory().getArmorContents()); + + ByteBuf buf = Unpooled.buffer(); + writeVarInt(PacketType.PLAY_ENTITY_PROPERTIES.getNewPacketID(), buf); + writeVarInt(player.getEntityId(), buf); + buf.writeInt(1); // only 1 property + writeString("generic.armor", buf); + buf.writeDouble(0); //default 0 armor + writeVarInt(1, buf); // 1 modifier + writeUUID(armorAttribute, buf); // armor modifier uuid + buf.writeDouble((double) armor); // the modifier value + buf.writeByte(0); // the modifier operation, 0 is add number + + ViaVersion.getInstance().sendRawPacket(player, buf); + } +} \ No newline at end of file diff --git a/src/main/java/us/myles/ViaVersion/armor/ArmorType.java b/src/main/java/us/myles/ViaVersion/armor/ArmorType.java new file mode 100644 index 000000000..23f0bda44 --- /dev/null +++ b/src/main/java/us/myles/ViaVersion/armor/ArmorType.java @@ -0,0 +1,91 @@ +package us.myles.ViaVersion.armor; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +public enum ArmorType { + + LEATHER_HELMET(1, 298, Material.LEATHER_HELMET), + LEATHER_CHESTPLATE(3, 299, Material.LEATHER_CHESTPLATE), + LEATHER_LEGGINGS(2, 300, Material.LEATHER_LEGGINGS), + LEATHER_BOOTS(1, 301, Material.LEATHER_BOOTS), + CHAINMAIL_HELMET(2, 302, Material.CHAINMAIL_HELMET), + CHAINMAIL_CHESTPLATE(5, 303, Material.CHAINMAIL_CHESTPLATE), + CHAINMAIL_LEGGINGS(4, 304, Material.CHAINMAIL_LEGGINGS), + CHAINMAIL_BOOTS(1, 305, Material.CHAINMAIL_BOOTS), + IRON_HELMET(2, 306, Material.IRON_HELMET), + IRON_CHESTPLATE(6, 307, Material.IRON_CHESTPLATE), + IRON_LEGGINGS(5, 308, Material.IRON_LEGGINGS), + IRON_BOOTS(2, 309, Material.IRON_BOOTS), + DIAMOND_HELMET(3, 310, Material.DIAMOND_HELMET), + DIAMOND_CHESTPLATE(8, 311, Material.DIAMOND_CHESTPLATE), + DIAMOND_LEGGINGS(6, 312, Material.DIAMOND_LEGGINGS), + DIAMOND_BOOTS(3, 313, Material.DIAMOND_BOOTS), + GOLD_HELMET(2, 314, Material.GOLD_HELMET), + GOLD_CHESTPLATE(5, 315, Material.GOLD_CHESTPLATE), + GOLD_LEGGINGS(3, 316, Material.GOLD_LEGGINGS), + GOLD_BOOTS(1, 317, Material.GOLD_BOOTS), + NONE(0, 0, Material.AIR); + + private int armorpoints; + private int id; + private Material type; + + ArmorType(int armor, int id, Material type) { + this.armorpoints = armor; + this.id = id; + this.type = type; + } + + public int getArmorPoints() { + return this.armorpoints; + } + + public int getId() { + return this.id; + } + + public Material getType() { + return this.type; + } + + public static ArmorType findByType(Material type) { + for(ArmorType a : ArmorType.values()) + if(a.getType() == type) + return a; + return ArmorType.NONE; + } + + public static int calculateArmorPoints(ItemStack[] armor) { + int total = 0; + for(int i = 0; i < armor.length; i++) { + if(armor[i] != null) + total += findByType(armor[i].getType()).getArmorPoints(); + } + return total; + } + + public static ArmorType findById(int id) { + for(ArmorType a : ArmorType.values()) + if(a.getId() == id) + return a; + return ArmorType.NONE; + } + + public static boolean isArmor(Material material){ + for(ArmorType a : ArmorType.values()) + if(a.getType() == material) + return true; + return false; + } + + public static int calculateArmorPoints(int[] armor) { + int total = 0; + for(int i = 0; i < armor.length; i++) { + if(armor[i] != -1) + total += findById(armor[i]).getArmorPoints(); + } + return total; + } + +} \ No newline at end of file diff --git a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java index bc4549e85..64fbcf1d3 100644 --- a/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java +++ b/src/main/java/us/myles/ViaVersion/transformers/IncomingTransformer.java @@ -1,26 +1,21 @@ package us.myles.ViaVersion.transformers; -import com.avaje.ebeaninternal.server.cluster.Packet; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -import org.spacehq.opennbt.tag.builtin.ListTag; -import org.spacehq.opennbt.tag.builtin.StringTag; -import org.spacehq.opennbt.tag.builtin.Tag; import us.myles.ViaVersion.CancelException; import us.myles.ViaVersion.ConnectionInfo; import us.myles.ViaVersion.ViaVersionPlugin; -import us.myles.ViaVersion.slot.ItemSlotRewriter; import us.myles.ViaVersion.packets.PacketType; import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.slot.ItemSlotRewriter; import us.myles.ViaVersion.util.PacketUtil; import us.myles.ViaVersion.util.ReflectionUtil; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.nio.charset.Charset; public class IncomingTransformer { private final ConnectionInfo info; @@ -108,6 +103,7 @@ public class IncomingTransformer { byte button = input.readByte(); short action = input.readShort(); byte mode = input.readByte(); + // if the action is on an elytra armour slot if (slot == 45 && windowID == 0) { try { Class setSlot = ReflectionUtil.nms("PacketPlayOutSetSlot"); diff --git a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java index 9609fc1f5..46fcf0556 100644 --- a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java +++ b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java @@ -1,17 +1,12 @@ package us.myles.ViaVersion.transformers; import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import org.bukkit.Material; import org.bukkit.entity.EntityType; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.spacehq.mc.protocol.data.game.chunk.Column; import org.spacehq.mc.protocol.util.NetUtil; -import org.spacehq.opennbt.tag.builtin.ListTag; -import org.spacehq.opennbt.tag.builtin.StringTag; -import org.spacehq.opennbt.tag.builtin.Tag; import us.myles.ViaVersion.CancelException; import us.myles.ViaVersion.ConnectionInfo; import us.myles.ViaVersion.ViaVersionPlugin; @@ -34,6 +29,7 @@ public class OutgoingTransformer { private final ConnectionInfo info; private final ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance(); private boolean cancel = false; + private Map uuidMap = new HashMap(); private Map clientEntityTypes = new HashMap(); private Map vehicleMap = new HashMap<>(); @@ -268,7 +264,7 @@ public class OutgoingTransformer { PacketUtil.writeString(uu, output); UUID uniqueId = UUID.fromString(uu); info.setUUID(uniqueId); - plugin.setPorted(uniqueId, true); + plugin.addPortedClient(info); output.writeBytes(input); return; } @@ -412,7 +408,6 @@ public class OutgoingTransformer { short slot = input.readShort(); output.writeShort(slot); - ItemSlotRewriter.rewrite1_8To1_9(input, output); return; } From 6fe3c15f7d95f1d856132cb72c37f7e28f51290b Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 4 Mar 2016 21:16:12 +0000 Subject: [PATCH 3/4] Remove 1.9 chunk unloading, should fix #38 --- .../transformers/OutgoingTransformer.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java index 46fcf0556..a42cb865d 100644 --- a/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java +++ b/src/main/java/us/myles/ViaVersion/transformers/OutgoingTransformer.java @@ -103,7 +103,7 @@ public class OutgoingTransformer { byte[] b = new byte[input.readableBytes()]; input.readBytes(b); // patch books - if(name.equals("MC|BOpen")){ + if (name.equals("MC|BOpen")) { PacketUtil.writeVarInt(0, output); } output.writeBytes(b); @@ -558,18 +558,18 @@ public class OutgoingTransformer { output.writeBoolean(groundUp); int bitMask = input.readUnsignedShort(); - - if (bitMask == 0 && groundUp) { - output.clear(); - PacketUtil.writeVarInt(PacketType.PLAY_UNLOAD_CHUNK.getNewPacketID(), output); - output.writeInt(chunkX); - output.writeInt(chunkZ); - return; - } int size = PacketUtil.readVarInt(input); - byte[] data = new byte[size]; input.readBytes(data); +// if (bitMask == 0 && groundUp) { +// // if 256 +// output.clear(); +// PacketUtil.writeVarInt(PacketType.PLAY_UNLOAD_CHUNK.getNewPacketID(), output); +// output.writeInt(chunkX); +// output.writeInt(chunkZ); +// System.out.println("Sending unload chunk " + chunkX + " " + chunkZ + " - " + size + " bulk: " + bulk); +// return; +// } boolean sk = false; if (info.getLastPacket().getClass().getName().endsWith("PacketPlayOutMapChunkBulk")) { try { From 89e0948f9778c6efceddbb83ffd95b4665eb64d1 Mon Sep 17 00:00:00 2001 From: Myles Date: Fri, 4 Mar 2016 21:21:51 +0000 Subject: [PATCH 4/4] Updated version to 0.5.0 :) --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b64840faf..398ef32c6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ViaVersion 0.4.9 +# ViaVersion 0.5.0 **Allows the connection of 1.9 clients to 1.8** This plugin modifies netty to allow connection of 1.9 clients to 1.8, diff --git a/pom.xml b/pom.xml index c87afbb2a..a96b8ae20 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ us.myles ViaVersion - 0.4.9 + 0.5.0 ViaVersion-${version}