mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2024-11-29 05:26:23 +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.bukkit.*;
|
||||||
import us.myles.ViaVersion.classgenerator.ClassGenerator;
|
import us.myles.ViaVersion.classgenerator.ClassGenerator;
|
||||||
import us.myles.ViaVersion.dump.PluginInfo;
|
import us.myles.ViaVersion.dump.PluginInfo;
|
||||||
|
import us.myles.ViaVersion.util.NMSUtil;
|
||||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
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
|
// Check if it's a spigot build with a protocol mod
|
||||||
try {
|
try {
|
||||||
compatSpigotBuild = ReflectionUtil.nms("PacketEncoder").getDeclaredField("version") != null;
|
compatSpigotBuild = NMSUtil.nms("PacketEncoder").getDeclaredField("version") != null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
compatSpigotBuild = false;
|
compatSpigotBuild = false;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import us.myles.ViaVersion.ViaVersionPlugin;
|
|||||||
import us.myles.ViaVersion.api.Via;
|
import us.myles.ViaVersion.api.Via;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
|
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||||
|
import us.myles.ViaVersion.util.NMSUtil;
|
||||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
@ -19,10 +20,10 @@ public class BukkitViaBulkChunkTranslator extends BulkChunkTranslatorProvider {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk"));
|
mapChunkBulkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunkBulk"));
|
||||||
mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk"));
|
mapChunkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunk"));
|
||||||
if (((ViaVersionPlugin) Via.getPlatform()).isSpigot()) {
|
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) {
|
} catch (ClassNotFoundException e) {
|
||||||
// Ignore as server is probably 1.9+
|
// 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.handlers.ViaVersionInitializer;
|
||||||
import us.myles.ViaVersion.util.ConcurrentList;
|
import us.myles.ViaVersion.util.ConcurrentList;
|
||||||
import us.myles.ViaVersion.util.ListWrapper;
|
import us.myles.ViaVersion.util.ListWrapper;
|
||||||
|
import us.myles.ViaVersion.util.NMSUtil;
|
||||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -128,9 +129,9 @@ public class BukkitViaInjector implements ViaInjector {
|
|||||||
@Override
|
@Override
|
||||||
public int getServerProtocolVersion() throws Exception {
|
public int getServerProtocolVersion() throws Exception {
|
||||||
try {
|
try {
|
||||||
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
|
Class<?> serverClazz = NMSUtil.nms("MinecraftServer");
|
||||||
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
||||||
Class<?> pingClazz = ReflectionUtil.nms("ServerPing");
|
Class<?> pingClazz = NMSUtil.nms("ServerPing");
|
||||||
Object ping = null;
|
Object ping = null;
|
||||||
// Search for ping method
|
// Search for ping method
|
||||||
for (Field f : serverClazz.getDeclaredFields()) {
|
for (Field f : serverClazz.getDeclaredFields()) {
|
||||||
@ -173,7 +174,7 @@ public class BukkitViaInjector implements ViaInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Object getServerConnection() throws Exception {
|
public static Object getServerConnection() throws Exception {
|
||||||
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
|
Class<?> serverClazz = NMSUtil.nms("MinecraftServer");
|
||||||
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
||||||
Object connection = null;
|
Object connection = null;
|
||||||
for (Method m : serverClazz.getDeclaredMethods()) {
|
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.base.ProtocolInfo;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
|
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
|
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
|
||||||
|
import us.myles.ViaVersion.util.NMSUtil;
|
||||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -28,7 +29,7 @@ public class BukkitViaMovementTransmitter extends MovementTransmitterProvider {
|
|||||||
|
|
||||||
Class<?> idlePacketClass;
|
Class<?> idlePacketClass;
|
||||||
try {
|
try {
|
||||||
idlePacketClass = ReflectionUtil.nms("PacketPlayInFlying");
|
idlePacketClass = NMSUtil.nms("PacketPlayInFlying");
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
return; // We'll hope this is 1.9.4+
|
return; // We'll hope this is 1.9.4+
|
||||||
}
|
}
|
||||||
@ -45,19 +46,19 @@ public class BukkitViaMovementTransmitter extends MovementTransmitterProvider {
|
|||||||
}
|
}
|
||||||
if (USE_NMS) {
|
if (USE_NMS) {
|
||||||
try {
|
try {
|
||||||
getHandle = ReflectionUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
|
getHandle = NMSUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
|
||||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||||
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connection = ReflectionUtil.nms("EntityPlayer").getDeclaredField("playerConnection");
|
connection = NMSUtil.nms("EntityPlayer").getDeclaredField("playerConnection");
|
||||||
} catch (NoSuchFieldException | ClassNotFoundException e) {
|
} catch (NoSuchFieldException | ClassNotFoundException e) {
|
||||||
throw new RuntimeException("Couldn't find Player Connection", e);
|
throw new RuntimeException("Couldn't find Player Connection", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
handleFlying = ReflectionUtil.nms("PlayerConnection").getDeclaredMethod("a", idlePacketClass);
|
handleFlying = NMSUtil.nms("PlayerConnection").getDeclaredMethod("a", idlePacketClass);
|
||||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||||
throw new RuntimeException("Couldn't find CraftPlayer", 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.api.ViaVersion;
|
||||||
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
|
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
|
||||||
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
|
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
|
||||||
|
import us.myles.ViaVersion.util.NMSUtil;
|
||||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
public class ClassGenerator {
|
public class ClassGenerator {
|
||||||
@ -27,8 +28,8 @@ public class ClassGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ViaVersion.getInstance().isCompatSpigotBuild()) {
|
if (ViaVersion.getInstance().isCompatSpigotBuild()) {
|
||||||
Class decodeSuper = ReflectionUtil.nms("PacketDecoder");
|
Class decodeSuper = NMSUtil.nms("PacketDecoder");
|
||||||
Class encodeSuper = ReflectionUtil.nms("PacketEncoder");
|
Class encodeSuper = NMSUtil.nms("PacketEncoder");
|
||||||
// Generate the classes
|
// Generate the classes
|
||||||
addSpigotCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
|
addSpigotCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
|
||||||
addSpigotCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
|
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.minecraft.Position;
|
||||||
import us.myles.ViaVersion.api.type.Type;
|
import us.myles.ViaVersion.api.type.Type;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||||
|
import us.myles.ViaVersion.util.NMSUtil;
|
||||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
@ -88,7 +89,7 @@ public class CommandBlockListener extends ViaListener {
|
|||||||
return;
|
return;
|
||||||
CommandBlock cmd = (CommandBlock) b.getState();
|
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");
|
Object updatePacket = ReflectionUtil.invoke(tileEntityCommand, "getUpdatePacket");
|
||||||
|
|
||||||
PacketWrapper wrapper = generatePacket(updatePacket, getUserConnection(player));
|
PacketWrapper wrapper = generatePacket(updatePacket, getUserConnection(player));
|
||||||
@ -98,12 +99,12 @@ public class CommandBlockListener extends ViaListener {
|
|||||||
private PacketWrapper generatePacket(Object updatePacket, UserConnection usr) throws Exception {
|
private PacketWrapper generatePacket(Object updatePacket, UserConnection usr) throws Exception {
|
||||||
PacketWrapper wrapper = new PacketWrapper(0x09, null, usr); // Update block entity
|
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.POSITION, new Position(pos[0], pos[1], pos[2])); //Block position
|
||||||
wrapper.write(Type.BYTE, (byte) 2); // Action id always 2
|
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) {
|
if (nbt == null) {
|
||||||
wrapper.write(Type.BYTE, (byte) 0); //If nbt is null. Use 0 as nbt
|
wrapper.write(Type.BYTE, (byte) 0); //If nbt is null. Use 0 as nbt
|
||||||
return wrapper;
|
return wrapper;
|
||||||
@ -125,12 +126,12 @@ public class CommandBlockListener extends ViaListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isR1() {
|
private boolean isR1() {
|
||||||
return ReflectionUtil.getVersion().equals("v1_8_R1");
|
return NMSUtil.getVersion().equals("v1_8_R1");
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompoundTag getNBT(Object obj) throws Exception {
|
private CompoundTag getNBT(Object obj) throws Exception {
|
||||||
ByteBuf buf = Unpooled.buffer();
|
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)));
|
m.invoke(null, obj, new DataOutputStream(new ByteBufOutputStream(buf)));
|
||||||
try {
|
try {
|
||||||
return Type.NBT.read(buf);
|
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>
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- BungeeCord -->
|
<!-- BungeeCord API -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-api</artifactId>
|
<artifactId>bungeecord-api</artifactId>
|
||||||
<version>1.10-SNAPSHOT</version>
|
<version>1.10-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- BungeeCord Proxy -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>us.myles</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>viaversion-common</artifactId>
|
<artifactId>bungeecord-proxy</artifactId>
|
||||||
<version>1.0.0-ALPHA-modules</version>
|
<version>1.4.7-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Common Module -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>us.myles</groupId>
|
<groupId>us.myles</groupId>
|
||||||
<artifactId>viaversion-common</artifactId>
|
<artifactId>viaversion-common</artifactId>
|
||||||
|
@ -28,10 +28,7 @@ public class Bungee extends Plugin implements ViaPlatform {
|
|||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
api = new BungeeViaAPI();
|
api = new BungeeViaAPI();
|
||||||
config = new BungeeConfigProvider();
|
config = new BungeeConfigProvider();
|
||||||
}
|
// Init platform
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnable() {
|
|
||||||
Via.init(ViaManager.builder()
|
Via.init(ViaManager.builder()
|
||||||
.platform(this)
|
.platform(this)
|
||||||
.injector(new BungeeViaInjector())
|
.injector(new BungeeViaInjector())
|
||||||
@ -39,6 +36,12 @@ public class Bungee extends Plugin implements ViaPlatform {
|
|||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
// Inject
|
||||||
|
Via.getManager().init();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPlatformName() {
|
public String getPlatformName() {
|
||||||
return "BungeeCord";
|
return "BungeeCord";
|
||||||
|
@ -1,18 +1,38 @@
|
|||||||
package us.myles.ViaVersion.bungee;
|
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.api.platform.ViaInjector;
|
||||||
|
import us.myles.ViaVersion.bungee.handlers.ViaVersionInitializer;
|
||||||
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
public class BungeeViaInjector implements ViaInjector {
|
public class BungeeViaInjector implements ViaInjector {
|
||||||
@Override
|
@Override
|
||||||
public void inject() throws Exception {
|
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
|
@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
|
@Override
|
||||||
public int getServerProtocolVersion() throws Exception {
|
public int getServerProtocolVersion() throws Exception {
|
||||||
return 47;
|
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;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
@ -27,6 +27,12 @@ public class ReflectionUtil {
|
|||||||
return (T) field.get(null);
|
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 {
|
public static <T> T getSuper(Object o, String f, Class<T> t) throws NoSuchFieldException, IllegalAccessException {
|
||||||
Field field = o.getClass().getSuperclass().getDeclaredField(f);
|
Field field = o.getClass().getSuperclass().getDeclaredField(f);
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
@ -58,6 +64,7 @@ public class ReflectionUtil {
|
|||||||
field.set(o, value);
|
field.set(o, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static final class ClassReflection {
|
public static final class ClassReflection {
|
||||||
private final Class<?> handle;
|
private final Class<?> handle;
|
||||||
private final Map<String, Field> fields = Maps.newConcurrentMap();
|
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.Via;
|
||||||
import us.myles.ViaVersion.api.platform.ViaInjector;
|
import us.myles.ViaVersion.api.platform.ViaInjector;
|
||||||
import us.myles.ViaVersion.sponge.handlers.ViaVersionInitializer;
|
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 us.myles.ViaVersion.util.ListWrapper;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import com.google.common.collect.Lists;
|
|||||||
import us.myles.ViaVersion.api.Via;
|
import us.myles.ViaVersion.api.Via;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
|
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
|
||||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
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.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
Loading…
Reference in New Issue
Block a user