From cc5bcb8a64cb5f43258d643590417d2920e33d4e Mon Sep 17 00:00:00 2001 From: Myles Date: Thu, 21 Apr 2016 16:19:29 +0100 Subject: [PATCH] Allow NMS packet receiving --- .../protocol1_9to1_8/Protocol1_9TO1_8.java | 2 +- .../protocol1_9to1_8/ViaIdleThread.java | 78 +++++++++++++++---- src/main/resources/config.yml | 2 + 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java index 3fe179b76..abdc74868 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java +++ b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java @@ -106,7 +106,7 @@ public class Protocol1_9TO1_8 extends Protocol { Bukkit.getPluginManager().registerEvents(new PaperPatch(), plugin); } if (plugin.getConfig().getBoolean("simulate-pt", true)) - new ViaIdleThread(plugin.getPortedPlayers()).runTaskTimerAsynchronously(plugin, 1L, 1L); // Updates player's idle status + new ViaIdleThread(plugin.getPortedPlayers()).runTaskTimer(plugin, 1L, 1L); // Updates player's idle status if (plugin.getConfig().getBoolean("item-cache", true)) { new HandItemCache().runTaskTimerAsynchronously(plugin, 2L, 2L); // Updates player's items :) HandItemCache.CACHE = true; diff --git a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java index 25b1dd7f6..a81eca3b0 100644 --- a/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java +++ b/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/ViaIdleThread.java @@ -1,7 +1,11 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8; import io.netty.channel.ChannelHandlerContext; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; +import us.myles.ViaVersion.ViaVersionPlugin; +import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker; @@ -9,18 +13,33 @@ import us.myles.ViaVersion.util.PipelineUtil; import us.myles.ViaVersion.util.ReflectionUtil; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Map; import java.util.UUID; public class ViaIdleThread extends BukkitRunnable { + private static boolean USE_NMS = true; private final Map portedPlayers; - private final Object idlePacket; - private final Object idlePacket2; + // Used for packet mode + private Object idlePacket; + private Object idlePacket2; + // Use for nms + private Method getHandle; + private Field connection; + private Method handleFlying; public ViaIdleThread(Map portedPlayers) { + USE_NMS = ((ViaVersionPlugin) ViaVersion.getInstance()).getConfig().getBoolean("nms-player-ticking", true); + this.portedPlayers = portedPlayers; + Class idlePacketClass; + try { + idlePacketClass = ReflectionUtil.nms("PacketPlayInFlying"); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Couldn't find idle packet, help!", e); + } try { - Class idlePacketClass = ReflectionUtil.nms("PacketPlayInFlying"); idlePacket = idlePacketClass.newInstance(); idlePacket2 = idlePacketClass.newInstance(); @@ -28,26 +47,59 @@ public class ViaIdleThread extends BukkitRunnable { flying.setAccessible(true); flying.set(idlePacket2, true); - } catch (NoSuchFieldException | InstantiationException | IllegalArgumentException | IllegalAccessException | ClassNotFoundException e) { - throw new RuntimeException("Couldn't find/make player idle packet, help!", e); + } catch (NoSuchFieldException | InstantiationException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException("Couldn't make player idle packet, help!", e); + } + if(USE_NMS) { + try { + getHandle = ReflectionUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle"); + } catch (NoSuchMethodException | ClassNotFoundException e) { + throw new RuntimeException("Couldn't find CraftPlayer", e); + } + + try { + connection = ReflectionUtil.nms("EntityPlayer").getDeclaredField("playerConnection"); + } catch (NoSuchFieldException | ClassNotFoundException e) { + throw new RuntimeException("Couldn't find Player Connection", e); + } + + try { + handleFlying = ReflectionUtil.nms("PlayerConnection").getDeclaredMethod("a", idlePacketClass); + } catch (NoSuchMethodException | ClassNotFoundException e) { + throw new RuntimeException("Couldn't find CraftPlayer", e); + } } } - @Override public void run() { for (UserConnection info : portedPlayers.values()) { if (info.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) { long nextIdleUpdate = info.get(MovementTracker.class).getNextIdlePacket(); if (nextIdleUpdate <= System.currentTimeMillis()) { - ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", info.getChannel().pipeline()); if (info.getChannel().isOpen()) { - if (context != null) { - if (info.get(MovementTracker.class).isGround()) { - context.fireChannelRead(idlePacket2); - } else { - context.fireChannelRead(idlePacket); + if (USE_NMS) { + Player player = Bukkit.getPlayer(info.get(ProtocolInfo.class).getUuid()); + try { + // Tick player + Object entityPlayer = getHandle.invoke(player); + Object pc = connection.get(entityPlayer); + handleFlying.invoke(pc, (info.get(MovementTracker.class).isGround() ? idlePacket2 : idlePacket)); + // Tick world + info.get(MovementTracker.class).incrementIdlePacket(); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + } else { + // Old method using packets. + ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", info.getChannel().pipeline()); + if (context != null) { + if (info.get(MovementTracker.class).isGround()) { + context.fireChannelRead(idlePacket2); + } else { + context.fireChannelRead(idlePacket); + } + info.get(MovementTracker.class).incrementIdlePacket(); } - info.get(MovementTracker.class).incrementIdlePacket(); } } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 8264a6d1c..5422bbd55 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -16,6 +16,8 @@ hologram-patch: false hologram-y: -1 # Enable player tick simulation, this fixes eating, drinking, nether portals. simulate-pt: true +# Should we use nms player to simulate packets, (may fix anti-cheat issues) +nms-player-ticking: true # Should we patch boss bars so they work? (Default: true, disable if you're having issues) bossbar-patch: true # If your boss bar flickers on 1.9, set this to 'true'. It will keep all boss bars on 100% (not recommended)