Made the object injector somewhat workable.
Dieser Commit ist enthalten in:
Ursprung
7e28aefb75
Commit
57c720681a
@ -1,8 +1,10 @@
|
||||
package com.comphenix.protocol.injector;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.Socket;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -60,10 +62,10 @@ public class NetworkObjectInjector extends PlayerInjector {
|
||||
|
||||
if (networkManager != null) {
|
||||
final Object networkDelegate = networkManagerRef.getOldValue();
|
||||
|
||||
Enhancer ex = new Enhancer();
|
||||
final Class<?> networkType = networkManager.getClass();
|
||||
final Enhancer ex = new Enhancer();
|
||||
|
||||
ex.setSuperclass(networkManager.getClass());
|
||||
ex.setSuperclass(networkType);
|
||||
ex.setClassLoader(manager.getClassLoader());
|
||||
ex.setCallback(new MethodInterceptor() {
|
||||
@Override
|
||||
@ -79,12 +81,12 @@ public class NetworkObjectInjector extends PlayerInjector {
|
||||
System.out.println("[Thread " + current.getId() + "] I'm committing suicide!");
|
||||
|
||||
// This is bad. Very bad. Thus, we prefer the NetworkFieldInjector ...
|
||||
throw new Error("Killing current thread.");
|
||||
throw new Error("Killing current thread. Ignore this.");
|
||||
}
|
||||
}
|
||||
|
||||
// OH OH! The queue method!
|
||||
if (method.equals(queueMethod)) {
|
||||
if (isEquivalentMethod(method, queueMethod)) {
|
||||
Packet packet = (Packet) args[0];
|
||||
|
||||
if (packet != null) {
|
||||
@ -107,8 +109,8 @@ public class NetworkObjectInjector extends PlayerInjector {
|
||||
}
|
||||
});
|
||||
|
||||
// Create instances of our network proxy.
|
||||
DefaultInstances generator = DefaultInstances.fromArray(PrimitiveGenerator.INSTANCE, new InstanceProvider() {
|
||||
// Hacks! Get your daily hack here!
|
||||
DefaultInstances generator = new DefaultInstances(PrimitiveGenerator.INSTANCE, new InstanceProvider() {
|
||||
@Override
|
||||
public Object create(@Nullable Class<?> type) {
|
||||
if (type.equals(Socket.class))
|
||||
@ -120,11 +122,22 @@ public class NetworkObjectInjector extends PlayerInjector {
|
||||
else
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
}) {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected <T> T createInstance(Class<T> type, Constructor<T> constructor,
|
||||
Class<?>[] types, Object[] params) {
|
||||
// Use cglib instead of standard reflection
|
||||
if (type.equals(networkType))
|
||||
return (T) ex.create(types, params);
|
||||
else
|
||||
return super.createInstance(type, constructor, types, params);
|
||||
}
|
||||
};
|
||||
|
||||
// Create our proxy object
|
||||
@SuppressWarnings("unchecked")
|
||||
Object networkProxy = generator.getDefault(ex.createClass());
|
||||
Object networkProxy = generator.getDefault(networkType);
|
||||
|
||||
// Get the two threads we'll have to kill
|
||||
try {
|
||||
@ -140,6 +153,12 @@ public class NetworkObjectInjector extends PlayerInjector {
|
||||
}
|
||||
}
|
||||
|
||||
// See if the two methods are the same
|
||||
private boolean isEquivalentMethod(Method a, Method b) {
|
||||
return a.getName().equals(b.getName()) &&
|
||||
Arrays.equals(a.getParameterTypes(), b.getParameterTypes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanupAll() {
|
||||
// Clean up
|
||||
|
@ -55,6 +55,15 @@ public class DefaultInstances {
|
||||
this.registered = registered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a default instance generator using the given instance providers.
|
||||
* @param instaceProviders - array of instance providers.
|
||||
* @return An default instance generator.
|
||||
*/
|
||||
public DefaultInstances(InstanceProvider... instaceProviders) {
|
||||
this(ImmutableList.copyOf(instaceProviders));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a default instance generator using the given instance providers.
|
||||
* @param instaceProviders - array of instance providers.
|
||||
@ -64,7 +73,6 @@ public class DefaultInstances {
|
||||
return new DefaultInstances(ImmutableList.copyOf(instaceProviders));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a immutable list of every default object providers that generates instances.
|
||||
* @return Table of instance providers.
|
||||
@ -131,7 +139,7 @@ public class DefaultInstances {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
Constructor<?> minimum = null;
|
||||
Constructor<T> minimum = null;
|
||||
int lastCount = Integer.MAX_VALUE;
|
||||
|
||||
// Find the constructor with the fewest parameters
|
||||
@ -142,7 +150,7 @@ public class DefaultInstances {
|
||||
// require itself in the constructor.
|
||||
if (types.length < lastCount) {
|
||||
if (!contains(types, type)) {
|
||||
minimum = candidate;
|
||||
minimum = (Constructor<T>) candidate;
|
||||
lastCount = types.length;
|
||||
|
||||
// Don't loop again if we've already found the best possible constructor
|
||||
@ -163,7 +171,7 @@ public class DefaultInstances {
|
||||
params[i] = getDefaultInternal(types[i], providers, recursionLevel + 1);
|
||||
}
|
||||
|
||||
return (T) minimum.newInstance(params);
|
||||
return createInstance(type, minimum, types, params);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
@ -174,8 +182,26 @@ public class DefaultInstances {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the default instance provider to create a class from a given constructor.
|
||||
* The default method uses reflection.
|
||||
* @param type - the type to create.
|
||||
* @param constructor - the constructor to use.
|
||||
* @param types - type of each parameter in order.
|
||||
* @param params - value of each parameter in order.
|
||||
* @return The constructed instance.
|
||||
*/
|
||||
protected <T> T createInstance(Class<T> type, Constructor<T> constructor, Class<?>[] types, Object[] params) {
|
||||
try {
|
||||
return (T) constructor.newInstance(params);
|
||||
} catch (Exception e) {
|
||||
// Cannot create it
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// We avoid Apache's utility methods to stay backwards compatible
|
||||
private <T> boolean contains(T[] elements, T elementToFind) {
|
||||
protected <T> boolean contains(T[] elements, T elementToFind) {
|
||||
// Search for the given element in the array
|
||||
for (T element : elements) {
|
||||
if (Objects.equal(elementToFind, element))
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren