mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2025-01-13 11:41:48 +01:00
Ensure that we don't cache wrong methods in the serialization.
This commit is contained in:
parent
86d3461700
commit
ede60970b9
@ -4,7 +4,7 @@
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<name>ProtocolLib</name>
|
||||
<version>1.7.1</version>
|
||||
<version>1.7.2-SNAPSHOT</version>
|
||||
<description>Provides read/write access to the Minecraft protocol.</description>
|
||||
<url>http://dev.bukkit.org/server-mods/protocollib/</url>
|
||||
<developers>
|
||||
|
@ -29,6 +29,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
@ -43,6 +44,7 @@ import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||
import com.comphenix.protocol.wrappers.ChunkPosition;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import net.minecraft.server.Packet;
|
||||
|
||||
@ -63,11 +65,11 @@ public class PacketContainer implements Serializable {
|
||||
|
||||
// Current structure modifier
|
||||
protected transient StructureModifier<Object> structureModifier;
|
||||
|
||||
|
||||
// Support for serialization
|
||||
private static Method writeMethod;
|
||||
private static Method readMethod;
|
||||
|
||||
private static ConcurrentMap<Class<?>, Method> writeMethods = Maps.newConcurrentMap();
|
||||
private static ConcurrentMap<Class<?>, Method> readMethods = Maps.newConcurrentMap();
|
||||
|
||||
/**
|
||||
* Creates a packet container for a new packet.
|
||||
* @param id - ID of the packet to create.
|
||||
@ -100,6 +102,12 @@ public class PacketContainer implements Serializable {
|
||||
this.structureModifier = structure;
|
||||
}
|
||||
|
||||
/**
|
||||
* For serialization.
|
||||
*/
|
||||
protected PacketContainer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the underlying Minecraft packet.
|
||||
* @return Underlying Minecraft packet.
|
||||
@ -399,14 +407,12 @@ public class PacketContainer implements Serializable {
|
||||
|
||||
// We'll take care of NULL packets as well
|
||||
output.writeBoolean(handle != null);
|
||||
|
||||
// Retrieve the write method by reflection
|
||||
if (writeMethod == null)
|
||||
writeMethod = FuzzyReflection.fromObject(handle).getMethodByParameters("write", DataOutputStream.class);
|
||||
|
||||
|
||||
try {
|
||||
// Call the write-method
|
||||
writeMethod.invoke(handle, new DataOutputStream(output));
|
||||
getMethodLazily(writeMethods, handle.getClass(), "write", DataOutputStream.class).
|
||||
invoke(handle, new DataOutputStream(output));
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IOException("Minecraft packet doesn't support DataOutputStream", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
@ -429,13 +435,11 @@ public class PacketContainer implements Serializable {
|
||||
// Create a default instance of the packet
|
||||
handle = StructureCache.newPacket(id);
|
||||
|
||||
// Retrieve the read method by reflection
|
||||
if (readMethod == null)
|
||||
readMethod = FuzzyReflection.fromObject(handle).getMethodByParameters("read", DataInputStream.class);
|
||||
|
||||
// Call the read method
|
||||
try {
|
||||
readMethod.invoke(handle, new DataInputStream(input));
|
||||
getMethodLazily(readMethods, handle.getClass(), "read", DataInputStream.class).
|
||||
invoke(handle, new DataInputStream(input));
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IOException("Minecraft packet doesn't support DataInputStream", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
@ -448,4 +452,30 @@ public class PacketContainer implements Serializable {
|
||||
structureModifier = structureModifier.withTarget(handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the cached method concurrently.
|
||||
* @param lookup - a lazy lookup cache.
|
||||
* @param handleClass - class type of the current packet.
|
||||
* @param methodName - name of method to retrieve.
|
||||
* @param parameterClass - the one parameter type in the method.
|
||||
* @return Reflected method.
|
||||
*/
|
||||
private Method getMethodLazily(ConcurrentMap<Class<?>, Method> lookup,
|
||||
Class<?> handleClass, String methodName, Class<?> parameterClass) {
|
||||
Method method = lookup.get(handleClass);
|
||||
|
||||
// Atomic operation
|
||||
if (method == null) {
|
||||
Method initialized = FuzzyReflection.fromClass(handleClass).getMethodByParameters(methodName, parameterClass);
|
||||
method = lookup.putIfAbsent(handleClass, initialized);
|
||||
|
||||
// Use our version if we succeeded
|
||||
if (method == null) {
|
||||
method = initialized;
|
||||
}
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import com.comphenix.protocol.injector.player.NetworkFieldInjector.FakePacket;
|
||||
|
||||
import net.minecraft.server.Packet;
|
||||
import net.sf.cglib.proxy.Enhancer;
|
||||
import net.sf.cglib.proxy.Factory;
|
||||
import net.sf.cglib.proxy.MethodInterceptor;
|
||||
import net.sf.cglib.proxy.MethodProxy;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user