mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2024-11-25 11:35:18 +01:00
Change reflection to NMSUtil, and start work on Bungee (doesn't work)
This commit is contained in:
parent
42efc736c3
commit
42edffb309
@ -17,6 +17,7 @@ import us.myles.ViaVersion.api.platform.ViaPlatform;
|
||||
import us.myles.ViaVersion.bukkit.*;
|
||||
import us.myles.ViaVersion.classgenerator.ClassGenerator;
|
||||
import us.myles.ViaVersion.dump.PluginInfo;
|
||||
import us.myles.ViaVersion.util.NMSUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -76,7 +77,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform {
|
||||
|
||||
// Check if it's a spigot build with a protocol mod
|
||||
try {
|
||||
compatSpigotBuild = ReflectionUtil.nms("PacketEncoder").getDeclaredField("version") != null;
|
||||
compatSpigotBuild = NMSUtil.nms("PacketEncoder").getDeclaredField("version") != null;
|
||||
} catch (Exception e) {
|
||||
compatSpigotBuild = false;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import us.myles.ViaVersion.util.NMSUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@ -19,10 +20,10 @@ public class BukkitViaBulkChunkTranslator extends BulkChunkTranslatorProvider {
|
||||
|
||||
static {
|
||||
try {
|
||||
mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk"));
|
||||
mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk"));
|
||||
mapChunkBulkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunkBulk"));
|
||||
mapChunkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunk"));
|
||||
if (((ViaVersionPlugin) Via.getPlatform()).isSpigot()) {
|
||||
obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, ReflectionUtil.nms("World"));
|
||||
obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, NMSUtil.nms("World"));
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Ignore as server is probably 1.9+
|
||||
|
@ -11,6 +11,7 @@ import us.myles.ViaVersion.api.platform.ViaInjector;
|
||||
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
||||
import us.myles.ViaVersion.util.ConcurrentList;
|
||||
import us.myles.ViaVersion.util.ListWrapper;
|
||||
import us.myles.ViaVersion.util.NMSUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@ -128,9 +129,9 @@ public class BukkitViaInjector implements ViaInjector {
|
||||
@Override
|
||||
public int getServerProtocolVersion() throws Exception {
|
||||
try {
|
||||
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
|
||||
Class<?> serverClazz = NMSUtil.nms("MinecraftServer");
|
||||
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
||||
Class<?> pingClazz = ReflectionUtil.nms("ServerPing");
|
||||
Class<?> pingClazz = NMSUtil.nms("ServerPing");
|
||||
Object ping = null;
|
||||
// Search for ping method
|
||||
for (Field f : serverClazz.getDeclaredFields()) {
|
||||
@ -173,7 +174,7 @@ public class BukkitViaInjector implements ViaInjector {
|
||||
}
|
||||
|
||||
public static Object getServerConnection() throws Exception {
|
||||
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
|
||||
Class<?> serverClazz = NMSUtil.nms("MinecraftServer");
|
||||
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
||||
Object connection = null;
|
||||
for (Method m : serverClazz.getDeclaredMethods()) {
|
||||
|
@ -7,6 +7,7 @@ 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.NMSUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@ -28,7 +29,7 @@ public class BukkitViaMovementTransmitter extends MovementTransmitterProvider {
|
||||
|
||||
Class<?> idlePacketClass;
|
||||
try {
|
||||
idlePacketClass = ReflectionUtil.nms("PacketPlayInFlying");
|
||||
idlePacketClass = NMSUtil.nms("PacketPlayInFlying");
|
||||
} catch (ClassNotFoundException e) {
|
||||
return; // We'll hope this is 1.9.4+
|
||||
}
|
||||
@ -45,19 +46,19 @@ public class BukkitViaMovementTransmitter extends MovementTransmitterProvider {
|
||||
}
|
||||
if (USE_NMS) {
|
||||
try {
|
||||
getHandle = ReflectionUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
|
||||
getHandle = NMSUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
||||
}
|
||||
|
||||
try {
|
||||
connection = ReflectionUtil.nms("EntityPlayer").getDeclaredField("playerConnection");
|
||||
connection = NMSUtil.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);
|
||||
handleFlying = NMSUtil.nms("PlayerConnection").getDeclaredMethod("a", idlePacketClass);
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import org.bukkit.plugin.Plugin;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
|
||||
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
|
||||
import us.myles.ViaVersion.util.NMSUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
public class ClassGenerator {
|
||||
@ -27,8 +28,8 @@ public class ClassGenerator {
|
||||
}
|
||||
|
||||
if (ViaVersion.getInstance().isCompatSpigotBuild()) {
|
||||
Class decodeSuper = ReflectionUtil.nms("PacketDecoder");
|
||||
Class encodeSuper = ReflectionUtil.nms("PacketEncoder");
|
||||
Class decodeSuper = NMSUtil.nms("PacketDecoder");
|
||||
Class encodeSuper = NMSUtil.nms("PacketEncoder");
|
||||
// Generate the classes
|
||||
addSpigotCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
|
||||
addSpigotCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
|
||||
|
@ -23,6 +23,7 @@ import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.minecraft.Position;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.util.NMSUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.io.DataOutput;
|
||||
@ -88,7 +89,7 @@ public class CommandBlockListener extends ViaListener {
|
||||
return;
|
||||
CommandBlock cmd = (CommandBlock) b.getState();
|
||||
|
||||
Object tileEntityCommand = ReflectionUtil.get(cmd, "commandBlock", ReflectionUtil.nms("TileEntityCommand"));
|
||||
Object tileEntityCommand = ReflectionUtil.get(cmd, "commandBlock", NMSUtil.nms("TileEntityCommand"));
|
||||
Object updatePacket = ReflectionUtil.invoke(tileEntityCommand, "getUpdatePacket");
|
||||
|
||||
PacketWrapper wrapper = generatePacket(updatePacket, getUserConnection(player));
|
||||
@ -98,12 +99,12 @@ public class CommandBlockListener extends ViaListener {
|
||||
private PacketWrapper generatePacket(Object updatePacket, UserConnection usr) throws Exception {
|
||||
PacketWrapper wrapper = new PacketWrapper(0x09, null, usr); // Update block entity
|
||||
|
||||
long[] pos = getPosition(ReflectionUtil.get(updatePacket, "a", ReflectionUtil.nms("BlockPosition")));
|
||||
long[] pos = getPosition(ReflectionUtil.get(updatePacket, "a", NMSUtil.nms("BlockPosition")));
|
||||
|
||||
wrapper.write(Type.POSITION, new Position(pos[0], pos[1], pos[2])); //Block position
|
||||
wrapper.write(Type.BYTE, (byte) 2); // Action id always 2
|
||||
|
||||
CompoundTag nbt = getNBT(ReflectionUtil.get(updatePacket, "c", ReflectionUtil.nms("NBTTagCompound")));
|
||||
CompoundTag nbt = getNBT(ReflectionUtil.get(updatePacket, "c", NMSUtil.nms("NBTTagCompound")));
|
||||
if (nbt == null) {
|
||||
wrapper.write(Type.BYTE, (byte) 0); //If nbt is null. Use 0 as nbt
|
||||
return wrapper;
|
||||
@ -125,12 +126,12 @@ public class CommandBlockListener extends ViaListener {
|
||||
}
|
||||
|
||||
private boolean isR1() {
|
||||
return ReflectionUtil.getVersion().equals("v1_8_R1");
|
||||
return NMSUtil.getVersion().equals("v1_8_R1");
|
||||
}
|
||||
|
||||
private CompoundTag getNBT(Object obj) throws Exception {
|
||||
ByteBuf buf = Unpooled.buffer();
|
||||
Method m = ReflectionUtil.nms("NBTCompressedStreamTools").getMethod("a", ReflectionUtil.nms("NBTTagCompound"), DataOutput.class);
|
||||
Method m = NMSUtil.nms("NBTCompressedStreamTools").getMethod("a", NMSUtil.nms("NBTTagCompound"), DataOutput.class);
|
||||
m.invoke(null, obj, new DataOutputStream(new ByteBufOutputStream(buf)));
|
||||
try {
|
||||
return Type.NBT.read(buf);
|
||||
|
20
bukkit/src/main/java/us/myles/ViaVersion/util/NMSUtil.java
Normal file
20
bukkit/src/main/java/us/myles/ViaVersion/util/NMSUtil.java
Normal file
@ -0,0 +1,20 @@
|
||||
package us.myles.ViaVersion.util;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class NMSUtil {
|
||||
private static String BASE = Bukkit.getServer().getClass().getPackage().getName();
|
||||
private static String NMS = BASE.replace("org.bukkit.craftbukkit", "net.minecraft.server");
|
||||
|
||||
public static Class<?> nms(String className) throws ClassNotFoundException {
|
||||
return Class.forName(NMS + "." + className);
|
||||
}
|
||||
|
||||
public static Class<?> obc(String className) throws ClassNotFoundException {
|
||||
return Class.forName(BASE + "." + className);
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return BASE.substring(BASE.lastIndexOf('.') + 1);
|
||||
}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
package us.myles.ViaVersion.util;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class ReflectionUtil {
|
||||
private static String BASE = Bukkit.getServer().getClass().getPackage().getName();
|
||||
private static String NMS = BASE.replace("org.bukkit.craftbukkit", "net.minecraft.server");
|
||||
|
||||
public static Class<?> nms(String className) throws ClassNotFoundException {
|
||||
return Class.forName(NMS + "." + className);
|
||||
}
|
||||
|
||||
public static Class<?> obc(String className) throws ClassNotFoundException {
|
||||
return Class.forName(BASE + "." + className);
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return BASE.substring(BASE.lastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
public static Object invokeStatic(Class<?> clazz, String method) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
Method m = clazz.getDeclaredMethod(method);
|
||||
return m.invoke(null);
|
||||
}
|
||||
|
||||
public static Object invoke(Object o, String method) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
Method m = o.getClass().getDeclaredMethod(method);
|
||||
return m.invoke(o);
|
||||
}
|
||||
|
||||
public static <T> T getStatic(Class<?> clazz, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = clazz.getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
return (T) field.get(null);
|
||||
}
|
||||
|
||||
public static <T> T getSuper(Object o, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getSuperclass().getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
return (T) field.get(o);
|
||||
}
|
||||
|
||||
public static <T> T get(Object instance, Class<?> clazz, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = clazz.getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
return (T) field.get(instance);
|
||||
}
|
||||
|
||||
public static <T> T get(Object o, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
return (T) field.get(o);
|
||||
}
|
||||
|
||||
public static <T> T getPublic(Object o, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getField(f);
|
||||
field.setAccessible(true);
|
||||
return (T) field.get(o);
|
||||
}
|
||||
|
||||
|
||||
public static void set(Object o, String f, Object value) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
field.set(o, value);
|
||||
}
|
||||
|
||||
public static final class ClassReflection {
|
||||
private final Class<?> handle;
|
||||
private final Map<String, Field> fields = Maps.newConcurrentMap();
|
||||
private final Map<String, Method> methods = Maps.newConcurrentMap();
|
||||
|
||||
public ClassReflection(Class<?> handle) {
|
||||
this(handle, true);
|
||||
}
|
||||
|
||||
public ClassReflection(Class<?> handle, boolean recursive) {
|
||||
this.handle = handle;
|
||||
scanFields(handle, recursive);
|
||||
scanMethods(handle, recursive);
|
||||
}
|
||||
|
||||
private void scanFields(Class<?> host, boolean recursive) {
|
||||
if (host.getSuperclass() != null && recursive) {
|
||||
scanFields(host.getSuperclass(), true);
|
||||
}
|
||||
|
||||
for (Field field : host.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
fields.put(field.getName(), field);
|
||||
}
|
||||
}
|
||||
|
||||
private void scanMethods(Class<?> host, boolean recursive) {
|
||||
if (host.getSuperclass() != null && recursive) {
|
||||
scanMethods(host.getSuperclass(), true);
|
||||
}
|
||||
|
||||
for (Method method : host.getDeclaredMethods()) {
|
||||
method.setAccessible(true);
|
||||
methods.put(method.getName(), method);
|
||||
}
|
||||
}
|
||||
|
||||
public Object newInstance() throws IllegalAccessException, InstantiationException {
|
||||
return handle.newInstance();
|
||||
}
|
||||
|
||||
public Field getField(String name) {
|
||||
return fields.get(name);
|
||||
}
|
||||
|
||||
public void setFieldValue(String fieldName, Object instance, Object value) throws IllegalAccessException {
|
||||
getField(fieldName).set(instance, value);
|
||||
}
|
||||
|
||||
public <T> T getFieldValue(String fieldName, Object instance, Class<T> type) throws IllegalAccessException {
|
||||
return type.cast(getField(fieldName).get(instance));
|
||||
}
|
||||
|
||||
public <T> T invokeMethod(Class<T> type, String methodName, Object instance, Object... args) throws InvocationTargetException, IllegalAccessException {
|
||||
return type.cast(getMethod(methodName).invoke(instance, args));
|
||||
}
|
||||
|
||||
public Method getMethod(String name) {
|
||||
return methods.get(name);
|
||||
}
|
||||
|
||||
public Collection<Field> getFields() {
|
||||
return Collections.unmodifiableCollection(fields.values());
|
||||
}
|
||||
|
||||
public Collection<Method> getMethods() {
|
||||
return Collections.unmodifiableCollection(methods.values());
|
||||
}
|
||||
}
|
||||
}
|
@ -25,18 +25,23 @@
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- BungeeCord -->
|
||||
<!-- BungeeCord API -->
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.10-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- BungeeCord Proxy -->
|
||||
<dependency>
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion-common</artifactId>
|
||||
<version>1.0.0-ALPHA-modules</version>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>1.4.7-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Common Module -->
|
||||
<dependency>
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion-common</artifactId>
|
||||
|
@ -28,10 +28,7 @@ public class Bungee extends Plugin implements ViaPlatform {
|
||||
public void onLoad() {
|
||||
api = new BungeeViaAPI();
|
||||
config = new BungeeConfigProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Init platform
|
||||
Via.init(ViaManager.builder()
|
||||
.platform(this)
|
||||
.injector(new BungeeViaInjector())
|
||||
@ -39,6 +36,12 @@ public class Bungee extends Plugin implements ViaPlatform {
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Inject
|
||||
Via.getManager().init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName() {
|
||||
return "BungeeCord";
|
||||
|
@ -1,18 +1,38 @@
|
||||
package us.myles.ViaVersion.bungee;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.platform.ViaInjector;
|
||||
import us.myles.ViaVersion.bungee.handlers.ViaVersionInitializer;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
public class BungeeViaInjector implements ViaInjector {
|
||||
@Override
|
||||
public void inject() throws Exception {
|
||||
try {
|
||||
try {
|
||||
ChannelInitializer<Channel> oldInit = PipelineUtils.SERVER_CHILD;
|
||||
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
|
||||
|
||||
ReflectionUtil.setStatic(PipelineUtils.class, "SERVER_CHILD", newInit);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new Exception("Unable to find core component 'childHandler', please check your plugins. issue: ");
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Via.getPlatform().getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version.");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void uninject() throws Exception {
|
||||
|
||||
public void uninject() {
|
||||
// TODO: Uninject from players currently online
|
||||
Via.getPlatform().getLogger().severe("ViaVersion cannot remove itself from Bungee without a reboot!");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getServerProtocolVersion() throws Exception {
|
||||
return 47;
|
||||
|
@ -0,0 +1,89 @@
|
||||
package us.myles.ViaVersion.bungee.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.util.PipelineUtil;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
public class ViaDecodeHandler extends ByteToMessageDecoder {
|
||||
|
||||
private final ByteToMessageDecoder minecraftDecoder;
|
||||
private final UserConnection info;
|
||||
|
||||
public ViaDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
|
||||
this.info = info;
|
||||
this.minecraftDecoder = minecraftDecoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> list) throws Exception {
|
||||
// use transformers
|
||||
if (bytebuf.readableBytes() > 0) {
|
||||
// Ignore if pending disconnect
|
||||
if (info.isPendingDisconnect()) {
|
||||
return;
|
||||
}
|
||||
// Increment received
|
||||
boolean second = info.incrementReceived();
|
||||
// Check PPS
|
||||
if (second) {
|
||||
if (info.handlePPS())
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.isActive()) {
|
||||
// Handle ID
|
||||
int id = Type.VAR_INT.read(bytebuf);
|
||||
// Transform
|
||||
ByteBuf newPacket = ctx.alloc().buffer();
|
||||
try {
|
||||
if (id == PacketWrapper.PASSTHROUGH_ID) {
|
||||
newPacket.writeBytes(bytebuf);
|
||||
} else {
|
||||
PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info);
|
||||
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
|
||||
protInfo.getPipeline().transform(Direction.INCOMING, protInfo.getState(), wrapper);
|
||||
wrapper.writeToBuffer(newPacket);
|
||||
}
|
||||
|
||||
bytebuf.clear();
|
||||
bytebuf = newPacket;
|
||||
} catch (Exception e) {
|
||||
// Clear Buffer
|
||||
bytebuf.clear();
|
||||
// Release Packet, be free!
|
||||
newPacket.release();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// call minecraft decoder
|
||||
try {
|
||||
list.addAll(PipelineUtil.callDecode(this.minecraftDecoder, ctx, bytebuf));
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getCause() instanceof Exception) {
|
||||
throw (Exception) e.getCause();
|
||||
}
|
||||
} finally {
|
||||
if (info.isActive()) {
|
||||
bytebuf.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (PipelineUtil.containsCause(cause, CancelException.class)) return;
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package us.myles.ViaVersion.bungee.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.util.PipelineUtil;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class ViaEncodeHandler extends MessageToByteEncoder {
|
||||
private final UserConnection info;
|
||||
private final MessageToByteEncoder minecraftEncoder;
|
||||
|
||||
public ViaEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
|
||||
this.info = info;
|
||||
this.minecraftEncoder = minecraftEncoder;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception {
|
||||
// handle the packet type
|
||||
if (!(o instanceof ByteBuf)) {
|
||||
// call minecraft encoder
|
||||
try {
|
||||
PipelineUtil.callEncode(this.minecraftEncoder, ctx, o, bytebuf);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getCause() instanceof Exception) {
|
||||
throw (Exception) e.getCause();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bytebuf.readableBytes() == 0) {
|
||||
throw new CancelException();
|
||||
}
|
||||
// Increment sent
|
||||
info.incrementSent();
|
||||
if (info.isActive()) {
|
||||
// Handle ID
|
||||
int id = Type.VAR_INT.read(bytebuf);
|
||||
// Transform
|
||||
ByteBuf oldPacket = bytebuf.copy();
|
||||
bytebuf.clear();
|
||||
|
||||
try {
|
||||
PacketWrapper wrapper = new PacketWrapper(id, oldPacket, info);
|
||||
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
|
||||
protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper);
|
||||
wrapper.writeToBuffer(bytebuf);
|
||||
} catch (Exception e) {
|
||||
bytebuf.clear();
|
||||
throw e;
|
||||
} finally {
|
||||
oldPacket.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (PipelineUtil.containsCause(cause, CancelException.class)) return;
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package us.myles.ViaVersion.bungee.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ViaPacketHandler extends MessageToMessageEncoder {
|
||||
private final UserConnection info;
|
||||
|
||||
public ViaPacketHandler(UserConnection info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, Object o, List list) throws Exception {
|
||||
// Split chunks bulk packet up in to single chunks packets before it reached the encoder.
|
||||
// This will prevent issues with several plugins and other protocol handlers due to the chunks being sent twice.
|
||||
// It also sends the chunks in the right order possible resolving some issues with added chunks/block/entity data.
|
||||
if (!(o instanceof ByteBuf)) {
|
||||
info.setLastPacket(o);
|
||||
/* This transformer is more for fixing issues which we find hard at packet level :) */
|
||||
if (info.isActive()) {
|
||||
if (info.get(ProtocolInfo.class).getPipeline().filter(o, list)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list.add(o);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package us.myles.ViaVersion.bungee.handlers;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
|
||||
|
||||
private final ChannelInitializer<Channel> original;
|
||||
private Method method;
|
||||
|
||||
public ViaVersionInitializer(ChannelInitializer<Channel> oldInit) {
|
||||
this.original = oldInit;
|
||||
try {
|
||||
this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
|
||||
this.method.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelInitializer<Channel> getOriginal() {
|
||||
return original;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||
UserConnection info = new UserConnection(socketChannel);
|
||||
// init protocol
|
||||
new ProtocolPipeline(info);
|
||||
// Add originals
|
||||
this.method.invoke(this.original, socketChannel);
|
||||
// Add our transformers
|
||||
MessageToByteEncoder encoder = new ViaEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder"));
|
||||
ByteToMessageDecoder decoder = new ViaDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder"));
|
||||
ViaPacketHandler chunkHandler = new ViaPacketHandler(info);
|
||||
|
||||
socketChannel.pipeline().replace("encoder", "encoder", encoder);
|
||||
socketChannel.pipeline().replace("decoder", "decoder", decoder);
|
||||
socketChannel.pipeline().addAfter("packet_handler", "viaversion_packet_handler", chunkHandler);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package us.myles.ViaVersion.sponge.util;
|
||||
package us.myles.ViaVersion.util;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
@ -27,6 +27,12 @@ public class ReflectionUtil {
|
||||
return (T) field.get(null);
|
||||
}
|
||||
|
||||
public static void setStatic(Class<?> clazz, String f, Object value) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = clazz.getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
field.set(null, value);
|
||||
}
|
||||
|
||||
public static <T> T getSuper(Object o, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = o.getClass().getSuperclass().getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
@ -58,6 +64,7 @@ public class ReflectionUtil {
|
||||
field.set(o, value);
|
||||
}
|
||||
|
||||
|
||||
public static final class ClassReflection {
|
||||
private final Class<?> handle;
|
||||
private final Map<String, Field> fields = Maps.newConcurrentMap();
|
@ -10,12 +10,11 @@ import us.myles.ViaVersion.api.Pair;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.platform.ViaInjector;
|
||||
import us.myles.ViaVersion.sponge.handlers.ViaVersionInitializer;
|
||||
import us.myles.ViaVersion.sponge.util.ReflectionUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
import us.myles.ViaVersion.util.ListWrapper;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -4,7 +4,7 @@ import com.google.common.collect.Lists;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import us.myles.ViaVersion.sponge.util.ReflectionUtil;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
Loading…
Reference in New Issue
Block a user