Ensure StreamSerializer functions correctly in 1.7.2
Dieser Commit ist enthalten in:
Ursprung
7055cadaef
Commit
f94b060591
@ -0,0 +1,85 @@
|
|||||||
|
package com.comphenix.protocol.reflect;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.reflect.compiler.EmptyClassVisitor;
|
||||||
|
import com.comphenix.protocol.reflect.compiler.EmptyMethodVisitor;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import net.sf.cglib.asm.ClassReader;
|
||||||
|
import net.sf.cglib.asm.MethodVisitor;
|
||||||
|
import net.sf.cglib.asm.Type;
|
||||||
|
|
||||||
|
public class ClassAnalyser {
|
||||||
|
/**
|
||||||
|
* Represents a method in ASM.
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
public static class AsmMethod {
|
||||||
|
private final String ownerClass;
|
||||||
|
private final String methodName;
|
||||||
|
private final String signature;
|
||||||
|
|
||||||
|
public AsmMethod(String ownerClass, String methodName, String signature) {
|
||||||
|
this.ownerClass = ownerClass;
|
||||||
|
this.methodName = methodName;
|
||||||
|
this.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOwnerClass() {
|
||||||
|
return ownerClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMethodName() {
|
||||||
|
return methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignature() {
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static final ClassAnalyser DEFAULT = new ClassAnalyser();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the default instance.
|
||||||
|
* @return The default.
|
||||||
|
*/
|
||||||
|
public static ClassAnalyser getDefault() {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve every method calls in the given method.
|
||||||
|
* @param method - the method to analyse.
|
||||||
|
* @return The method calls.
|
||||||
|
* @throws IOException Cannot access the parent class.
|
||||||
|
*/
|
||||||
|
public List<AsmMethod> getMethodCalls(Method method) throws IOException {
|
||||||
|
final ClassReader reader = new ClassReader(method.getDeclaringClass().getCanonicalName());
|
||||||
|
final List<AsmMethod> output = Lists.newArrayList();
|
||||||
|
|
||||||
|
// The method we are looking for
|
||||||
|
final String methodName = method.getName();
|
||||||
|
final String methodDescription = Type.getMethodDescriptor(method);
|
||||||
|
|
||||||
|
reader.accept(new EmptyClassVisitor() {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||||
|
// Check method
|
||||||
|
if (methodName.equals(name) && methodDescription.equals(desc)) {
|
||||||
|
return new EmptyMethodVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
|
||||||
|
output.add(new AsmMethod(owner, name, desc));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}, ClassReader.EXPAND_FRAMES);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
@ -53,6 +53,13 @@ public class FuzzyReflection {
|
|||||||
* @throws IllegalStateException If the current security context prohibits reflection.
|
* @throws IllegalStateException If the current security context prohibits reflection.
|
||||||
*/
|
*/
|
||||||
public Object get(Object instance);
|
public Object get(Object instance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of a field for a particular instance.
|
||||||
|
* @param instance - the instance, or NULL for a static field.
|
||||||
|
* @param value - the new value of the field.
|
||||||
|
*/
|
||||||
|
public void set(Object instance, Object value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,7 +136,6 @@ public class FuzzyReflection {
|
|||||||
public static FieldAccessor getFieldAccessor(Class<?> instanceClass, Class<?> fieldClass, boolean forceAccess) {
|
public static FieldAccessor getFieldAccessor(Class<?> instanceClass, Class<?> fieldClass, boolean forceAccess) {
|
||||||
// Get a field accessor
|
// Get a field accessor
|
||||||
Field field = FuzzyReflection.fromObject(instanceClass, forceAccess).getFieldByType(null, fieldClass);
|
Field field = FuzzyReflection.fromObject(instanceClass, forceAccess).getFieldByType(null, fieldClass);
|
||||||
field.setAccessible(true);
|
|
||||||
return getFieldAccessor(field);
|
return getFieldAccessor(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +145,18 @@ public class FuzzyReflection {
|
|||||||
* @return The field accessor.
|
* @return The field accessor.
|
||||||
*/
|
*/
|
||||||
public static FieldAccessor getFieldAccessor(final Field field) {
|
public static FieldAccessor getFieldAccessor(final Field field) {
|
||||||
|
return getFieldAccessor(field, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a field accessor from a given field that uses unchecked exceptions.
|
||||||
|
* @param field - the field.
|
||||||
|
* @param forceAccess - whether or not to skip Java access checking.
|
||||||
|
* @return The field accessor.
|
||||||
|
*/
|
||||||
|
public static FieldAccessor getFieldAccessor(final Field field, boolean forceAccess) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
|
||||||
return new FieldAccessor() {
|
return new FieldAccessor() {
|
||||||
@Override
|
@Override
|
||||||
public Object get(Object instance) {
|
public Object get(Object instance) {
|
||||||
@ -148,6 +166,15 @@ public class FuzzyReflection {
|
|||||||
throw new IllegalStateException("Cannot use reflection.", e);
|
throw new IllegalStateException("Cannot use reflection.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Object instance, Object value) {
|
||||||
|
try {
|
||||||
|
field.set(instance, value);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalStateException("Cannot use reflection.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,376 @@
|
|||||||
|
package com.comphenix.protocol.utility;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.GatheringByteChannel;
|
||||||
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
|
import java.nio.channels.WritableByteChannel;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyReflection.FieldAccessor;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.google.common.io.LimitInputStream;
|
||||||
|
|
||||||
|
import net.minecraft.util.io.netty.buffer.AbstractByteBuf;
|
||||||
|
import net.minecraft.util.io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraft.util.io.netty.buffer.ByteBufAllocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a ByteBuf around an input stream and an output stream.
|
||||||
|
* <p>
|
||||||
|
* Note that as streams usually don't support seeking, this implementation will ignore
|
||||||
|
* all indexing in the byte buffer.
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
class ByteBufAdapter extends AbstractByteBuf {
|
||||||
|
private DataInputStream input;
|
||||||
|
private DataOutputStream output;
|
||||||
|
|
||||||
|
// For modifying the reader or writer index
|
||||||
|
private static FieldAccessor READER_INDEX;
|
||||||
|
private static FieldAccessor WRITER_INDEX;
|
||||||
|
|
||||||
|
private static final int CAPACITY = Short.MAX_VALUE;
|
||||||
|
|
||||||
|
private ByteBufAdapter(DataInputStream input, DataOutputStream output) {
|
||||||
|
// Just pick a figure
|
||||||
|
super(CAPACITY);
|
||||||
|
this.input = input;
|
||||||
|
this.output = output;
|
||||||
|
|
||||||
|
// Prepare accessors
|
||||||
|
try {
|
||||||
|
if (READER_INDEX == null) {
|
||||||
|
READER_INDEX = FuzzyReflection.getFieldAccessor(AbstractByteBuf.class.getDeclaredField("readerIndex"));
|
||||||
|
}
|
||||||
|
if (WRITER_INDEX == null) {
|
||||||
|
WRITER_INDEX = FuzzyReflection.getFieldAccessor(AbstractByteBuf.class.getDeclaredField("writerIndex"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Cannot initialize ByteBufAdapter.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Infinite" reading/writing
|
||||||
|
if (input == null)
|
||||||
|
READER_INDEX.set(this, Integer.MAX_VALUE);
|
||||||
|
if (output == null)
|
||||||
|
WRITER_INDEX.set(this, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new Minecraft packet serializer using the current byte buf adapter.
|
||||||
|
* @param input - the input stream.
|
||||||
|
* @return A packet serializer with a wrapped byte buf adapter.
|
||||||
|
*/
|
||||||
|
public static ByteBuf packetReader(DataInputStream input) {
|
||||||
|
return MinecraftReflection.getPacketDataSerializer(new ByteBufAdapter(input, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new Minecraft packet deserializer using the current byte buf adapter.
|
||||||
|
* @param output - the output stream.
|
||||||
|
* @return A packet serializer with a wrapped byte buf adapter.
|
||||||
|
*/
|
||||||
|
public static ByteBuf packetWriter(DataOutputStream output) {
|
||||||
|
return MinecraftReflection.getPacketDataSerializer(new ByteBufAdapter(null, output));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int refCnt() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean release() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean release(int paramInt) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected byte _getByte(int paramInt) {
|
||||||
|
try {
|
||||||
|
return input.readByte();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot read input.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected short _getShort(int paramInt) {
|
||||||
|
try {
|
||||||
|
return input.readShort();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot read input.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int _getUnsignedMedium(int paramInt) {
|
||||||
|
try {
|
||||||
|
return input.readUnsignedShort();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot read input.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int _getInt(int paramInt) {
|
||||||
|
try {
|
||||||
|
return input.readInt();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot read input.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected long _getLong(int paramInt) {
|
||||||
|
try {
|
||||||
|
return input.readLong();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot read input.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setByte(int index, int value) {
|
||||||
|
try {
|
||||||
|
output.writeByte(value);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot write output.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setShort(int index, int value) {
|
||||||
|
try {
|
||||||
|
output.writeShort(value);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot write output.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setMedium(int index, int value) {
|
||||||
|
try {
|
||||||
|
output.writeShort(value);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot write output.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setInt(int index, int value) {
|
||||||
|
try {
|
||||||
|
output.writeInt(value);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot write output.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void _setLong(int index, long value) {
|
||||||
|
try {
|
||||||
|
output.writeLong(value);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot write output.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int capacity() {
|
||||||
|
return CAPACITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf capacity(int paramInt) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteOrder order() {
|
||||||
|
return ByteOrder.LITTLE_ENDIAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf unwrap() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDirect() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
dst.setByte(dstIndex + i, input.read());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot read input.", e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
|
||||||
|
try {
|
||||||
|
input.read(dst, dstIndex, length);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot read input.", e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf getBytes(int index, ByteBuffer dst) {
|
||||||
|
try {
|
||||||
|
dst.put(ByteStreams.toByteArray(input));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot read input.", e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf getBytes(int index, OutputStream dst, int length) throws IOException {
|
||||||
|
ByteStreams.copy(new LimitInputStream(input, length), dst);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
|
||||||
|
byte[] data = ByteStreams.toByteArray(new LimitInputStream(input, length));
|
||||||
|
|
||||||
|
out.write(ByteBuffer.wrap(data));
|
||||||
|
return data.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
|
||||||
|
byte[] buffer = new byte[length];
|
||||||
|
src.getBytes(srcIndex, buffer);
|
||||||
|
|
||||||
|
try {
|
||||||
|
output.write(buffer);
|
||||||
|
return this;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot write output.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
|
||||||
|
try {
|
||||||
|
output.write(src, srcIndex, length);
|
||||||
|
return this;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot write output.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf setBytes(int index, ByteBuffer src) {
|
||||||
|
try {
|
||||||
|
WritableByteChannel channel = Channels.newChannel(output);
|
||||||
|
|
||||||
|
channel.write(src);
|
||||||
|
return this;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Cannot write output.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int setBytes(int index, InputStream in, int length) throws IOException {
|
||||||
|
LimitInputStream limit = new LimitInputStream(in, length);
|
||||||
|
ByteStreams.copy(limit, output);
|
||||||
|
return length - limit.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(length);
|
||||||
|
WritableByteChannel channel = Channels.newChannel(output);
|
||||||
|
|
||||||
|
int count = in.read(buffer);
|
||||||
|
channel.write(buffer);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf copy(int index, int length) {
|
||||||
|
throw new UnsupportedOperationException("Cannot seek in input stream.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nioBufferCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer nioBuffer(int paramInt1, int paramInt2) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer internalNioBuffer(int paramInt1, int paramInt2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer[] nioBuffers(int paramInt1, int paramInt2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasArray() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] array() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int arrayOffset() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasMemoryAddress() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long memoryAddress() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf retain(int paramInt) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuf retain() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
|
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
|
||||||
|
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyReflection.MethodAccessor;
|
||||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
||||||
@ -25,14 +26,14 @@ import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
|||||||
*/
|
*/
|
||||||
public class StreamSerializer {
|
public class StreamSerializer {
|
||||||
// Cached methods
|
// Cached methods
|
||||||
private static Method READ_ITEM_METHOD;
|
private static MethodAccessor READ_ITEM_METHOD;
|
||||||
private static Method WRITE_ITEM_METHOD;
|
private static MethodAccessor WRITE_ITEM_METHOD;
|
||||||
|
|
||||||
private static Method READ_NBT_METHOD;
|
private static MethodAccessor READ_NBT_METHOD;
|
||||||
private static Method WRITE_NBT_METHOD;
|
private static MethodAccessor WRITE_NBT_METHOD;
|
||||||
|
|
||||||
private static Method READ_STRING_METHOD;
|
private static MethodAccessor READ_STRING_METHOD;
|
||||||
private static Method WRITE_STRING_METHOD;
|
private static MethodAccessor WRITE_STRING_METHOD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read or deserialize an item stack from an underlying input stream.
|
* Read or deserialize an item stack from an underlying input stream.
|
||||||
@ -47,26 +48,37 @@ public class StreamSerializer {
|
|||||||
public ItemStack deserializeItemStack(@Nonnull DataInputStream input) throws IOException {
|
public ItemStack deserializeItemStack(@Nonnull DataInputStream input) throws IOException {
|
||||||
if (input == null)
|
if (input == null)
|
||||||
throw new IllegalArgumentException("Input stream cannot be NULL.");
|
throw new IllegalArgumentException("Input stream cannot be NULL.");
|
||||||
if (READ_ITEM_METHOD == null) {
|
Object nmsItem = null;
|
||||||
READ_ITEM_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
|
||||||
FuzzyMethodContract.newBuilder().
|
|
||||||
parameterCount(1).
|
|
||||||
parameterDerivedOf(DataInput.class).
|
|
||||||
returnDerivedOf(MinecraftReflection.getItemStackClass()).
|
|
||||||
build());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Object nmsItem = READ_ITEM_METHOD.invoke(null, input);
|
|
||||||
|
|
||||||
// Convert back to a Bukkit item stack
|
if (MinecraftReflection.isUsingNetty()) {
|
||||||
if (nmsItem != null)
|
if (READ_ITEM_METHOD == null) {
|
||||||
return MinecraftReflection.getBukkitItemStack(nmsItem);
|
READ_ITEM_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
else
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
|
||||||
return null;
|
getMethodByParameters("readItemStack",
|
||||||
|
MinecraftReflection.getItemStackClass(), new Class<?>[0])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
nmsItem = READ_ITEM_METHOD.invoke(ByteBufAdapter.packetReader(input));
|
||||||
|
|
||||||
} catch (Exception e) {
|
} else {
|
||||||
throw new IOException("Cannot read item stack.", e);
|
if (READ_ITEM_METHOD == null) {
|
||||||
|
READ_ITEM_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||||
|
FuzzyMethodContract.newBuilder().
|
||||||
|
parameterCount(1).
|
||||||
|
parameterDerivedOf(DataInput.class).
|
||||||
|
returnDerivedOf(MinecraftReflection.getItemStackClass()).
|
||||||
|
build())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
nmsItem = READ_ITEM_METHOD.invoke(null, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert back to a Bukkit item stack
|
||||||
|
if (nmsItem != null)
|
||||||
|
return MinecraftReflection.getBukkitItemStack(nmsItem);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,26 +90,43 @@ public class StreamSerializer {
|
|||||||
public NbtCompound deserializeCompound(@Nonnull DataInputStream input) throws IOException {
|
public NbtCompound deserializeCompound(@Nonnull DataInputStream input) throws IOException {
|
||||||
if (input == null)
|
if (input == null)
|
||||||
throw new IllegalArgumentException("Input stream cannot be NULL.");
|
throw new IllegalArgumentException("Input stream cannot be NULL.");
|
||||||
if (READ_NBT_METHOD == null) {
|
Object nmsCompound = null;
|
||||||
READ_NBT_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
|
||||||
|
// Invoke the correct method
|
||||||
|
if (MinecraftReflection.isUsingNetty()) {
|
||||||
|
if (READ_NBT_METHOD == null) {
|
||||||
|
READ_NBT_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
|
||||||
|
getMethodByParameters("readNbtCompound",
|
||||||
|
MinecraftReflection.getNBTCompoundClass(), new Class<?>[0])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
nmsCompound = READ_NBT_METHOD.invoke(ByteBufAdapter.packetReader(input));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (READ_NBT_METHOD == null) {
|
||||||
|
READ_NBT_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||||
FuzzyMethodContract.newBuilder().
|
FuzzyMethodContract.newBuilder().
|
||||||
parameterCount(1).
|
parameterCount(1).
|
||||||
parameterDerivedOf(DataInput.class).
|
parameterDerivedOf(DataInput.class).
|
||||||
returnDerivedOf(MinecraftReflection.getNBTBaseClass()).
|
returnDerivedOf(MinecraftReflection.getNBTBaseClass()).
|
||||||
build());
|
build())
|
||||||
}
|
);
|
||||||
try {
|
}
|
||||||
Object nmsCompound = READ_NBT_METHOD.invoke(null, input);
|
|
||||||
|
|
||||||
// Convert back to an NBT Compound
|
try {
|
||||||
if (nmsCompound != null)
|
nmsCompound = READ_NBT_METHOD.invoke(null, input);
|
||||||
return NbtFactory.fromNMSCompound(nmsCompound);
|
} catch (Exception e) {
|
||||||
else
|
throw new IOException("Cannot read item stack.", e);
|
||||||
return null;
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IOException("Cannot read item stack.", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert back to an NBT Compound
|
||||||
|
if (nmsCompound != null)
|
||||||
|
return NbtFactory.fromNMSCompound(nmsCompound);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,21 +146,28 @@ public class StreamSerializer {
|
|||||||
if (maximumLength < 0)
|
if (maximumLength < 0)
|
||||||
throw new IllegalArgumentException("Maximum lenght cannot be negative.");
|
throw new IllegalArgumentException("Maximum lenght cannot be negative.");
|
||||||
|
|
||||||
if (READ_STRING_METHOD == null) {
|
if (MinecraftReflection.isUsingNetty()) {
|
||||||
READ_STRING_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
if (READ_STRING_METHOD == null) {
|
||||||
FuzzyMethodContract.newBuilder().
|
READ_STRING_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
parameterCount(2).
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
|
||||||
parameterDerivedOf(DataInput.class, 0).
|
getMethodByParameters("readString", String.class, new Class<?>[] { int.class })
|
||||||
parameterExactType(int.class, 1).
|
);
|
||||||
returnTypeExact(String.class).
|
}
|
||||||
build());
|
return (String) READ_STRING_METHOD.invoke(ByteBufAdapter.packetReader(input), maximumLength);
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
} else {
|
||||||
// Convert back to a Bukkit item stack
|
if (READ_STRING_METHOD == null) {
|
||||||
|
READ_STRING_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||||
|
FuzzyMethodContract.newBuilder().
|
||||||
|
parameterCount(2).
|
||||||
|
parameterDerivedOf(DataInput.class, 0).
|
||||||
|
parameterExactType(int.class, 1).
|
||||||
|
returnTypeExact(String.class).
|
||||||
|
build())
|
||||||
|
);
|
||||||
|
}
|
||||||
return (String) READ_STRING_METHOD.invoke(null, input, maximumLength);
|
return (String) READ_STRING_METHOD.invoke(null, input, maximumLength);
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IOException("Cannot read Minecraft string.", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,17 +204,26 @@ public class StreamSerializer {
|
|||||||
// Get the NMS version of the ItemStack
|
// Get the NMS version of the ItemStack
|
||||||
Object nmsItem = MinecraftReflection.getMinecraftItemStack(stack);
|
Object nmsItem = MinecraftReflection.getMinecraftItemStack(stack);
|
||||||
|
|
||||||
if (WRITE_ITEM_METHOD == null)
|
if (MinecraftReflection.isUsingNetty()) {
|
||||||
WRITE_ITEM_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
if (WRITE_ITEM_METHOD == null) {
|
||||||
FuzzyMethodContract.newBuilder().
|
WRITE_ITEM_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
parameterCount(2).
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
|
||||||
parameterDerivedOf(MinecraftReflection.getItemStackClass(), 0).
|
getMethodByParameters("writeStack", MinecraftReflection.getItemStackClass())
|
||||||
parameterDerivedOf(DataOutput.class, 1).
|
);
|
||||||
build());
|
}
|
||||||
try {
|
WRITE_ITEM_METHOD.invoke(ByteBufAdapter.packetWriter(output), nmsItem);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (WRITE_ITEM_METHOD == null)
|
||||||
|
WRITE_ITEM_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||||
|
FuzzyMethodContract.newBuilder().
|
||||||
|
parameterCount(2).
|
||||||
|
parameterDerivedOf(MinecraftReflection.getItemStackClass(), 0).
|
||||||
|
parameterDerivedOf(DataOutput.class, 1).
|
||||||
|
build())
|
||||||
|
);
|
||||||
WRITE_ITEM_METHOD.invoke(null, nmsItem, output);
|
WRITE_ITEM_METHOD.invoke(null, nmsItem, output);
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IOException("Cannot write item stack " + stack, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,21 +243,28 @@ public class StreamSerializer {
|
|||||||
// Get the NMS version of the compound
|
// Get the NMS version of the compound
|
||||||
Object handle = compound != null ? NbtFactory.fromBase(compound).getHandle() : null;
|
Object handle = compound != null ? NbtFactory.fromBase(compound).getHandle() : null;
|
||||||
|
|
||||||
if (WRITE_NBT_METHOD == null) {
|
if (MinecraftReflection.isUsingNetty()) {
|
||||||
WRITE_NBT_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass(), true).getMethod(
|
if (WRITE_NBT_METHOD == null) {
|
||||||
FuzzyMethodContract.newBuilder().
|
WRITE_NBT_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
parameterCount(2).
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
|
||||||
parameterDerivedOf(MinecraftReflection.getNBTBaseClass(), 0).
|
getMethodByParameters("writeNbtCompound", MinecraftReflection.getNBTCompoundClass())
|
||||||
parameterDerivedOf(DataOutput.class, 1).
|
);
|
||||||
returnTypeVoid().
|
}
|
||||||
build());
|
WRITE_NBT_METHOD.invoke(ByteBufAdapter.packetWriter(output), handle);
|
||||||
WRITE_NBT_METHOD.setAccessible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
} else {
|
||||||
|
if (WRITE_NBT_METHOD == null) {
|
||||||
|
WRITE_NBT_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass(), true).getMethod(
|
||||||
|
FuzzyMethodContract.newBuilder().
|
||||||
|
parameterCount(2).
|
||||||
|
parameterDerivedOf(MinecraftReflection.getNBTBaseClass(), 0).
|
||||||
|
parameterDerivedOf(DataOutput.class, 1).
|
||||||
|
returnTypeVoid().
|
||||||
|
build())
|
||||||
|
);
|
||||||
|
}
|
||||||
WRITE_NBT_METHOD.invoke(null, handle, output);
|
WRITE_NBT_METHOD.invoke(null, handle, output);
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IOException("Cannot write compound " + compound, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,21 +282,28 @@ public class StreamSerializer {
|
|||||||
if (text == null)
|
if (text == null)
|
||||||
throw new IllegalArgumentException("text cannot be NULL.");
|
throw new IllegalArgumentException("text cannot be NULL.");
|
||||||
|
|
||||||
if (WRITE_STRING_METHOD == null) {
|
if (MinecraftReflection.isUsingNetty()) {
|
||||||
WRITE_STRING_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
if (WRITE_STRING_METHOD == null) {
|
||||||
FuzzyMethodContract.newBuilder().
|
WRITE_STRING_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
parameterCount(2).
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketDataSerializerClass(), true).
|
||||||
parameterExactType(String.class, 0).
|
getMethodByParameters("writeString", String.class)
|
||||||
parameterDerivedOf(DataOutput.class, 1).
|
);
|
||||||
returnTypeVoid().
|
}
|
||||||
build());
|
WRITE_STRING_METHOD.invoke(ByteBufAdapter.packetWriter(output), text);
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
} else {
|
||||||
// Convert back to a Bukkit item stack
|
if (WRITE_STRING_METHOD == null) {
|
||||||
|
WRITE_STRING_METHOD = FuzzyReflection.getMethodAccessor(
|
||||||
|
FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||||
|
FuzzyMethodContract.newBuilder().
|
||||||
|
parameterCount(2).
|
||||||
|
parameterExactType(String.class, 0).
|
||||||
|
parameterDerivedOf(DataOutput.class, 1).
|
||||||
|
returnTypeVoid().
|
||||||
|
build())
|
||||||
|
);
|
||||||
|
}
|
||||||
WRITE_STRING_METHOD.invoke(null, text, output);
|
WRITE_STRING_METHOD.invoke(null, text, output);
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IOException("Cannot read Minecraft string.", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren