Add required provider for movement (for reflection caching)

This commit is contained in:
Myles 2016-09-25 18:26:14 +01:00
parent 52610f7c66
commit 7a7c3f15d8
7 changed files with 139 additions and 100 deletions

View File

@ -50,8 +50,6 @@ public class BukkitViaLoader implements ViaPlatformLoader {
plugin.getLogger().info("Enabling PaperSpigot/TacoSpigot patch: Fixes block placement.");
new PaperPatch(plugin).register();
}
if (plugin.getConf().isStimulatePlayerTick())
new ViaIdleThread(Via.getManager().getPortedPlayers()).runTaskTimer(plugin, 1L, 1L); // Updates player's idle status
if (plugin.getConf().isItemCache()) {
new HandItemCache().runTaskTimerAsynchronously(plugin, 2L, 2L); // Updates player's items :)
HandItemCache.CACHE = true;

View File

@ -0,0 +1,99 @@
package us.myles.ViaVersion.bukkit;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class BukkitViaMovementTransmitter extends MovementTransmitterProvider {
private static boolean USE_NMS = true;
// Used for packet mode
private Object idlePacket;
private Object idlePacket2;
// Use for nms
private Method getHandle;
private Field connection;
private Method handleFlying;
public BukkitViaMovementTransmitter() {
USE_NMS = Via.getConfig().isNMSPlayerTicking();
Class<?> idlePacketClass;
try {
idlePacketClass = ReflectionUtil.nms("PacketPlayInFlying");
} catch (ClassNotFoundException e) {
throw new RuntimeException("Couldn't find idle packet, help!", e);
}
try {
idlePacket = idlePacketClass.newInstance();
idlePacket2 = idlePacketClass.newInstance();
Field flying = idlePacketClass.getDeclaredField("f");
flying.setAccessible(true);
flying.set(idlePacket2, true);
} 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 Object getFlyingPacket() {
return idlePacket2;
}
@Override
public Object getGroundPacket() {
return idlePacket;
}
@Override
public void sendPlayer(UserConnection info) {
if (USE_NMS) {
Player player = Bukkit.getPlayer(info.get(ProtocolInfo.class).getUuid());
if (player != null) {
try {
// Tick player
Object entityPlayer = getHandle.invoke(player);
Object pc = connection.get(entityPlayer);
if (pc != null) {
handleFlying.invoke(pc, (info.get(MovementTracker.class).isGround() ? idlePacket2 : idlePacket));
// Tick world
info.get(MovementTracker.class).incrementIdlePacket();
}
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
} else {
super.sendPlayer(info);
}
}
}

View File

@ -23,6 +23,8 @@ public interface ViaPlatform<T> {
public void runSync(Runnable runnable);
public void runRepeatingSync(Runnable runnable, Long ticks);
public ViaCommandSender[] getOnlinePlayers();
public void sendMessage(UUID uuid, String message);

View File

@ -57,11 +57,11 @@ public abstract class Protocol {
}
/**
* Register providers for this protocol
* Handle protocol registration phase, use this to register providers / tasks.
*
* @param providers The current providers
*/
protected void registerProviders(ViaProviders providers) {
protected void register(ViaProviders providers) {
}
/**

View File

@ -16,6 +16,7 @@ import us.myles.ViaVersion.api.type.types.version.Metadata1_8Type;
import us.myles.ViaVersion.api.type.types.version.MetadataList1_8Type;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.packets.*;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.HandItemProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.*;
import java.util.List;
@ -78,8 +79,12 @@ public class Protocol1_9TO1_8 extends Protocol {
}
@Override
protected void registerProviders(ViaProviders providers) {
protected void register(ViaProviders providers) {
providers.register(HandItemProvider.class, new HandItemProvider());
providers.require(MovementTransmitterProvider.class);
if (Via.getConfig().isStimulatePlayerTick()) {
Via.getPlatform().runRepeatingSync(new ViaIdleThread(), 1L);
}
}
@Override

View File

@ -1,111 +1,20 @@
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.api.Via;
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.providers.MovementTransmitterProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
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;
// 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 = Via.getConfig().isNMSPlayerTicking();
this.portedPlayers = portedPlayers;
Class<?> idlePacketClass;
try {
idlePacketClass = ReflectionUtil.nms("PacketPlayInFlying");
} catch (ClassNotFoundException e) {
throw new RuntimeException("Couldn't find idle packet, help!", e);
}
try {
idlePacket = idlePacketClass.newInstance();
idlePacket2 = idlePacketClass.newInstance();
Field flying = idlePacketClass.getDeclaredField("f");
flying.setAccessible(true);
flying.set(idlePacket2, true);
} 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);
}
}
}
public class ViaIdleThread implements Runnable {
@Override
public void run() {
for (UserConnection info : portedPlayers.values()) {
for (UserConnection info : Via.getManager().getPortedPlayers().values()) {
if (info.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) {
long nextIdleUpdate = info.get(MovementTracker.class).getNextIdlePacket();
if (nextIdleUpdate <= System.currentTimeMillis()) {
if (info.getChannel().isOpen()) {
if (USE_NMS) {
Player player = Bukkit.getPlayer(info.get(ProtocolInfo.class).getUuid());
if (player != null) {
try {
// Tick player
Object entityPlayer = getHandle.invoke(player);
Object pc = connection.get(entityPlayer);
if (pc != null) {
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();
}
}
Via.getManager().getProviders().get(MovementTransmitterProvider.class).sendPlayer(info);
}
}
}

View File

@ -0,0 +1,26 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.providers;
import io.netty.channel.ChannelHandlerContext;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.platform.providers.Provider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
import us.myles.ViaVersion.util.PipelineUtil;
public abstract class MovementTransmitterProvider implements Provider {
public abstract Object getFlyingPacket();
public abstract Object getGroundPacket();
public void sendPlayer(UserConnection userConnection) {
// Old method using packets.
ChannelHandlerContext context = PipelineUtil.getContextBefore("decoder", userConnection.getChannel().pipeline());
if (context != null) {
if (userConnection.get(MovementTracker.class).isGround()) {
context.fireChannelRead(getGroundPacket());
} else {
context.fireChannelRead(getFlyingPacket());
}
userConnection.get(MovementTracker.class).incrementIdlePacket();
}
}
}