Remove NMS, now uses reflection. (whew)

This commit is contained in:
Myles 2016-02-29 17:35:55 +00:00
parent 156f42318c
commit 3cc6bf4c51
8 changed files with 247 additions and 201 deletions

28
pom.xml
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 {
slot = -999; // we're evil, they'll throw item on the ground 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
} 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) {

View File

@ -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,113 +352,124 @@ 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) {
short id = -1;
int data = -1;
if (dw != null) { Iterator iterator = dw.iterator();
short id = -1; while (iterator.hasNext()) {
int data = -1; Object watchableObj = iterator.next(); //
MetaIndex metaIndex = MetaIndex.getIndex(entity, (int) ReflectionUtil.invoke(watchableObj, "a"));
Iterator<DataWatcher.WatchableObject> iterator = dw.iterator(); if (metaIndex.getNewType() != NewType.Discontinued) {
while (iterator.hasNext()) { if (metaIndex.getNewType() != NewType.BlockID || id != -1 && data == -1 || id == -1 && data != -1) { // block ID is only written if we have both parts
DataWatcher.WatchableObject obj = iterator.next(); output.writeByte(metaIndex.getNewIndex());
MetaIndex metaIndex = MetaIndex.getIndex(entity, obj.a()); output.writeByte(metaIndex.getNewType().getTypeID());
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 Object value = ReflectionUtil.invoke(watchableObj, "b");
output.writeByte(metaIndex.getNewIndex()); switch (metaIndex.getNewType()) {
output.writeByte(metaIndex.getNewType().getTypeID()); case Byte:
} // convert from int, byte
switch (metaIndex.getNewType()) { if (metaIndex.getOldType() == Type.Byte) {
case Byte: output.writeByte(((Byte) value).byteValue());
// convert from int, byte
if (metaIndex.getOldType() == Type.Byte) {
packetdataserializer.writeByte(((Byte) obj.b()).byteValue());
}
if (metaIndex.getOldType() == Type.Int) {
packetdataserializer.writeByte(((Integer) obj.b()).byteValue());
}
break;
case OptUUID:
String owner = (String) obj.b();
UUID toWrite = null;
if (owner.length() != 0) {
try {
toWrite = UUID.fromString(owner);
} catch (Exception ignored) {
} }
} if (metaIndex.getOldType() == Type.Int) {
packetdataserializer.writeBoolean(toWrite != null); output.writeByte(((Integer) value).byteValue());
if (toWrite != null) }
packetdataserializer.a(toWrite); break;
break; case OptUUID:
case BlockID: String owner = (String) value;
// if we have both sources :)) UUID toWrite = null;
if (metaIndex.getOldType() == Type.Byte) { if (owner.length() != 0) {
data = ((Byte) obj.b()).byteValue(); try {
} toWrite = UUID.fromString(owner);
if (metaIndex.getOldType() == Type.Short) { } catch (Exception ignored) {
id = ((Short) obj.b()).shortValue(); }
} }
if (id != -1 && data != -1) { output.writeBoolean(toWrite != null);
int combined = id << 4 | data; if (toWrite != null)
data = -1; PacketUtil.writeUUID((UUID) value, output);
id = -1; break;
PacketUtil.writeVarInt(combined, output); case BlockID:
} // if we have both sources :))
break; if (metaIndex.getOldType() == Type.Byte) {
case VarInt: data = ((Byte) value).byteValue();
// convert from int, short, byte }
if (metaIndex.getOldType() == Type.Byte) { if (metaIndex.getOldType() == Type.Short) {
PacketUtil.writeVarInt(((Byte) obj.b()).intValue(), output); id = ((Short) value).shortValue();
} }
if (metaIndex.getOldType() == Type.Short) { if (id != -1 && data != -1) {
PacketUtil.writeVarInt(((Short) obj.b()).intValue(), output); int combined = id << 4 | data;
} data = -1;
if (metaIndex.getOldType() == Type.Int) { id = -1;
PacketUtil.writeVarInt(((Integer) obj.b()).intValue(), output); PacketUtil.writeVarInt(combined, output);
} }
break; break;
case Float: case VarInt:
packetdataserializer.writeFloat(((Float) obj.b()).floatValue()); // convert from int, short, byte
break; if (metaIndex.getOldType() == Type.Byte) {
case String: PacketUtil.writeVarInt(((Byte) value).intValue(), output);
packetdataserializer.a((String) obj.b()); }
break; if (metaIndex.getOldType() == Type.Short) {
case Boolean: PacketUtil.writeVarInt(((Short) value).intValue(), output);
packetdataserializer.writeBoolean(((Byte) obj.b()).byteValue() != 0); }
break; if (metaIndex.getOldType() == Type.Int) {
case Slot: PacketUtil.writeVarInt(((Integer) value).intValue(), output);
ItemStack itemstack = (ItemStack) obj.b(); }
packetdataserializer.a(itemstack); break;
break; case Float:
case Position: output.writeFloat(((Float) value).floatValue());
BlockPosition blockposition = (BlockPosition) obj.b(); break;
packetdataserializer.writeInt(blockposition.getX()); case String:
packetdataserializer.writeInt(blockposition.getY()); PacketUtil.writeString((String) value, output);
packetdataserializer.writeInt(blockposition.getZ()); break;
break; case Boolean:
case Vector3F: output.writeBoolean(((Byte) value).byteValue() != 0);
Vector3f vector3f = (Vector3f) obj.b(); break;
packetdataserializer.writeFloat(vector3f.getX()); case Slot:
packetdataserializer.writeFloat(vector3f.getY()); PacketUtil.writeItem(value, output);
packetdataserializer.writeFloat(vector3f.getZ()); break;
case Position:
output.writeInt((int) ReflectionUtil.invoke(value, "getX"));
output.writeInt((int) ReflectionUtil.invoke(value, "getY"));
output.writeInt((int) ReflectionUtil.invoke(value, "getZ"));
break;
case Vector3F:
output.writeFloat((float) ReflectionUtil.invoke(value, "getX"));
output.writeFloat((float) ReflectionUtil.invoke(value, "getY"));
output.writeFloat((float) ReflectionUtil.invoke(value, "getZ"));
}
} }
} }
} }
output.writeByte(255);
}catch(Exception e){
e.printStackTrace();
} }
output.writeByte(255);
} }