Attempting to add support for MCPC.
Still have to track down a very elusive bug however.
Dieser Commit ist enthalten in:
Ursprung
8b12907dfb
Commit
e8c615b203
@ -19,6 +19,7 @@ package com.comphenix.protocol.async;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
@ -67,10 +68,16 @@ class PacketProcessingQueue extends AbstractConcurrentListenerMultimap<AsyncList
|
|||||||
public PacketProcessingQueue(PlayerSendingHandler sendingHandler, int initialSize, int maximumSize, int maximumConcurrency) {
|
public PacketProcessingQueue(PlayerSendingHandler sendingHandler, int initialSize, int maximumSize, int maximumConcurrency) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
try {
|
||||||
this.processingQueue = Synchronization.queue(MinMaxPriorityQueue.
|
this.processingQueue = Synchronization.queue(MinMaxPriorityQueue.
|
||||||
expectedSize(initialSize).
|
expectedSize(initialSize).
|
||||||
maximumSize(maximumSize).
|
maximumSize(maximumSize).
|
||||||
<PacketEventHolder>create(), null);
|
<PacketEventHolder>create(), null);
|
||||||
|
} catch (IncompatibleClassChangeError e) {
|
||||||
|
// It's a Beta class after all
|
||||||
|
this.processingQueue = Synchronization.queue(
|
||||||
|
new PriorityQueue<PacketEventHolder>(), null);
|
||||||
|
}
|
||||||
|
|
||||||
this.maximumConcurrency = maximumConcurrency;
|
this.maximumConcurrency = maximumConcurrency;
|
||||||
this.concurrentProcessing = new Semaphore(maximumConcurrency);
|
this.concurrentProcessing = new Semaphore(maximumConcurrency);
|
||||||
|
@ -164,9 +164,9 @@ class EntityUtilities {
|
|||||||
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
|
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
|
||||||
Object worldServer = unwrapper.unwrapItem(world);
|
Object worldServer = unwrapper.unwrapItem(world);
|
||||||
|
|
||||||
// We have to rely on the class naming here.
|
|
||||||
if (entityTrackerField == null)
|
if (entityTrackerField == null)
|
||||||
entityTrackerField = FuzzyReflection.fromObject(worldServer).getFieldByType(".*Tracker");
|
entityTrackerField = FuzzyReflection.fromObject(worldServer).
|
||||||
|
getFieldByType("tracker", MinecraftReflection.getEntityTrackerClass());
|
||||||
|
|
||||||
// Get the tracker
|
// Get the tracker
|
||||||
Object tracker = null;
|
Object tracker = null;
|
||||||
@ -191,7 +191,7 @@ class EntityUtilities {
|
|||||||
|
|
||||||
// The Minecraft field that's NOT filled in by the constructor
|
// The Minecraft field that's NOT filled in by the constructor
|
||||||
trackedEntitiesField = FuzzyReflection.fromObject(tracker, true).
|
trackedEntitiesField = FuzzyReflection.fromObject(tracker, true).
|
||||||
getFieldByType(MinecraftReflection.getMinecraftObjectMatcher(), ignoredTypes);
|
getFieldByType(MinecraftReflection.getMinecraftObjectRegex(), ignoredTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the entity hashmap
|
// Read the entity hashmap
|
||||||
@ -250,8 +250,16 @@ class EntityUtilities {
|
|||||||
|
|
||||||
// Handle NULL cases
|
// Handle NULL cases
|
||||||
if (trackerEntry != null) {
|
if (trackerEntry != null) {
|
||||||
if (trackerField == null)
|
if (trackerField == null) {
|
||||||
|
try {
|
||||||
trackerField = trackerEntry.getClass().getField("tracker");
|
trackerField = trackerEntry.getClass().getField("tracker");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
// Assume it's the first public entity field then
|
||||||
|
trackerField = FuzzyReflection.fromObject(trackerEntry).getFieldByType(
|
||||||
|
"tracker", MinecraftReflection.getEntityClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tracker = FieldUtils.readField(trackerField, trackerEntry, true);
|
tracker = FieldUtils.readField(trackerField, trackerEntry, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ class PacketInjector {
|
|||||||
if (intHashMap == null) {
|
if (intHashMap == null) {
|
||||||
// We're looking for the first static field with a Minecraft-object. This should be a IntHashMap.
|
// We're looking for the first static field with a Minecraft-object. This should be a IntHashMap.
|
||||||
Field intHashMapField = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass(), true).
|
Field intHashMapField = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass(), true).
|
||||||
getFieldByType(MinecraftReflection.getMinecraftObjectMatcher());
|
getFieldByType(MinecraftReflection.getMinecraftObjectRegex());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
intHashMap = FieldUtils.readField(intHashMapField, (Object) null, true);
|
intHashMap = FieldUtils.readField(intHashMapField, (Object) null, true);
|
||||||
|
@ -107,12 +107,10 @@ class InjectedServerConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void injectListenerThread() {
|
private void injectListenerThread() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (listenerThreadField == null)
|
if (listenerThreadField == null)
|
||||||
listenerThreadField = FuzzyReflection.fromObject(minecraftServer).
|
listenerThreadField = FuzzyReflection.fromObject(minecraftServer).
|
||||||
getFieldByType(".*NetworkListenThread");
|
getFieldByType("networkListenThread", MinecraftReflection.getNetworkListenThreadClass());
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
reporter.reportDetailed(this, "Cannot find listener thread in MinecraftServer.", e, minecraftServer);
|
reporter.reportDetailed(this, "Cannot find listener thread in MinecraftServer.", e, minecraftServer);
|
||||||
return;
|
return;
|
||||||
|
@ -20,7 +20,8 @@ package com.comphenix.protocol.injector.player;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import net.sf.cglib.proxy.Callback;
|
import net.sf.cglib.proxy.Callback;
|
||||||
import net.sf.cglib.proxy.CallbackFilter;
|
import net.sf.cglib.proxy.CallbackFilter;
|
||||||
import net.sf.cglib.proxy.Enhancer;
|
import net.sf.cglib.proxy.Enhancer;
|
||||||
@ -43,6 +44,7 @@ import com.comphenix.protocol.reflect.VolatileField;
|
|||||||
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.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a player hook into the NetServerHandler class.
|
* Represents a player hook into the NetServerHandler class.
|
||||||
@ -91,9 +93,59 @@ public class NetworkServerInjector extends PlayerInjector {
|
|||||||
|
|
||||||
// Get the send packet method!
|
// Get the send packet method!
|
||||||
if (hasInitialized) {
|
if (hasInitialized) {
|
||||||
if (sendPacketMethod == null)
|
if (sendPacketMethod == null) {
|
||||||
|
try {
|
||||||
sendPacketMethod = FuzzyReflection.fromObject(serverHandler).getMethodByName("sendPacket.*");
|
sendPacketMethod = FuzzyReflection.fromObject(serverHandler).getMethodByName("sendPacket.*");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
Map<String, Method> netServer = getMethodList(
|
||||||
|
MinecraftReflection.getNetServerHandlerClass(), MinecraftReflection.getPacketClass());
|
||||||
|
Map<String, Method> netHandler = getMethodList(
|
||||||
|
MinecraftReflection.getNetHandlerClass(), MinecraftReflection.getPacketClass());
|
||||||
|
|
||||||
|
// Remove every method in net handler from net server
|
||||||
|
for (String methodName : netHandler.keySet()) {
|
||||||
|
netServer.remove(methodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The remainder is the send packet method
|
||||||
|
if (netServer.size() == 1) {
|
||||||
|
Method[] methods = netServer.values().toArray(new Method[0]);
|
||||||
|
sendPacketMethod = methods[0];
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unable to find the sendPacket method in NetServerHandler/PlayerConnection.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a method mapped list of every method with the given signature.
|
||||||
|
* @param source - class source.
|
||||||
|
* @param params - parameters.
|
||||||
|
* @return Method mapped list.
|
||||||
|
*/
|
||||||
|
private Map<String, Method> getMethodList(Class<?> source, Class<?>... params) {
|
||||||
|
return getMappedMethods(
|
||||||
|
FuzzyReflection.fromClass(source, true).
|
||||||
|
getMethodListByParameters(Void.TYPE, params)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve every method as a map over names.
|
||||||
|
* <p>
|
||||||
|
* Note that overloaded methods will only occur once in the resulting map.
|
||||||
|
* @param methods - every method.
|
||||||
|
* @return A map over every given method.
|
||||||
|
*/
|
||||||
|
private Map<String, Method> getMappedMethods(List<Method> methods) {
|
||||||
|
Map<String, Method> map = Maps.newHashMap();
|
||||||
|
|
||||||
|
for (Method method : methods) {
|
||||||
|
map.put(method.getName(), method);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -297,7 +349,21 @@ public class NetworkServerInjector extends PlayerInjector {
|
|||||||
FieldUtils.writeField(disconnectField, handler, value);
|
FieldUtils.writeField(disconnectField, handler, value);
|
||||||
|
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
reporter.reportDetailed(this, "Unable to find disconnect field. Is ProtocolLib up to date?", e, handler);
|
// Assume it's the first ...
|
||||||
|
if (disconnectField == null) {
|
||||||
|
disconnectField = FuzzyReflection.fromObject(handler).getFieldByType("disconnected", boolean.class);
|
||||||
|
reporter.reportWarning(this, "Unable to find 'disconnected' field. Assuming " + disconnectField);
|
||||||
|
|
||||||
|
// Try again
|
||||||
|
if (disconnectField != null) {
|
||||||
|
setDisconnect(handler, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is really bad
|
||||||
|
reporter.reportDetailed(this, "Cannot find disconnected field. Is ProtocolLib up to date?", e);
|
||||||
|
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
reporter.reportWarning(this, "Unable to update disconnected field. Player quit event may be sent twice.");
|
reporter.reportWarning(this, "Unable to update disconnected field. Player quit event may be sent twice.");
|
||||||
}
|
}
|
||||||
|
@ -167,8 +167,8 @@ abstract class PlayerInjector {
|
|||||||
|
|
||||||
// Next, get the network manager
|
// Next, get the network manager
|
||||||
if (networkManagerField == null)
|
if (networkManagerField == null)
|
||||||
networkManagerField = FuzzyReflection.fromObject(serverHandler).
|
networkManagerField = FuzzyReflection.fromObject(serverHandler).getFieldByType(
|
||||||
getFieldByType(".*" + MinecraftReflection.getNetworkManagerName());
|
"networkManager", MinecraftReflection.getNetworkManagerClass());
|
||||||
initializeNetworkManager(networkManagerField, serverHandler);
|
initializeNetworkManager(networkManagerField, serverHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ abstract class PlayerInjector {
|
|||||||
|
|
||||||
if (netLoginNetworkField == null)
|
if (netLoginNetworkField == null)
|
||||||
netLoginNetworkField = FuzzyReflection.fromObject(netLoginHandler).
|
netLoginNetworkField = FuzzyReflection.fromObject(netLoginHandler).
|
||||||
getFieldByType(".*" + MinecraftReflection.getNetworkManagerName());
|
getFieldByType("networkManager", MinecraftReflection.getNetworkManagerClass());
|
||||||
initializeNetworkManager(netLoginNetworkField, netLoginHandler);
|
initializeNetworkManager(netLoginNetworkField, netLoginHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,7 +290,13 @@ abstract class PlayerInjector {
|
|||||||
// Execute disconnect on it
|
// Execute disconnect on it
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
if (disconnect == null) {
|
if (disconnect == null) {
|
||||||
|
try {
|
||||||
disconnect = FuzzyReflection.fromObject(handler).getMethodByName("disconnect.*");
|
disconnect = FuzzyReflection.fromObject(handler).getMethodByName("disconnect.*");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// Just assume it's the first String method
|
||||||
|
disconnect = FuzzyReflection.fromObject(handler).getMethodByParameters("disconnect", String.class);
|
||||||
|
reporter.reportWarning(this, "Cannot find disconnect method by name. Assuming " + disconnect);
|
||||||
|
}
|
||||||
|
|
||||||
// Save the method for later
|
// Save the method for later
|
||||||
if (usingNetServer)
|
if (usingNetServer)
|
||||||
@ -380,7 +386,7 @@ abstract class PlayerInjector {
|
|||||||
try {
|
try {
|
||||||
// Well, that sucks. Try just Minecraft objects then.
|
// Well, that sucks. Try just Minecraft objects then.
|
||||||
netHandlerField = FuzzyReflection.fromClass(networkManager.getClass(), true).
|
netHandlerField = FuzzyReflection.fromClass(networkManager.getClass(), true).
|
||||||
getFieldByType(MinecraftReflection.getMinecraftObjectMatcher());
|
getFieldByType(MinecraftReflection.getMinecraftObjectRegex());
|
||||||
|
|
||||||
} catch (RuntimeException e2) {
|
} catch (RuntimeException e2) {
|
||||||
throw new IllegalAccessException("Cannot locate net handler. " + e2.getMessage());
|
throw new IllegalAccessException("Cannot locate net handler. " + e2.getMessage());
|
||||||
|
@ -72,4 +72,64 @@ public abstract class AbstractFuzzyMatcher<T> implements Comparable<AbstractFuzz
|
|||||||
// No match
|
// No match
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a fuzzy matcher that returns the opposite result of the current matcher.
|
||||||
|
* @return An inverted fuzzy matcher.
|
||||||
|
*/
|
||||||
|
public AbstractFuzzyMatcher<T> inverted() {
|
||||||
|
return new AbstractFuzzyMatcher<T>() {
|
||||||
|
@Override
|
||||||
|
public boolean isMatch(T value, Object parent) {
|
||||||
|
return !AbstractFuzzyMatcher.this.isMatch(value, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateRoundNumber() {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require that this and the given matcher be TRUE.
|
||||||
|
* @param other - the other fuzzy matcher.
|
||||||
|
* @return A combined fuzzy matcher.
|
||||||
|
*/
|
||||||
|
public AbstractFuzzyMatcher<T> and(final AbstractFuzzyMatcher<T> other) {
|
||||||
|
return new AbstractFuzzyMatcher<T>() {
|
||||||
|
@Override
|
||||||
|
public boolean isMatch(T value, Object parent) {
|
||||||
|
// They both have to be true
|
||||||
|
return AbstractFuzzyMatcher.this.isMatch(value, parent) &&
|
||||||
|
other.isMatch(value, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateRoundNumber() {
|
||||||
|
return combineRounds(AbstractFuzzyMatcher.this.getRoundNumber(), other.getRoundNumber());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require that either this or the other given matcher be TRUE.
|
||||||
|
* @param other - the other fuzzy matcher.
|
||||||
|
* @return A combined fuzzy matcher.
|
||||||
|
*/
|
||||||
|
public AbstractFuzzyMatcher<T> or(final AbstractFuzzyMatcher<T> other) {
|
||||||
|
return new AbstractFuzzyMatcher<T>() {
|
||||||
|
@Override
|
||||||
|
public boolean isMatch(T value, Object parent) {
|
||||||
|
// Either can be true
|
||||||
|
return AbstractFuzzyMatcher.this.isMatch(value, parent) ||
|
||||||
|
other.isMatch(value, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateRoundNumber() {
|
||||||
|
return combineRounds(AbstractFuzzyMatcher.this.getRoundNumber(), other.getRoundNumber());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,11 @@ import javax.annotation.Nonnull;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzzyMatcher<T> {
|
public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzzyMatcher<T> {
|
||||||
// Accessibility matchers
|
// Accessibility matchers
|
||||||
private int modifiersRequired;
|
protected int modifiersRequired;
|
||||||
private int modifiersBanned;
|
protected int modifiersBanned;
|
||||||
|
|
||||||
private Pattern nameRegex;
|
protected Pattern nameRegex;
|
||||||
private AbstractFuzzyMatcher<Class<?>> declaringMatcher = ExactClassMatcher.MATCH_ALL;
|
protected AbstractFuzzyMatcher<Class<?>> declaringMatcher = ExactClassMatcher.MATCH_ALL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not this contract can be modified.
|
* Whether or not this contract can be modified.
|
||||||
@ -89,7 +89,7 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder<T> declaringClassExactType(Class<?> declaringClass) {
|
public Builder<T> declaringClassExactType(Class<?> declaringClass) {
|
||||||
member.declaringMatcher = ExactClassMatcher.matchExact(declaringClass);
|
member.declaringMatcher = FuzzyMatchers.matchExact(declaringClass);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder<T> declaringClassSuperOf(Class<?> declaringClass) {
|
public Builder<T> declaringClassSuperOf(Class<?> declaringClass) {
|
||||||
member.declaringMatcher = ExactClassMatcher.matchSuper(declaringClass);
|
member.declaringMatcher = FuzzyMatchers.matchSuper(declaringClass);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ public abstract class AbstractFuzzyMember<T extends Member> extends AbstractFuzz
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder<T> declaringClassDerivedOf(Class<?> declaringClass) {
|
public Builder<T> declaringClassDerivedOf(Class<?> declaringClass) {
|
||||||
member.declaringMatcher = ExactClassMatcher.matchDerived(declaringClass);
|
member.declaringMatcher = FuzzyMatchers.matchDerived(declaringClass);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,38 +34,12 @@ class ExactClassMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
private final Class<?> matcher;
|
private final Class<?> matcher;
|
||||||
private final Options option;
|
private final Options option;
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a class matcher that matches types exactly.
|
|
||||||
* @param matcher - the matching class.
|
|
||||||
*/
|
|
||||||
public static ExactClassMatcher matchExact(Class<?> matcher) {
|
|
||||||
return new ExactClassMatcher(matcher, Options.MATCH_EXACT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a class matcher that matches super types of the given class.
|
|
||||||
* @param matcher - the matching type must be a super class of this type.
|
|
||||||
* @return A new class mathcher.
|
|
||||||
*/
|
|
||||||
public static ExactClassMatcher matchSuper(Class<?> matcher) {
|
|
||||||
return new ExactClassMatcher(matcher, Options.MATCH_SUPER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a class matcher that matches derived types of the given class.
|
|
||||||
* @param matcher - the matching type must be a derived class of this type.
|
|
||||||
* @return A new class mathcher.
|
|
||||||
*/
|
|
||||||
public static ExactClassMatcher matchDerived(Class<?> matcher) {
|
|
||||||
return new ExactClassMatcher(matcher, Options.MATCH_DERIVED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new class matcher.
|
* Constructs a new class matcher.
|
||||||
* @param matcher - the matching class, or NULL to represent anything.
|
* @param matcher - the matching class, or NULL to represent anything.
|
||||||
* @param option - options specifying the matching rules.
|
* @param option - options specifying the matching rules.
|
||||||
*/
|
*/
|
||||||
private ExactClassMatcher(Class<?> matcher, Options option) {
|
ExactClassMatcher(Class<?> matcher, Options option) {
|
||||||
this.matcher = matcher;
|
this.matcher = matcher;
|
||||||
this.option = option;
|
this.option = option;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package com.comphenix.protocol.reflect;
|
package com.comphenix.protocol.reflect;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Member;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
@ -107,32 +107,6 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Match the parent class of a method, field or constructor.
|
|
||||||
* @return Parent matcher.
|
|
||||||
*/
|
|
||||||
public static AbstractFuzzyMatcher<Class<?>> matchParent() {
|
|
||||||
return new AbstractFuzzyMatcher<Class<?>>() {
|
|
||||||
@Override
|
|
||||||
public boolean isMatch(Class<?> value, Object parent) {
|
|
||||||
if (parent instanceof Member) {
|
|
||||||
return ((Member) parent).getDeclaringClass().equals(value);
|
|
||||||
} else if (parent instanceof Class) {
|
|
||||||
return parent.equals(value);
|
|
||||||
} else {
|
|
||||||
// Can't be a match
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int calculateRoundNumber() {
|
|
||||||
// We match a very specific type
|
|
||||||
return -100;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new fuzzy class contract with the given contracts.
|
* Constructs a new fuzzy class contract with the given contracts.
|
||||||
* @param fieldContracts - field contracts.
|
* @param fieldContracts - field contracts.
|
||||||
@ -197,7 +171,7 @@ public class FuzzyClassContract extends AbstractFuzzyMatcher<Class<?>> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMatch(Class<?> value, Object parent) {
|
public boolean isMatch(Class<?> value, Object parent) {
|
||||||
FuzzyReflection reflection = FuzzyReflection.fromClass(value);
|
FuzzyReflection reflection = FuzzyReflection.fromClass(value, true);
|
||||||
|
|
||||||
// Make sure all the contracts are valid
|
// Make sure all the contracts are valid
|
||||||
return processContracts(reflection.getFields(), value, fieldContracts) &&
|
return processContracts(reflection.getFields(), value, fieldContracts) &&
|
||||||
|
@ -13,6 +13,11 @@ import javax.annotation.Nonnull;
|
|||||||
public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
||||||
private AbstractFuzzyMatcher<Class<?>> typeMatcher = ExactClassMatcher.MATCH_ALL;
|
private AbstractFuzzyMatcher<Class<?>> typeMatcher = ExactClassMatcher.MATCH_ALL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a builder for a field matcher.
|
||||||
|
*
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
public static class Builder extends AbstractFuzzyMember.Builder<FuzzyFieldContract> {
|
public static class Builder extends AbstractFuzzyMember.Builder<FuzzyFieldContract> {
|
||||||
@Override
|
@Override
|
||||||
public Builder requireModifier(int modifier) {
|
public Builder requireModifier(int modifier) {
|
||||||
@ -74,12 +79,22 @@ public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Builder typeExact(Class<?> type) {
|
public Builder typeExact(Class<?> type) {
|
||||||
member.typeMatcher = ExactClassMatcher.matchExact(type);
|
member.typeMatcher = FuzzyMatchers.matchExact(type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder typeSuperOf(Class<?> type) {
|
public Builder typeSuperOf(Class<?> type) {
|
||||||
member.typeMatcher = ExactClassMatcher.matchSuper(type);
|
member.typeMatcher = FuzzyMatchers.matchSuper(type);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder typeDerivedOf(Class<?> type) {
|
||||||
|
member.typeMatcher = FuzzyMatchers.matchDerived(type);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder typeMatches(AbstractFuzzyMatcher<Class<?>> matcher) {
|
||||||
|
member.typeMatcher = matcher;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +105,10 @@ public class FuzzyFieldContract extends AbstractFuzzyMember<Field> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new fuzzy field contract builder.
|
||||||
|
* @return New fuzzy field contract builder.
|
||||||
|
*/
|
||||||
public static Builder newBuilder() {
|
public static Builder newBuilder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,100 @@
|
|||||||
|
package com.comphenix.protocol.reflect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Member;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains factory methods for matching classes.
|
||||||
|
*
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
public class FuzzyMatchers {
|
||||||
|
private FuzzyMatchers() {
|
||||||
|
// Don't make this constructable
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a class matcher that matches types exactly.
|
||||||
|
* @param matcher - the matching class.
|
||||||
|
*/
|
||||||
|
public static AbstractFuzzyMatcher<Class<?>> matchExact(Class<?> matcher) {
|
||||||
|
return new ExactClassMatcher(matcher, ExactClassMatcher.Options.MATCH_EXACT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a class matcher that matches super types of the given class.
|
||||||
|
* @param matcher - the matching type must be a super class of this type.
|
||||||
|
* @return A new class mathcher.
|
||||||
|
*/
|
||||||
|
public static AbstractFuzzyMatcher<Class<?>> matchSuper(Class<?> matcher) {
|
||||||
|
return new ExactClassMatcher(matcher, ExactClassMatcher.Options.MATCH_SUPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a class matcher that matches derived types of the given class.
|
||||||
|
* @param matcher - the matching type must be a derived class of this type.
|
||||||
|
* @return A new class mathcher.
|
||||||
|
*/
|
||||||
|
public static AbstractFuzzyMatcher<Class<?>> matchDerived(Class<?> matcher) {
|
||||||
|
return new ExactClassMatcher(matcher, ExactClassMatcher.Options.MATCH_DERIVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a class matcher based on the canonical names of classes.
|
||||||
|
* @param regex - regular expression pattern matching class names.
|
||||||
|
* @param priority - the priority this matcher takes - higher is better.
|
||||||
|
* @return A fuzzy class matcher based on name.
|
||||||
|
*/
|
||||||
|
public static AbstractFuzzyMatcher<Class<?>> matchRegex(final Pattern regex, final int priority) {
|
||||||
|
return new AbstractFuzzyMatcher<Class<?>>() {
|
||||||
|
@Override
|
||||||
|
public boolean isMatch(Class<?> value, Object parent) {
|
||||||
|
if (value != null)
|
||||||
|
return regex.matcher(value.getCanonicalName()).matches();
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateRoundNumber() {
|
||||||
|
return -priority;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a class matcher based on the canonical names of classes.
|
||||||
|
* @param regex - regular expression matching class names.
|
||||||
|
* @param priority - the priority this matcher takes - higher is better.
|
||||||
|
* @return A fuzzy class matcher based on name.
|
||||||
|
*/
|
||||||
|
public static AbstractFuzzyMatcher<Class<?>> matchRegex(String regex, final int priority) {
|
||||||
|
return FuzzyMatchers.matchRegex(Pattern.compile(regex), priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match the parent class of a method, field or constructor.
|
||||||
|
* @return Parent matcher.
|
||||||
|
*/
|
||||||
|
public static AbstractFuzzyMatcher<Class<?>> matchParent() {
|
||||||
|
return new AbstractFuzzyMatcher<Class<?>>() {
|
||||||
|
@Override
|
||||||
|
public boolean isMatch(Class<?> value, Object parent) {
|
||||||
|
if (parent instanceof Member) {
|
||||||
|
return ((Member) parent).getDeclaringClass().equals(value);
|
||||||
|
} else if (parent instanceof Class) {
|
||||||
|
return parent.equals(value);
|
||||||
|
} else {
|
||||||
|
// Can't be a match
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateRoundNumber() {
|
||||||
|
// We match a very specific type
|
||||||
|
return -100;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -85,6 +85,11 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
// Expected parameter count
|
// Expected parameter count
|
||||||
private Integer paramCount;
|
private Integer paramCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a builder for a fuzzy method contract.
|
||||||
|
*
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
public static class Builder extends AbstractFuzzyMember.Builder<FuzzyMethodContract> {
|
public static class Builder extends AbstractFuzzyMember.Builder<FuzzyMethodContract> {
|
||||||
public Builder requireModifier(int modifier) {
|
public Builder requireModifier(int modifier) {
|
||||||
super.requireModifier(modifier);
|
super.requireModifier(modifier);
|
||||||
@ -145,19 +150,19 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder parameterExactType(Class<?> type) {
|
public Builder parameterExactType(Class<?> type) {
|
||||||
member.paramMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchExact(type)));
|
member.paramMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchExact(type)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new required parameter whose type must be a superlcass of the given type.
|
* Add a new required parameter whose type must be a superclass of the given type.
|
||||||
* <p>
|
* <p>
|
||||||
* If a parameter is of type Number, any derived class (Integer, Long, etc.) will match it.
|
* If a parameter is of type Number, any derived class (Integer, Long, etc.) will match it.
|
||||||
* @param type - a type or derived type of the matching parameter.
|
* @param type - a type or derived type of the matching parameter.
|
||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder parameterSuperOf(Class<?> type) {
|
public Builder parameterSuperOf(Class<?> type) {
|
||||||
member.paramMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchSuper(type)));
|
member.paramMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchSuper(type)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +183,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder parameterExactType(Class<?> type, int index) {
|
public Builder parameterExactType(Class<?> type, int index) {
|
||||||
member.paramMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchExact(type), index));
|
member.paramMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchExact(type), index));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +196,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder parameterSuperOf(Class<?> type, int index) {
|
public Builder parameterSuperOf(Class<?> type, int index) {
|
||||||
member.paramMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchSuper(type), index));
|
member.paramMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchSuper(type), index));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +235,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder returnTypeExact(Class<?> type) {
|
public Builder returnTypeExact(Class<?> type) {
|
||||||
member.returnMatcher = ExactClassMatcher.matchExact(type);
|
member.returnMatcher = FuzzyMatchers.matchExact(type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +245,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder returnDerivedOf(Class<?> type) {
|
public Builder returnDerivedOf(Class<?> type) {
|
||||||
member.returnMatcher = ExactClassMatcher.matchDerived(type);
|
member.returnMatcher = FuzzyMatchers.matchDerived(type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +265,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder exceptionExactType(Class<?> type) {
|
public Builder exceptionExactType(Class<?> type) {
|
||||||
member.exceptionMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchExact(type)));
|
member.exceptionMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchExact(type)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +275,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder exceptionSuperOf(Class<?> type) {
|
public Builder exceptionSuperOf(Class<?> type) {
|
||||||
member.exceptionMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchSuper(type)));
|
member.exceptionMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchSuper(type)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +296,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder exceptionExactType(Class<?> type, int index) {
|
public Builder exceptionExactType(Class<?> type, int index) {
|
||||||
member.exceptionMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchExact(type), index));
|
member.exceptionMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchExact(type), index));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +307,7 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
* @return This builder, for chaining.
|
* @return This builder, for chaining.
|
||||||
*/
|
*/
|
||||||
public Builder exceptionSuperOf(Class<?> type, int index) {
|
public Builder exceptionSuperOf(Class<?> type, int index) {
|
||||||
member.exceptionMatchers.add(new ParameterClassMatcher(ExactClassMatcher.matchSuper(type), index));
|
member.exceptionMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchSuper(type), index));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,6 +335,10 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a method contract builder.
|
||||||
|
* @return Method contract builder.
|
||||||
|
*/
|
||||||
public static Builder newBuilder() {
|
public static Builder newBuilder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,6 @@ public class FuzzyReflection {
|
|||||||
* @throws IllegalArgumentException If the field cannot be found.
|
* @throws IllegalArgumentException If the field cannot be found.
|
||||||
*/
|
*/
|
||||||
public Field getFieldByName(String nameRegex) {
|
public Field getFieldByName(String nameRegex) {
|
||||||
|
|
||||||
Pattern match = Pattern.compile(nameRegex);
|
Pattern match = Pattern.compile(nameRegex);
|
||||||
|
|
||||||
for (Field field : getFields()) {
|
for (Field field : getFields()) {
|
||||||
@ -276,7 +275,6 @@ public class FuzzyReflection {
|
|||||||
* @return The first field with a type that is an instance of the given type.
|
* @return The first field with a type that is an instance of the given type.
|
||||||
*/
|
*/
|
||||||
public Field getFieldByType(String name, Class<?> type) {
|
public Field getFieldByType(String name, Class<?> type) {
|
||||||
|
|
||||||
List<Field> fields = getFieldListByType(type);
|
List<Field> fields = getFieldListByType(type);
|
||||||
|
|
||||||
if (fields.size() > 0) {
|
if (fields.size() > 0) {
|
||||||
@ -295,7 +293,6 @@ public class FuzzyReflection {
|
|||||||
* @return Every field with a type that is an instance of the given type.
|
* @return Every field with a type that is an instance of the given type.
|
||||||
*/
|
*/
|
||||||
public List<Field> getFieldListByType(Class<?> type) {
|
public List<Field> getFieldListByType(Class<?> type) {
|
||||||
|
|
||||||
List<Field> fields = new ArrayList<Field>();
|
List<Field> fields = new ArrayList<Field>();
|
||||||
|
|
||||||
// Field with a compatible type
|
// Field with a compatible type
|
||||||
|
@ -17,9 +17,17 @@
|
|||||||
|
|
||||||
package com.comphenix.protocol.utility;
|
package com.comphenix.protocol.utility;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -29,6 +37,13 @@ import org.bukkit.Server;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
||||||
|
import com.comphenix.protocol.reflect.AbstractFuzzyMatcher;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyClassContract;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyMatchers;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyFieldContract;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyMethodContract;
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
|
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,7 +55,7 @@ public class MinecraftReflection {
|
|||||||
/**
|
/**
|
||||||
* Regular expression that matches a Minecraft object.
|
* Regular expression that matches a Minecraft object.
|
||||||
* <p>
|
* <p>
|
||||||
* Replaced by the method {@link #getMinecraftObjectMatcher()}.
|
* Replaced by the method {@link #getMinecraftObjectRegex()}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static final String MINECRAFT_OBJECT = "net\\.minecraft(\\.\\w+)+";
|
public static final String MINECRAFT_OBJECT = "net\\.minecraft(\\.\\w+)+";
|
||||||
@ -81,12 +96,20 @@ public class MinecraftReflection {
|
|||||||
* Retrieve a regular expression that can match Minecraft package objects.
|
* Retrieve a regular expression that can match Minecraft package objects.
|
||||||
* @return Minecraft package matcher.
|
* @return Minecraft package matcher.
|
||||||
*/
|
*/
|
||||||
public static String getMinecraftObjectMatcher() {
|
public static String getMinecraftObjectRegex() {
|
||||||
if (DYNAMIC_PACKAGE_MATCHER == null)
|
if (DYNAMIC_PACKAGE_MATCHER == null)
|
||||||
getMinecraftPackage();
|
getMinecraftPackage();
|
||||||
return DYNAMIC_PACKAGE_MATCHER;
|
return DYNAMIC_PACKAGE_MATCHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a abstract fuzzy class matcher for Minecraft objects.
|
||||||
|
* @return A matcher for Minecraft objects.
|
||||||
|
*/
|
||||||
|
public static AbstractFuzzyMatcher<Class<?>> getMinecraftObjectMatcher() {
|
||||||
|
return FuzzyMatchers.matchRegex(getMinecraftObjectRegex(), 50);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the name of the Minecraft server package.
|
* Retrieve the name of the Minecraft server package.
|
||||||
* @return Full canonical name of the Minecraft server package.
|
* @return Full canonical name of the Minecraft server package.
|
||||||
@ -120,6 +143,10 @@ public class MinecraftReflection {
|
|||||||
DYNAMIC_PACKAGE_MATCHER =
|
DYNAMIC_PACKAGE_MATCHER =
|
||||||
(MINECRAFT_PREFIX_PACKAGE.length() > 0 ?
|
(MINECRAFT_PREFIX_PACKAGE.length() > 0 ?
|
||||||
Pattern.quote(MINECRAFT_PREFIX_PACKAGE + ".") : "") + "\\w+";
|
Pattern.quote(MINECRAFT_PREFIX_PACKAGE + ".") : "") + "\\w+";
|
||||||
|
|
||||||
|
// We'll still accept the default location, however
|
||||||
|
DYNAMIC_PACKAGE_MATCHER = "(" + DYNAMIC_PACKAGE_MATCHER + ")|(" + MINECRAFT_OBJECT + ")";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Use the standard matcher
|
// Use the standard matcher
|
||||||
DYNAMIC_PACKAGE_MATCHER = MINECRAFT_OBJECT;
|
DYNAMIC_PACKAGE_MATCHER = MINECRAFT_OBJECT;
|
||||||
@ -146,6 +173,9 @@ public class MinecraftReflection {
|
|||||||
public static void setMinecraftPackage(String minecraftPackage, String craftBukkitPackage) {
|
public static void setMinecraftPackage(String minecraftPackage, String craftBukkitPackage) {
|
||||||
MINECRAFT_FULL_PACKAGE = minecraftPackage;
|
MINECRAFT_FULL_PACKAGE = minecraftPackage;
|
||||||
CRAFTBUKKIT_PACKAGE = craftBukkitPackage;
|
CRAFTBUKKIT_PACKAGE = craftBukkitPackage;
|
||||||
|
|
||||||
|
// Standard matcher
|
||||||
|
DYNAMIC_PACKAGE_MATCHER = MINECRAFT_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -325,7 +355,22 @@ public class MinecraftReflection {
|
|||||||
* @return The entity class.
|
* @return The entity class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getEntityPlayerClass() {
|
public static Class<?> getEntityPlayerClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("EntityPlayer");
|
return getMinecraftClass("EntityPlayer");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
try {
|
||||||
|
// A fairly stable method
|
||||||
|
Method detect = FuzzyReflection.fromClass(getCraftBukkitClass("CraftServer")).
|
||||||
|
getMethodByName("detectListNameConflict");
|
||||||
|
|
||||||
|
// EntityPlayer is then the first parameter
|
||||||
|
return detect.getParameterTypes()[0];
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
// Last resort
|
||||||
|
return fallbackMethodReturn("EntityPlayer", "entity.CraftPlayer", "getHandle");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -333,7 +378,38 @@ public class MinecraftReflection {
|
|||||||
* @return The entity class.
|
* @return The entity class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getEntityClass() {
|
public static Class<?> getEntityClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("Entity");
|
return getMinecraftClass("Entity");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
return fallbackMethodReturn("Entity", "entity.CraftEntity", "getHandle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the WorldServer (NMS) class.
|
||||||
|
* @return The WorldServer class.
|
||||||
|
*/
|
||||||
|
public static Class<?> getWorldServerClass() {
|
||||||
|
try {
|
||||||
|
return getMinecraftClass("WorldServer");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
return fallbackMethodReturn("WorldServer", "CraftWorld", "getHandle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback on the return value of a named method in order to get a NMS class.
|
||||||
|
* @param nmsClass - the expected name of the Minecraft class.
|
||||||
|
* @param craftClass - a CraftBukkit class to look at.
|
||||||
|
* @param methodName - the method we will use.
|
||||||
|
* @return The return value of this method, which will be saved to the package cache.
|
||||||
|
*/
|
||||||
|
private static Class<?> fallbackMethodReturn(String nmsClass, String craftClass, String methodName) {
|
||||||
|
Class<?> result = FuzzyReflection.fromClass(getCraftBukkitClass(craftClass)).
|
||||||
|
getMethodByName(methodName).getReturnType();
|
||||||
|
|
||||||
|
// Save the result
|
||||||
|
return setMinecraftClass(nmsClass, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -341,7 +417,75 @@ public class MinecraftReflection {
|
|||||||
* @return The packet class.
|
* @return The packet class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getPacketClass() {
|
public static Class<?> getPacketClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("Packet");
|
return getMinecraftClass("Packet");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// What kind of class we're looking for (sanity check)
|
||||||
|
FuzzyClassContract paketContract =
|
||||||
|
FuzzyClassContract.newBuilder().
|
||||||
|
field(FuzzyFieldContract.newBuilder().
|
||||||
|
typeDerivedOf(Map.class).
|
||||||
|
requireModifier(Modifier.STATIC)).
|
||||||
|
field(FuzzyFieldContract.newBuilder().
|
||||||
|
typeDerivedOf(Set.class).
|
||||||
|
requireModifier(Modifier.STATIC)).
|
||||||
|
method(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterSuperOf(DataInputStream.class).
|
||||||
|
returnTypeVoid()).
|
||||||
|
build();
|
||||||
|
|
||||||
|
// Select a method with one Minecraft object parameter
|
||||||
|
Method selected = FuzzyReflection.fromClass(getNetHandlerClass()).
|
||||||
|
getMethod(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterMatches(paketContract, 0).
|
||||||
|
parameterCount(1).
|
||||||
|
build()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save and return
|
||||||
|
Class<?> clazz = getTopmostClass(selected.getParameterTypes()[0]);
|
||||||
|
return setMinecraftClass("Packet", clazz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the least derived class, except Object.
|
||||||
|
* @return Least derived super class.
|
||||||
|
*/
|
||||||
|
private static Class<?> getTopmostClass(Class<?> clazz) {
|
||||||
|
while (true) {
|
||||||
|
Class<?> superClass = clazz.getSuperclass();
|
||||||
|
|
||||||
|
if (superClass == Object.class || superClass == null)
|
||||||
|
return clazz;
|
||||||
|
else
|
||||||
|
clazz = superClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the MinecraftServer class.
|
||||||
|
* @return MinecraftServer class.
|
||||||
|
*/
|
||||||
|
public static Class<?> getMinecraftServerClass() {
|
||||||
|
try {
|
||||||
|
return getMinecraftClass("MinecraftServer");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Get the first constructor that matches CraftServer(MINECRAFT_OBJECT, ANY)
|
||||||
|
Constructor<?> selected = FuzzyReflection.fromClass(getCraftBukkitClass("CraftServer")).
|
||||||
|
getConstructor(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterMatches(getMinecraftObjectMatcher(), 0).
|
||||||
|
parameterCount(2).
|
||||||
|
build()
|
||||||
|
);
|
||||||
|
Class<?>[] params = selected.getParameterTypes();
|
||||||
|
|
||||||
|
// Jackpot - two classes at the same time!
|
||||||
|
setMinecraftClass("MinecraftServer", params[0]);
|
||||||
|
setMinecraftClass("ServerConfigurationManager", params[1]);
|
||||||
|
return params[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -349,7 +493,13 @@ public class MinecraftReflection {
|
|||||||
* @return The player list class.
|
* @return The player list class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getPlayerListClass() {
|
public static Class<?> getPlayerListClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("ServerConfigurationManager", "PlayerList");
|
return getMinecraftClass("ServerConfigurationManager", "PlayerList");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Try again
|
||||||
|
getMinecraftServerClass();
|
||||||
|
return getMinecraftClass("ServerConfigurationManager");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -357,7 +507,22 @@ public class MinecraftReflection {
|
|||||||
* @return The NetLoginHandler class.
|
* @return The NetLoginHandler class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getNetLoginHandlerClass() {
|
public static Class<?> getNetLoginHandlerClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("NetLoginHandler", "PendingConnection");
|
return getMinecraftClass("NetLoginHandler", "PendingConnection");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Method selected = FuzzyReflection.fromClass(getPlayerListClass()).
|
||||||
|
getMethod(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterMatches(
|
||||||
|
FuzzyMatchers.matchExact(getEntityPlayerClass()).inverted(), 0
|
||||||
|
).
|
||||||
|
parameterExactType(String.class, 1).
|
||||||
|
parameterExactType(String.class, 2).
|
||||||
|
build()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save the pending connection reference
|
||||||
|
return setMinecraftClass("NetLoginHandler", selected.getParameterTypes()[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -365,15 +530,35 @@ public class MinecraftReflection {
|
|||||||
* @return The NetServerHandler class.
|
* @return The NetServerHandler class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getNetServerHandlerClass() {
|
public static Class<?> getNetServerHandlerClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("NetServerHandler", "PlayerConnection");
|
return getMinecraftClass("NetServerHandler", "PlayerConnection");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Use the player connection field
|
||||||
|
return setMinecraftClass("NetLoginHandler",
|
||||||
|
FuzzyReflection.fromClass(getEntityPlayerClass()).
|
||||||
|
getFieldByType("playerConnection", getNetHandlerClass()).getType()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the NetworkManager class.
|
* Retrieve the NetworkManager class or its interface.
|
||||||
* @return The NetworkManager class.
|
* @return The NetworkManager class or its interface.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getNetworkManagerClass() {
|
public static Class<?> getNetworkManagerClass() {
|
||||||
return getMinecraftClass("NetworkManager");
|
try {
|
||||||
|
return getMinecraftClass("INetworkManager", "NetworkManager");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Constructor<?> selected = FuzzyReflection.fromClass(getNetServerHandlerClass()).
|
||||||
|
getConstructor(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterSuperOf(getMinecraftServerClass(), 0).
|
||||||
|
parameterSuperOf(getEntityPlayerClass(), 2).
|
||||||
|
build()
|
||||||
|
);
|
||||||
|
|
||||||
|
// And we're done
|
||||||
|
return setMinecraftClass("INetworkManager", selected.getParameterTypes()[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -381,7 +566,11 @@ public class MinecraftReflection {
|
|||||||
* @return The NetHandler class.
|
* @return The NetHandler class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getNetHandlerClass() {
|
public static Class<?> getNetHandlerClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("NetHandler", "Connection");
|
return getMinecraftClass("NetHandler", "Connection");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
return setMinecraftClass("NetHandler", getNetLoginHandlerClass().getSuperclass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -389,7 +578,13 @@ public class MinecraftReflection {
|
|||||||
* @return The ItemStack class.
|
* @return The ItemStack class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getItemStackClass() {
|
public static Class<?> getItemStackClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("ItemStack");
|
return getMinecraftClass("ItemStack");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Use the handle reference
|
||||||
|
return setMinecraftClass("ItemStack",
|
||||||
|
FuzzyReflection.fromClass(getCraftItemStackClass(), true).getFieldByName("handle").getType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -397,15 +592,21 @@ public class MinecraftReflection {
|
|||||||
* @return The WorldType class.
|
* @return The WorldType class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getWorldTypeClass() {
|
public static Class<?> getWorldTypeClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("WorldType");
|
return getMinecraftClass("WorldType");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Get the first constructor that matches CraftServer(MINECRAFT_OBJECT, ANY)
|
||||||
|
Method selected = FuzzyReflection.fromClass(getMinecraftServerClass(), true).
|
||||||
|
getMethod(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterExactType(String.class, 0).
|
||||||
|
parameterExactType(String.class, 1).
|
||||||
|
parameterMatches(getMinecraftObjectMatcher()).
|
||||||
|
parameterExactType(String.class, 4).
|
||||||
|
parameterCount(5).
|
||||||
|
build()
|
||||||
|
);
|
||||||
|
return setMinecraftClass("WorldType", selected.getParameterTypes()[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the MinecraftServer class.
|
|
||||||
* @return MinecraftServer class.
|
|
||||||
*/
|
|
||||||
public static Class<?> getMinecraftServerClass() {
|
|
||||||
return getMinecraftClass("MinecraftServer");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -413,7 +614,33 @@ public class MinecraftReflection {
|
|||||||
* @return The DataWatcher class.
|
* @return The DataWatcher class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getDataWatcherClass() {
|
public static Class<?> getDataWatcherClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("DataWatcher");
|
return getMinecraftClass("DataWatcher");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Describe the DataWatcher
|
||||||
|
FuzzyClassContract dataWatcherContract = FuzzyClassContract.newBuilder().
|
||||||
|
field(FuzzyFieldContract.newBuilder().
|
||||||
|
requireModifier(Modifier.STATIC).
|
||||||
|
typeDerivedOf(Map.class)).
|
||||||
|
field(FuzzyFieldContract.newBuilder().
|
||||||
|
banModifier(Modifier.STATIC).
|
||||||
|
typeDerivedOf(Map.class)).
|
||||||
|
method(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterExactType(int.class).
|
||||||
|
parameterExactType(Object.class).
|
||||||
|
returnTypeVoid()).
|
||||||
|
build();
|
||||||
|
FuzzyFieldContract fieldContract = FuzzyFieldContract.newBuilder().
|
||||||
|
typeMatches(dataWatcherContract).
|
||||||
|
build();
|
||||||
|
|
||||||
|
// Get such a field and save the result
|
||||||
|
return setMinecraftClass("DataWatcher",
|
||||||
|
FuzzyReflection.fromClass(getEntityClass(), true).
|
||||||
|
getField(fieldContract).
|
||||||
|
getType()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -421,7 +648,25 @@ public class MinecraftReflection {
|
|||||||
* @return The ChunkPosition class.
|
* @return The ChunkPosition class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getChunkPositionClass() {
|
public static Class<?> getChunkPositionClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("ChunkPosition");
|
return getMinecraftClass("ChunkPosition");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Class<?> normalChunkGenerator = getCraftBukkitClass("generator.NormalChunkGenerator");
|
||||||
|
|
||||||
|
// ChunkPosition a(net.minecraft.server.World world, String string, int i, int i1, int i2) {
|
||||||
|
FuzzyMethodContract selected = FuzzyMethodContract.newBuilder().
|
||||||
|
banModifier(Modifier.STATIC).
|
||||||
|
parameterMatches(getMinecraftObjectMatcher(), 0).
|
||||||
|
parameterExactType(String.class, 1).
|
||||||
|
parameterExactType(int.class, 2).
|
||||||
|
parameterExactType(int.class, 3).
|
||||||
|
parameterExactType(int.class, 4).
|
||||||
|
build();
|
||||||
|
|
||||||
|
return setMinecraftClass("ChunkPosition",
|
||||||
|
FuzzyReflection.fromClass(normalChunkGenerator).
|
||||||
|
getMethod(selected).getReturnType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -429,7 +674,11 @@ public class MinecraftReflection {
|
|||||||
* @return The ChunkPosition class.
|
* @return The ChunkPosition class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getChunkCoordinatesClass() {
|
public static Class<?> getChunkCoordinatesClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("ChunkCoordinates");
|
return getMinecraftClass("ChunkCoordinates");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
return setMinecraftClass("ChunkCoordinates", WrappedDataWatcher.getTypeClass(6));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -437,7 +686,19 @@ public class MinecraftReflection {
|
|||||||
* @return The WatchableObject class.
|
* @return The WatchableObject class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getWatchableObjectClass() {
|
public static Class<?> getWatchableObjectClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("WatchableObject");
|
return getMinecraftClass("WatchableObject");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Method selected = FuzzyReflection.fromClass(getDataWatcherClass(), true).
|
||||||
|
getMethod(FuzzyMethodContract.newBuilder().
|
||||||
|
requireModifier(Modifier.STATIC).
|
||||||
|
parameterSuperOf(DataOutputStream.class, 0).
|
||||||
|
parameterMatches(getMinecraftObjectMatcher(), 1).
|
||||||
|
build());
|
||||||
|
|
||||||
|
// Use the second parameter
|
||||||
|
return setMinecraftClass("WatchableObject", selected.getParameterTypes()[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -445,7 +706,26 @@ public class MinecraftReflection {
|
|||||||
* @return The ServerConnection class.
|
* @return The ServerConnection class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getServerConnectionClass() {
|
public static Class<?> getServerConnectionClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("ServerConnection");
|
return getMinecraftClass("ServerConnection");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
FuzzyClassContract serverConnectionContract = FuzzyClassContract.newBuilder().
|
||||||
|
constructor(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterExactType(getMinecraftServerClass()).
|
||||||
|
parameterCount(1)).
|
||||||
|
method(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterExactType(getNetServerHandlerClass())).
|
||||||
|
build();
|
||||||
|
|
||||||
|
Method selected = FuzzyReflection.fromClass(getMinecraftServerClass()).
|
||||||
|
getMethod(FuzzyMethodContract.newBuilder().
|
||||||
|
requireModifier(Modifier.ABSTRACT).
|
||||||
|
returnTypeMatches(serverConnectionContract).
|
||||||
|
build());
|
||||||
|
|
||||||
|
// Use the return type
|
||||||
|
return setMinecraftClass("ServerConnection", selected.getReturnType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -453,7 +733,95 @@ public class MinecraftReflection {
|
|||||||
* @return The NBT base class.
|
* @return The NBT base class.
|
||||||
*/
|
*/
|
||||||
public static Class<?> getNBTBaseClass() {
|
public static Class<?> getNBTBaseClass() {
|
||||||
|
try {
|
||||||
return getMinecraftClass("NBTBase");
|
return getMinecraftClass("NBTBase");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
FuzzyClassContract tagCompoundContract = FuzzyClassContract.newBuilder().
|
||||||
|
constructor(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterExactType(String.class).
|
||||||
|
parameterCount(1)).
|
||||||
|
field(FuzzyFieldContract.newBuilder().
|
||||||
|
typeDerivedOf(Map.class)).
|
||||||
|
build();
|
||||||
|
|
||||||
|
Method selected = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).
|
||||||
|
getMethod(FuzzyMethodContract.newBuilder().
|
||||||
|
requireModifier(Modifier.STATIC).
|
||||||
|
parameterSuperOf(DataInputStream.class).
|
||||||
|
parameterCount(1).
|
||||||
|
returnTypeMatches(tagCompoundContract).
|
||||||
|
build()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Use the return type here too
|
||||||
|
return setMinecraftClass("NBTBase", selected.getReturnType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the EntityTracker (NMS) class.
|
||||||
|
* @return EntityTracker class.
|
||||||
|
*/
|
||||||
|
public static Class<?> getEntityTrackerClass() {
|
||||||
|
try {
|
||||||
|
return getMinecraftClass("EntityTracker");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
FuzzyClassContract entityTrackerContract = FuzzyClassContract.newBuilder().
|
||||||
|
field(FuzzyFieldContract.newBuilder().
|
||||||
|
typeDerivedOf(Set.class)).
|
||||||
|
method(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterSuperOf(MinecraftReflection.getEntityClass()).
|
||||||
|
parameterCount(1).
|
||||||
|
returnTypeVoid()).
|
||||||
|
method(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterSuperOf(MinecraftReflection.getEntityClass(), 0).
|
||||||
|
parameterSuperOf(int.class, 1).
|
||||||
|
parameterSuperOf(int.class, 2).
|
||||||
|
parameterCount(3).
|
||||||
|
returnTypeVoid()).
|
||||||
|
build();
|
||||||
|
|
||||||
|
Field selected = FuzzyReflection.fromClass(MinecraftReflection.getWorldServerClass(), true).
|
||||||
|
getField(FuzzyFieldContract.newBuilder().
|
||||||
|
typeMatches(entityTrackerContract).
|
||||||
|
build()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Go by the defined type of this field
|
||||||
|
return setMinecraftClass("EntityTracker", selected.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the NetworkListenThread class (NMS).
|
||||||
|
* <p>
|
||||||
|
* Note that this class was removed after Minecraft 1.3.1.
|
||||||
|
* @return NetworkListenThread class.
|
||||||
|
*/
|
||||||
|
public static Class<?> getNetworkListenThreadClass() {
|
||||||
|
try {
|
||||||
|
return getMinecraftClass("NetworkListenThread");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
FuzzyClassContract networkListenContract = FuzzyClassContract.newBuilder().
|
||||||
|
field(FuzzyFieldContract.newBuilder().
|
||||||
|
typeDerivedOf(ServerSocket.class)).
|
||||||
|
field(FuzzyFieldContract.newBuilder().
|
||||||
|
typeDerivedOf(Thread.class)).
|
||||||
|
field(FuzzyFieldContract.newBuilder().
|
||||||
|
typeDerivedOf(List.class)).
|
||||||
|
method(FuzzyMethodContract.newBuilder().
|
||||||
|
parameterExactType(getNetServerHandlerClass())).
|
||||||
|
build();
|
||||||
|
|
||||||
|
Field selected = FuzzyReflection.fromClass(MinecraftReflection.getMinecraftServerClass(), true).
|
||||||
|
getField(FuzzyFieldContract.newBuilder().
|
||||||
|
typeMatches(networkListenContract).
|
||||||
|
build()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Go by the defined type of this field
|
||||||
|
return setMinecraftClass("NetworkListenThread", selected.getType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -619,6 +987,19 @@ public class MinecraftReflection {
|
|||||||
return minecraftPackage.getPackageClass(className);
|
return minecraftPackage.getPackageClass(className);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the class object for the specific Minecraft class.
|
||||||
|
* @param className - name of the Minecraft class.
|
||||||
|
* @param clazz - the new class object.
|
||||||
|
* @return The provided clazz object.
|
||||||
|
*/
|
||||||
|
private static Class<?> setMinecraftClass(String className, Class<?> clazz) {
|
||||||
|
if (minecraftPackage == null)
|
||||||
|
minecraftPackage = new CachedPackage(getMinecraftPackage());
|
||||||
|
minecraftPackage.setPackageClass(className, clazz);
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the first class that matches a specified Minecraft name.
|
* Retrieve the first class that matches a specified Minecraft name.
|
||||||
* @param className - the specific Minecraft class.
|
* @param className - the specific Minecraft class.
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren