Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-25 15:50:10 +01:00
Remove NMS, now uses reflection. (whew)
Dieser Commit ist enthalten in:
Ursprung
156f42318c
Commit
3cc6bf4c51
28
pom.xml
28
pom.xml
@ -21,12 +21,28 @@
|
|||||||
</build>
|
</build>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<!-- Sorry about this path >:( I promise to fix it when I stop using NMS :) -->
|
<groupId>org.bukkit</groupId>
|
||||||
<groupId>org.spigot</groupId>
|
<artifactId>bukkit</artifactId>
|
||||||
<artifactId>spigot1.8</artifactId>
|
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||||
<version>1.8</version>
|
<scope>provided</scope>
|
||||||
<scope>system</scope>
|
</dependency>
|
||||||
<systemPath>E:/spigot_server.jar</systemPath>
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<version>4.0.20.Final</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.4</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>18.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -5,15 +5,12 @@ import io.netty.channel.ChannelHandler;
|
|||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import net.minecraft.server.v1_8_R3.*;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
@ -23,10 +20,6 @@ public class Core extends JavaPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
System.out.println("ViaVersion enabled, injecting. (Allows 1.8 to be accessed via 1.9)");
|
System.out.println("ViaVersion enabled, injecting. (Allows 1.8 to be accessed via 1.9)");
|
||||||
/* Obvious message here:
|
|
||||||
If loading this plugin nobody will be on 1.9 cause only 1.8 so we're fine, as for reloading ugh.
|
|
||||||
Clients might crash cause of it being a bum maybe? :P
|
|
||||||
*/
|
|
||||||
try {
|
try {
|
||||||
injectPacketHandler();
|
injectPacketHandler();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -36,39 +29,37 @@ public class Core extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void injectPacketHandler() throws Exception {
|
public void injectPacketHandler() throws Exception {
|
||||||
MinecraftServer server = MinecraftServer.getServer();
|
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
|
||||||
ServerConnection connection = server.getServerConnection();
|
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
||||||
|
Object connection = serverClazz.getDeclaredMethod("getServerConnection").invoke(server);
|
||||||
|
|
||||||
List<ChannelFuture> futures = getPrivateField(connection, "g", List.class);
|
List<ChannelFuture> futures = ReflectionUtil.get(connection, "g", List.class);
|
||||||
if(futures.size() == 0){
|
if (futures.size() == 0) {
|
||||||
throw new Exception("Could not find server to inject (late bind?)");
|
throw new Exception("Could not find server to inject (late bind?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ChannelFuture future : futures) {
|
for (ChannelFuture future : futures) {
|
||||||
ChannelPipeline pipeline = future.channel().pipeline();
|
ChannelPipeline pipeline = future.channel().pipeline();
|
||||||
ChannelHandler bootstrapAcceptor = pipeline.first();
|
ChannelHandler bootstrapAcceptor = pipeline.first();
|
||||||
ChannelInitializer<SocketChannel> oldInit = getPrivateField(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
|
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
|
||||||
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
|
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
|
||||||
setPrivateField(bootstrapAcceptor, "childHandler", newInit);
|
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Entity getEntity(final UUID player, final int id) {
|
public static Entity getEntity(final UUID player, final int id) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return Bukkit.getScheduler().callSyncMethod(getPlugin(Core.class), new Callable<Entity>() {
|
return Bukkit.getScheduler().callSyncMethod(getPlugin(Core.class), new Callable<Entity>() {
|
||||||
@Override
|
@Override
|
||||||
public Entity call() throws Exception {
|
public Entity call() throws Exception {
|
||||||
Player p = Bukkit.getPlayer(player);
|
Player p = Bukkit.getPlayer(player);
|
||||||
if (p == null) return null;
|
if (p == null) return null;
|
||||||
WorldServer ws = ((CraftWorld) p.getWorld()).getHandle();
|
for (Entity e : p.getWorld().getEntities()) {
|
||||||
for (Entity e : ws.entityList) {
|
if (e.getEntityId() == id) {
|
||||||
if (e.getId() == id) {
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("Couldn't find in the world!!");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}).get(10, TimeUnit.SECONDS);
|
}).get(10, TimeUnit.SECONDS);
|
||||||
@ -77,41 +68,5 @@ public class Core extends JavaPlugin {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T getPrivateField(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 void setPrivateField(Object o, String f, Object value) throws NoSuchFieldException, IllegalAccessException {
|
|
||||||
Field field = o.getClass().getDeclaredField(f);
|
|
||||||
field.setAccessible(true);
|
|
||||||
field.set(o, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisable() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ItemStack getHandItem(final ConnectionInfo info) {
|
|
||||||
try {
|
|
||||||
return Bukkit.getScheduler().callSyncMethod(getPlugin(Core.class), new Callable<ItemStack>() {
|
|
||||||
@Override
|
|
||||||
public ItemStack call() throws Exception {
|
|
||||||
if (info.getPlayer() != null) {
|
|
||||||
return info.getPlayer().getItemInHand();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}).get(10, TimeUnit.SECONDS);
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Error fetching hand item ");
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,4 +338,22 @@ public class PacketUtil {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void writeItem(Object value, ByteBuf output) {
|
||||||
|
try {
|
||||||
|
Class<?> serializer = ReflectionUtil.nms("PacketDataSerializer");
|
||||||
|
Object init = serializer.getDeclaredConstructor(ByteBuf.class).newInstance(output);
|
||||||
|
Method toCall = init.getClass().getDeclaredMethod("a", ReflectionUtil.nms("ItemStack"));
|
||||||
|
toCall.invoke(init, value);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
41
src/main/java/us/myles/ViaVersion/ReflectionUtil.java
Normale Datei
41
src/main/java/us/myles/ViaVersion/ReflectionUtil.java
Normale Datei
@ -0,0 +1,41 @@
|
|||||||
|
package us.myles.ViaVersion;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
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 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 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 void set(Object o, String f, Object value) throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
Field field = o.getClass().getDeclaredField(f);
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(o, value);
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,14 @@
|
|||||||
package us.myles.ViaVersion.handlers;
|
package us.myles.ViaVersion.handlers;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
import net.minecraft.server.v1_8_R3.Packet;
|
|
||||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk;
|
|
||||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunkBulk;
|
|
||||||
import net.minecraft.server.v1_8_R3.World;
|
|
||||||
import us.myles.ViaVersion.ConnectionInfo;
|
import us.myles.ViaVersion.ConnectionInfo;
|
||||||
import us.myles.ViaVersion.Core;
|
import us.myles.ViaVersion.ReflectionUtil;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
public class ViaOutboundPacketHandler extends ChannelOutboundHandlerAdapter {
|
public class ViaOutboundPacketHandler extends ChannelOutboundHandlerAdapter {
|
||||||
private final ConnectionInfo info;
|
private final ConnectionInfo info;
|
||||||
@ -17,21 +16,26 @@ public class ViaOutboundPacketHandler extends ChannelOutboundHandlerAdapter {
|
|||||||
public ViaOutboundPacketHandler(Channel c, ConnectionInfo info) {
|
public ViaOutboundPacketHandler(Channel c, ConnectionInfo info) {
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(ChannelHandlerContext channelHandlerContext, Object o, ChannelPromise channelPromise) throws Exception {
|
public void write(ChannelHandlerContext channelHandlerContext, Object o, ChannelPromise channelPromise) throws Exception {
|
||||||
if(o instanceof Packet){
|
if (!(o instanceof ByteBuf)) {
|
||||||
info.setLastPacket(o);
|
info.setLastPacket(o);
|
||||||
/* This transformer is more for fixing issues which we find hard at byte level :) */
|
/* This transformer is more for fixing issues which we find hard at byte level :) */
|
||||||
if(o instanceof PacketPlayOutMapChunkBulk){
|
if (o.getClass().getName().endsWith("PacketPlayOutMapChunkBulk")) {
|
||||||
PacketPlayOutMapChunkBulk bulk = (PacketPlayOutMapChunkBulk) o;
|
int[] locX = ReflectionUtil.get(o, "a", int[].class);
|
||||||
int[] locX = Core.getPrivateField(bulk, "a", int[].class);
|
int[] locZ = ReflectionUtil.get(o, "b", int[].class);
|
||||||
int[] locZ = Core.getPrivateField(bulk, "b", int[].class);
|
|
||||||
|
|
||||||
World world = Core.getPrivateField(bulk, "world", World.class);
|
Object world = ReflectionUtil.get(o, "world", ReflectionUtil.nms("World"));
|
||||||
for(int i = 0;i<locX.length;i++){
|
Class<?> mapChunk = ReflectionUtil.nms("PacketPlayOutMapChunk");
|
||||||
|
Constructor constructor = mapChunk.getDeclaredConstructor(ReflectionUtil.nms("Chunk"), boolean.class, int.class);
|
||||||
|
for (int i = 0; i < locX.length; i++) {
|
||||||
int x = locX[i];
|
int x = locX[i];
|
||||||
int z = locZ[i];
|
int z = locZ[i];
|
||||||
channelHandlerContext.write(new PacketPlayOutMapChunk(world.getChunkAt(x, z), true, 65535)); // magic was 65535
|
// world invoke function
|
||||||
|
Object chunk = ReflectionUtil.nms("World").getDeclaredMethod("getChunkAt", int.class, int.class).invoke(world, x, z);
|
||||||
|
Object packet = constructor.newInstance(chunk, true, 65535);
|
||||||
|
channelHandlerContext.write(packet);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package us.myles.ViaVersion.metadata;
|
package us.myles.ViaVersion.metadata;
|
||||||
|
|
||||||
import net.minecraft.server.v1_8_R3.Entity;
|
|
||||||
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
|
||||||
import net.minecraft.server.v1_8_R3.EntityTypes;
|
|
||||||
import org.bukkit.entity.*;
|
import org.bukkit.entity.*;
|
||||||
|
|
||||||
public enum MetaIndex {
|
public enum MetaIndex {
|
||||||
@ -164,11 +161,10 @@ public enum MetaIndex {
|
|||||||
|
|
||||||
public static MetaIndex getIndex(Entity entity, int index) {
|
public static MetaIndex getIndex(Entity entity, int index) {
|
||||||
EntityType type;
|
EntityType type;
|
||||||
if (entity instanceof EntityPlayer) {
|
if (entity instanceof Player) {
|
||||||
type = EntityType.PLAYER;
|
type = EntityType.PLAYER;
|
||||||
} else {
|
} else {
|
||||||
int entityID = EntityTypes.a(entity);
|
type = entity.getType();
|
||||||
type = EntityType.fromId(entityID);
|
|
||||||
}
|
}
|
||||||
return getIndex(type, index);
|
return getIndex(type, index);
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,15 @@ package us.myles.ViaVersion.transformers;
|
|||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import net.minecraft.server.v1_8_R3.ItemStack;
|
|
||||||
import net.minecraft.server.v1_8_R3.PacketDataSerializer;
|
|
||||||
import net.minecraft.server.v1_8_R3.PacketPlayOutSetSlot;
|
|
||||||
import us.myles.ViaVersion.CancelException;
|
import us.myles.ViaVersion.CancelException;
|
||||||
import us.myles.ViaVersion.ConnectionInfo;
|
import us.myles.ViaVersion.ConnectionInfo;
|
||||||
import us.myles.ViaVersion.PacketUtil;
|
import us.myles.ViaVersion.PacketUtil;
|
||||||
|
import us.myles.ViaVersion.ReflectionUtil;
|
||||||
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
||||||
import us.myles.ViaVersion.packets.PacketType;
|
import us.myles.ViaVersion.packets.PacketType;
|
||||||
import us.myles.ViaVersion.packets.State;
|
import us.myles.ViaVersion.packets.State;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
public class IncomingTransformer {
|
public class IncomingTransformer {
|
||||||
private final Channel channel;
|
private final Channel channel;
|
||||||
@ -97,23 +95,29 @@ public class IncomingTransformer {
|
|||||||
byte button = input.readByte();
|
byte button = input.readByte();
|
||||||
short action = input.readShort();
|
short action = input.readShort();
|
||||||
byte mode = input.readByte();
|
byte mode = input.readByte();
|
||||||
PacketDataSerializer pds = new PacketDataSerializer(input);
|
|
||||||
ItemStack slotItem = null;
|
|
||||||
try {
|
|
||||||
slotItem = pds.i();
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
if (slot == 45 && windowID == 0) {
|
if (slot == 45 && windowID == 0) {
|
||||||
channel.writeAndFlush(new PacketPlayOutSetSlot(windowID, slot, null)); // slot is empty
|
try {
|
||||||
|
Class<?> setSlot = ReflectionUtil.nms("PacketPlayOutSetSlot");
|
||||||
|
Object setSlotPacket = setSlot.getConstructors()[1].newInstance(windowID, slot, null);
|
||||||
|
channel.writeAndFlush(setSlotPacket); // slot is empty
|
||||||
slot = -999; // we're evil, they'll throw item on the ground
|
slot = -999; // we're evil, they'll throw item on the ground
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
output.writeByte(windowID);
|
output.writeByte(windowID);
|
||||||
output.writeShort(slot);
|
output.writeShort(slot);
|
||||||
output.writeByte(button);
|
output.writeByte(button);
|
||||||
output.writeShort(action);
|
output.writeShort(action);
|
||||||
output.writeByte(mode);
|
output.writeByte(mode);
|
||||||
PacketDataSerializer pdss = new PacketDataSerializer(output);
|
output.writeBytes(input);
|
||||||
pdss.a(slotItem);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (packet == PacketType.PLAY_CLIENT_SETTINGS) {
|
if (packet == PacketType.PLAY_CLIENT_SETTINGS) {
|
||||||
|
@ -4,16 +4,11 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import net.minecraft.server.v1_8_R3.*;
|
import org.bukkit.Bukkit;
|
||||||
import net.minecraft.server.v1_8_R3.ItemStack;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
|
|
||||||
import org.bukkit.inventory.*;
|
|
||||||
import org.spacehq.mc.protocol.data.game.chunk.Column;
|
import org.spacehq.mc.protocol.data.game.chunk.Column;
|
||||||
import org.spacehq.mc.protocol.util.NetUtil;
|
import org.spacehq.mc.protocol.util.NetUtil;
|
||||||
import us.myles.ViaVersion.CancelException;
|
import us.myles.ViaVersion.*;
|
||||||
import us.myles.ViaVersion.ConnectionInfo;
|
|
||||||
import us.myles.ViaVersion.Core;
|
|
||||||
import us.myles.ViaVersion.PacketUtil;
|
|
||||||
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
||||||
import us.myles.ViaVersion.metadata.MetaIndex;
|
import us.myles.ViaVersion.metadata.MetaIndex;
|
||||||
import us.myles.ViaVersion.metadata.NewType;
|
import us.myles.ViaVersion.metadata.NewType;
|
||||||
@ -22,6 +17,8 @@ import us.myles.ViaVersion.packets.PacketType;
|
|||||||
import us.myles.ViaVersion.packets.State;
|
import us.myles.ViaVersion.packets.State;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class OutgoingTransformer {
|
public class OutgoingTransformer {
|
||||||
@ -171,7 +168,7 @@ public class OutgoingTransformer {
|
|||||||
PacketUtil.writeVarInt(id, output);
|
PacketUtil.writeVarInt(id, output);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List dw = Core.getPrivateField(info.getLastPacket(), "b", List.class);
|
List dw = ReflectionUtil.get(info.getLastPacket(), "b", List.class);
|
||||||
// get entity via entityID, not preferred but we need it.
|
// get entity via entityID, not preferred but we need it.
|
||||||
Entity entity = Core.getEntity(info.getUUID(), id);
|
Entity entity = Core.getEntity(info.getUUID(), id);
|
||||||
if (entity != null) {
|
if (entity != null) {
|
||||||
@ -262,12 +259,14 @@ public class OutgoingTransformer {
|
|||||||
short vZ = input.readShort();
|
short vZ = input.readShort();
|
||||||
output.writeShort(vZ);
|
output.writeShort(vZ);
|
||||||
try {
|
try {
|
||||||
DataWatcher dw = Core.getPrivateField(info.getLastPacket(), "l", DataWatcher.class);
|
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "l", ReflectionUtil.nms("DataWatcher"));
|
||||||
transformMetadata(dw, output);
|
transformMetadata(dataWatcher, output);
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -290,12 +289,14 @@ public class OutgoingTransformer {
|
|||||||
byte yaw = input.readByte();
|
byte yaw = input.readByte();
|
||||||
output.writeByte(yaw);
|
output.writeByte(yaw);
|
||||||
try {
|
try {
|
||||||
DataWatcher dw = Core.getPrivateField(info.getLastPacket(), "i", DataWatcher.class);
|
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "i", ReflectionUtil.nms("DataWatcher"));
|
||||||
transformMetadata(dw, output);
|
transformMetadata(dataWatcher, output);
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -326,9 +327,9 @@ public class OutgoingTransformer {
|
|||||||
byte[] data = new byte[size];
|
byte[] data = new byte[size];
|
||||||
input.readBytes(data);
|
input.readBytes(data);
|
||||||
boolean sk = false;
|
boolean sk = false;
|
||||||
if (info.getLastPacket() instanceof PacketPlayOutMapChunkBulk) {
|
if (info.getLastPacket().getClass().getName().endsWith("PacketPlayOutMapChunkBulk")) {
|
||||||
try {
|
try {
|
||||||
sk = Core.getPrivateField(info.getLastPacket(), "d", boolean.class);
|
sk = ReflectionUtil.get(info.getLastPacket(), "d", boolean.class);
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
@ -351,45 +352,57 @@ public class OutgoingTransformer {
|
|||||||
output.writeBytes(input);
|
output.writeBytes(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void transformMetadata(DataWatcher dw, ByteBuf output) {
|
private void transformMetadata(Object dw, ByteBuf output) {
|
||||||
// get entity
|
// get entity
|
||||||
try {
|
try {
|
||||||
transformMetadata(Core.getPrivateField(dw, "a", Entity.class), dw.b(), output);
|
Class<?> nmsClass = ReflectionUtil.nms("Entity");
|
||||||
|
Object nmsEntity = ReflectionUtil.get(dw, "a", nmsClass);
|
||||||
|
Class<?> craftClass = ReflectionUtil.obc("entity.CraftEntity");
|
||||||
|
Method bukkitMethod = craftClass.getDeclaredMethod("getEntity", ReflectionUtil.obc("CraftServer"), nmsClass);
|
||||||
|
|
||||||
|
Object entity = bukkitMethod.invoke(null, Bukkit.getServer(), nmsEntity);
|
||||||
|
transformMetadata((Entity) entity, (List) ReflectionUtil.invoke(dw, "b"), output);
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void transformMetadata(Entity entity, List<DataWatcher.WatchableObject> dw, ByteBuf output) {
|
private void transformMetadata(Entity entity, List dw, ByteBuf output) {
|
||||||
PacketDataSerializer packetdataserializer = new PacketDataSerializer(output);
|
try {
|
||||||
|
|
||||||
if (dw != null) {
|
if (dw != null) {
|
||||||
short id = -1;
|
short id = -1;
|
||||||
int data = -1;
|
int data = -1;
|
||||||
|
|
||||||
Iterator<DataWatcher.WatchableObject> iterator = dw.iterator();
|
Iterator iterator = dw.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
DataWatcher.WatchableObject obj = iterator.next();
|
Object watchableObj = iterator.next(); //
|
||||||
MetaIndex metaIndex = MetaIndex.getIndex(entity, obj.a());
|
MetaIndex metaIndex = MetaIndex.getIndex(entity, (int) ReflectionUtil.invoke(watchableObj, "a"));
|
||||||
if (metaIndex.getNewType() != NewType.Discontinued) {
|
if (metaIndex.getNewType() != NewType.Discontinued) {
|
||||||
if (metaIndex.getNewType() != NewType.BlockID || id != -1 && data == -1 || id == -1 && data != -1) { // block ID is only written if we have both parts
|
if (metaIndex.getNewType() != NewType.BlockID || id != -1 && data == -1 || id == -1 && data != -1) { // block ID is only written if we have both parts
|
||||||
output.writeByte(metaIndex.getNewIndex());
|
output.writeByte(metaIndex.getNewIndex());
|
||||||
output.writeByte(metaIndex.getNewType().getTypeID());
|
output.writeByte(metaIndex.getNewType().getTypeID());
|
||||||
}
|
}
|
||||||
|
Object value = ReflectionUtil.invoke(watchableObj, "b");
|
||||||
switch (metaIndex.getNewType()) {
|
switch (metaIndex.getNewType()) {
|
||||||
case Byte:
|
case Byte:
|
||||||
// convert from int, byte
|
// convert from int, byte
|
||||||
if (metaIndex.getOldType() == Type.Byte) {
|
if (metaIndex.getOldType() == Type.Byte) {
|
||||||
packetdataserializer.writeByte(((Byte) obj.b()).byteValue());
|
output.writeByte(((Byte) value).byteValue());
|
||||||
}
|
}
|
||||||
if (metaIndex.getOldType() == Type.Int) {
|
if (metaIndex.getOldType() == Type.Int) {
|
||||||
packetdataserializer.writeByte(((Integer) obj.b()).byteValue());
|
output.writeByte(((Integer) value).byteValue());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OptUUID:
|
case OptUUID:
|
||||||
String owner = (String) obj.b();
|
String owner = (String) value;
|
||||||
UUID toWrite = null;
|
UUID toWrite = null;
|
||||||
if (owner.length() != 0) {
|
if (owner.length() != 0) {
|
||||||
try {
|
try {
|
||||||
@ -397,17 +410,17 @@ public class OutgoingTransformer {
|
|||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
packetdataserializer.writeBoolean(toWrite != null);
|
output.writeBoolean(toWrite != null);
|
||||||
if (toWrite != null)
|
if (toWrite != null)
|
||||||
packetdataserializer.a(toWrite);
|
PacketUtil.writeUUID((UUID) value, output);
|
||||||
break;
|
break;
|
||||||
case BlockID:
|
case BlockID:
|
||||||
// if we have both sources :))
|
// if we have both sources :))
|
||||||
if (metaIndex.getOldType() == Type.Byte) {
|
if (metaIndex.getOldType() == Type.Byte) {
|
||||||
data = ((Byte) obj.b()).byteValue();
|
data = ((Byte) value).byteValue();
|
||||||
}
|
}
|
||||||
if (metaIndex.getOldType() == Type.Short) {
|
if (metaIndex.getOldType() == Type.Short) {
|
||||||
id = ((Short) obj.b()).shortValue();
|
id = ((Short) value).shortValue();
|
||||||
}
|
}
|
||||||
if (id != -1 && data != -1) {
|
if (id != -1 && data != -1) {
|
||||||
int combined = id << 4 | data;
|
int combined = id << 4 | data;
|
||||||
@ -419,45 +432,44 @@ public class OutgoingTransformer {
|
|||||||
case VarInt:
|
case VarInt:
|
||||||
// convert from int, short, byte
|
// convert from int, short, byte
|
||||||
if (metaIndex.getOldType() == Type.Byte) {
|
if (metaIndex.getOldType() == Type.Byte) {
|
||||||
PacketUtil.writeVarInt(((Byte) obj.b()).intValue(), output);
|
PacketUtil.writeVarInt(((Byte) value).intValue(), output);
|
||||||
}
|
}
|
||||||
if (metaIndex.getOldType() == Type.Short) {
|
if (metaIndex.getOldType() == Type.Short) {
|
||||||
PacketUtil.writeVarInt(((Short) obj.b()).intValue(), output);
|
PacketUtil.writeVarInt(((Short) value).intValue(), output);
|
||||||
}
|
}
|
||||||
if (metaIndex.getOldType() == Type.Int) {
|
if (metaIndex.getOldType() == Type.Int) {
|
||||||
PacketUtil.writeVarInt(((Integer) obj.b()).intValue(), output);
|
PacketUtil.writeVarInt(((Integer) value).intValue(), output);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Float:
|
case Float:
|
||||||
packetdataserializer.writeFloat(((Float) obj.b()).floatValue());
|
output.writeFloat(((Float) value).floatValue());
|
||||||
break;
|
break;
|
||||||
case String:
|
case String:
|
||||||
packetdataserializer.a((String) obj.b());
|
PacketUtil.writeString((String) value, output);
|
||||||
break;
|
break;
|
||||||
case Boolean:
|
case Boolean:
|
||||||
packetdataserializer.writeBoolean(((Byte) obj.b()).byteValue() != 0);
|
output.writeBoolean(((Byte) value).byteValue() != 0);
|
||||||
break;
|
break;
|
||||||
case Slot:
|
case Slot:
|
||||||
ItemStack itemstack = (ItemStack) obj.b();
|
PacketUtil.writeItem(value, output);
|
||||||
packetdataserializer.a(itemstack);
|
|
||||||
break;
|
break;
|
||||||
case Position:
|
case Position:
|
||||||
BlockPosition blockposition = (BlockPosition) obj.b();
|
output.writeInt((int) ReflectionUtil.invoke(value, "getX"));
|
||||||
packetdataserializer.writeInt(blockposition.getX());
|
output.writeInt((int) ReflectionUtil.invoke(value, "getY"));
|
||||||
packetdataserializer.writeInt(blockposition.getY());
|
output.writeInt((int) ReflectionUtil.invoke(value, "getZ"));
|
||||||
packetdataserializer.writeInt(blockposition.getZ());
|
|
||||||
break;
|
break;
|
||||||
case Vector3F:
|
case Vector3F:
|
||||||
Vector3f vector3f = (Vector3f) obj.b();
|
output.writeFloat((float) ReflectionUtil.invoke(value, "getX"));
|
||||||
packetdataserializer.writeFloat(vector3f.getX());
|
output.writeFloat((float) ReflectionUtil.invoke(value, "getY"));
|
||||||
packetdataserializer.writeFloat(vector3f.getY());
|
output.writeFloat((float) ReflectionUtil.invoke(value, "getZ"));
|
||||||
packetdataserializer.writeFloat(vector3f.getZ());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output.writeByte(255);
|
output.writeByte(255);
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren