Allow NMS packet receiving

This commit is contained in:
Myles 2016-04-21 16:19:29 +01:00
parent b6794f5597
commit cc5bcb8a64
3 changed files with 68 additions and 14 deletions

View File

@ -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;

View File

@ -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<UUID, UserConnection> 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<UUID, UserConnection> 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();
}
}
}

View File

@ -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)