Prevent method #3 from creating uneeded proxy objects.
This would happen if the NetServerHandler is already a proxy, and the injection method is unable to create an instance of the proxy type. It's best to fail instead of polluting (due to constructors with side-effects) Minecraft with failed proxy objects.
Dieser Commit ist enthalten in:
Ursprung
f0651f7170
Commit
eb12808483
@ -19,10 +19,8 @@ import com.comphenix.protocol.events.PacketListener;
|
|||||||
import com.comphenix.protocol.reflect.FieldUtils;
|
import com.comphenix.protocol.reflect.FieldUtils;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.ObjectCloner;
|
import com.comphenix.protocol.reflect.ObjectCloner;
|
||||||
import com.comphenix.protocol.reflect.instances.CollectionGenerator;
|
|
||||||
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
import com.comphenix.protocol.reflect.instances.DefaultInstances;
|
||||||
import com.comphenix.protocol.reflect.instances.ExistingGenerator;
|
import com.comphenix.protocol.reflect.instances.ExistingGenerator;
|
||||||
import com.comphenix.protocol.reflect.instances.PrimitiveGenerator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a player hook into the NetServerHandler class.
|
* Represents a player hook into the NetServerHandler class.
|
||||||
@ -87,7 +85,7 @@ public class NetworkServerInjector extends PlayerInjector {
|
|||||||
Callback sendPacketCallback = new MethodInterceptor() {
|
Callback sendPacketCallback = new MethodInterceptor() {
|
||||||
@Override
|
@Override
|
||||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
|
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
|
||||||
|
|
||||||
Packet packet = (Packet) args[0];
|
Packet packet = (Packet) args[0];
|
||||||
|
|
||||||
if (packet != null) {
|
if (packet != null) {
|
||||||
@ -121,10 +119,10 @@ public class NetworkServerInjector extends PlayerInjector {
|
|||||||
|
|
||||||
// Use the existing field values when we create our copy
|
// Use the existing field values when we create our copy
|
||||||
DefaultInstances serverInstances = DefaultInstances.fromArray(
|
DefaultInstances serverInstances = DefaultInstances.fromArray(
|
||||||
ExistingGenerator.fromObjectFields(serverHandler),
|
ExistingGenerator.fromObjectFields(serverHandler));
|
||||||
PrimitiveGenerator.INSTANCE,
|
serverInstances.setNonNull(true);
|
||||||
CollectionGenerator.INSTANCE);
|
serverInstances.setMaximumRecursion(1);
|
||||||
|
|
||||||
Object proxyObject = serverInstances.forEnhancer(ex).getDefault(serverClass);
|
Object proxyObject = serverInstances.forEnhancer(ex).getDefault(serverClass);
|
||||||
|
|
||||||
// Inject it now
|
// Inject it now
|
||||||
@ -144,23 +142,23 @@ public class NetworkServerInjector extends PlayerInjector {
|
|||||||
if (serverHandlerRef != null && serverHandlerRef.isCurrentSet()) {
|
if (serverHandlerRef != null && serverHandlerRef.isCurrentSet()) {
|
||||||
ObjectCloner.copyTo(serverHandlerRef.getValue(), serverHandlerRef.getOldValue(), serverHandler.getClass());
|
ObjectCloner.copyTo(serverHandlerRef.getValue(), serverHandlerRef.getOldValue(), serverHandler.getClass());
|
||||||
serverHandlerRef.revertValue();
|
serverHandlerRef.revertValue();
|
||||||
}
|
|
||||||
|
try {
|
||||||
serverInjection.revertServerHandler(serverHandler);
|
if (getNetHandler() != null) {
|
||||||
|
// Restore packet listener
|
||||||
try {
|
try {
|
||||||
if (getNetHandler() != null) {
|
FieldUtils.writeField(netHandlerField, networkManager, serverHandlerRef.getOldValue(), true);
|
||||||
// Restore packet listener
|
} catch (IllegalAccessException e) {
|
||||||
try {
|
// Oh well
|
||||||
FieldUtils.writeField(netHandlerField, networkManager, serverHandlerRef.getOldValue(), true);
|
e.printStackTrace();
|
||||||
} catch (IllegalAccessException e) {
|
}
|
||||||
// Oh well
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serverInjection.revertServerHandler(serverHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,13 +41,18 @@ public class DefaultInstances {
|
|||||||
/**
|
/**
|
||||||
* The maximum height of the hierachy of creates types. Used to prevent cycles.
|
* The maximum height of the hierachy of creates types. Used to prevent cycles.
|
||||||
*/
|
*/
|
||||||
private final static int MAXIMUM_RECURSION = 20;
|
private int maximumRecursion = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ordered list of instance provider, from highest priority to lowest.
|
* Ordered list of instance provider, from highest priority to lowest.
|
||||||
*/
|
*/
|
||||||
private ImmutableList<InstanceProvider> registered;
|
private ImmutableList<InstanceProvider> registered;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the constructor must be non-null.
|
||||||
|
*/
|
||||||
|
private boolean nonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a default instance generator using the given instance providers.
|
* Construct a default instance generator using the given instance providers.
|
||||||
* @param registered - list of instance providers.
|
* @param registered - list of instance providers.
|
||||||
@ -56,6 +61,16 @@ public class DefaultInstances {
|
|||||||
this.registered = registered;
|
this.registered = registered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a given instance provider.
|
||||||
|
* @param other - instance provider to copy.
|
||||||
|
*/
|
||||||
|
public DefaultInstances(DefaultInstances other) {
|
||||||
|
this.nonNull = other.nonNull;
|
||||||
|
this.maximumRecursion = other.maximumRecursion;
|
||||||
|
this.registered = other.registered;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a default instance generator using the given instance providers.
|
* Construct a default instance generator using the given instance providers.
|
||||||
* @param instaceProviders - array of instance providers.
|
* @param instaceProviders - array of instance providers.
|
||||||
@ -81,6 +96,40 @@ public class DefaultInstances {
|
|||||||
return registered;
|
return registered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve whether or not the constructor's parameters must be non-null.
|
||||||
|
* @return TRUE if they must be non-null, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isNonNull() {
|
||||||
|
return nonNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether or not the constructor's parameters must be non-null.
|
||||||
|
* @param nonNull - TRUE if they must be non-null, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
public void setNonNull(boolean nonNull) {
|
||||||
|
this.nonNull = nonNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the the maximum height of the hierachy of creates types.
|
||||||
|
* @return Maximum height.
|
||||||
|
*/
|
||||||
|
public int getMaximumRecursion() {
|
||||||
|
return maximumRecursion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum height of the hierachy of creates types. Used to prevent cycles.
|
||||||
|
* @param maximumRecursion - maximum recursion height.
|
||||||
|
*/
|
||||||
|
public void setMaximumRecursion(int maximumRecursion) {
|
||||||
|
if (maximumRecursion < 1)
|
||||||
|
throw new IllegalArgumentException("Maxmimum recursion height must be one or higher.");
|
||||||
|
this.maximumRecursion = maximumRecursion;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a default instance or value that is assignable to this type.
|
* Retrieves a default instance or value that is assignable to this type.
|
||||||
* <p>
|
* <p>
|
||||||
@ -158,12 +207,8 @@ public class DefaultInstances {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T> T getDefaultInternal(Class<T> type, List<InstanceProvider> providers, int recursionLevel) {
|
private <T> T getDefaultInternal(Class<T> type, List<InstanceProvider> providers, int recursionLevel) {
|
||||||
|
|
||||||
// Guard against recursion
|
// The instance providiers should protect themselves against recursion
|
||||||
if (recursionLevel > MAXIMUM_RECURSION) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (InstanceProvider generator : providers) {
|
for (InstanceProvider generator : providers) {
|
||||||
Object value = generator.create(type);
|
Object value = generator.create(type);
|
||||||
|
|
||||||
@ -171,6 +216,11 @@ public class DefaultInstances {
|
|||||||
return (T) value;
|
return (T) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Guard against recursion
|
||||||
|
if (recursionLevel >= maximumRecursion) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Constructor<T> minimum = getMinimumConstructor(type);
|
Constructor<T> minimum = getMinimumConstructor(type);
|
||||||
|
|
||||||
// Create the type with this constructor using default values. This might fail, though.
|
// Create the type with this constructor using default values. This might fail, though.
|
||||||
@ -183,13 +233,18 @@ public class DefaultInstances {
|
|||||||
// Fill out
|
// Fill out
|
||||||
for (int i = 0; i < parameterCount; i++) {
|
for (int i = 0; i < parameterCount; i++) {
|
||||||
params[i] = getDefaultInternal(types[i], providers, recursionLevel + 1);
|
params[i] = getDefaultInternal(types[i], providers, recursionLevel + 1);
|
||||||
|
|
||||||
|
// Did we break the non-null contract?
|
||||||
|
if (params[i] == null && nonNull)
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return createInstance(type, minimum, types, params);
|
return createInstance(type, minimum, types, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Nope, we couldn't create this type
|
// Nope, we couldn't create this type
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// No suitable default value could be found
|
// No suitable default value could be found
|
||||||
@ -204,7 +259,7 @@ public class DefaultInstances {
|
|||||||
public DefaultInstances forEnhancer(Enhancer enhancer) {
|
public DefaultInstances forEnhancer(Enhancer enhancer) {
|
||||||
final Enhancer ex = enhancer;
|
final Enhancer ex = enhancer;
|
||||||
|
|
||||||
return new DefaultInstances(registered) {
|
return new DefaultInstances(this) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
protected <T> T createInstance(Class<T> type, Constructor<T> constructor, Class<?>[] types, Object[] params) {
|
protected <T> T createInstance(Class<T> type, Constructor<T> constructor, Class<?>[] types, Object[] params) {
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren