Minimize the number of unnecessary references.

This commit is contained in:
Kristian S. Stangeland 2013-06-19 02:07:12 +02:00
parent e7954a0f79
commit 8f2935e241
3 changed files with 414 additions and 391 deletions

View File

@ -286,42 +286,10 @@ public class PacketContainer implements Serializable {
* @return A modifier for ItemStack array fields. * @return A modifier for ItemStack array fields.
*/ */
public StructureModifier<ItemStack[]> getItemArrayModifier() { public StructureModifier<ItemStack[]> getItemArrayModifier() {
final EquivalentConverter<ItemStack> stackConverter = BukkitConverters.getItemStackConverter();
// Convert to and from the Bukkit wrapper // Convert to and from the Bukkit wrapper
return structureModifier.<ItemStack[]>withType( return structureModifier.<ItemStack[]>withType(
MinecraftReflection.getItemStackArrayClass(), MinecraftReflection.getItemStackArrayClass(),
BukkitConverters.getIgnoreNull(new EquivalentConverter<ItemStack[]>() { BukkitConverters.getIgnoreNull(new ItemStackArrayConverter()));
public Object getGeneric(Class<?>genericType, ItemStack[] specific) {
Class<?> nmsStack = MinecraftReflection.getItemStackClass();
Object[] result = (Object[]) Array.newInstance(nmsStack, specific.length);
// Unwrap every item
for (int i = 0; i < result.length; i++) {
result[i] = stackConverter.getGeneric(nmsStack, specific[i]);
}
return result;
}
@Override
public ItemStack[] getSpecific(Object generic) {
Object[] input = (Object[]) generic;
ItemStack[] result = new ItemStack[input.length];
// Add the wrapper
for (int i = 0; i < result.length; i++) {
result[i] = stackConverter.getSpecific(input[i]);
}
return result;
}
@Override
public Class<ItemStack[]> getSpecificType() {
return ItemStack[].class;
}
}));
} }
/** /**
@ -556,4 +524,40 @@ public class PacketContainer implements Serializable {
return method; return method;
} }
/**
* Represents an equivalent converter for ItemStack arrays.
* @author Kristian
*/
private static class ItemStackArrayConverter implements EquivalentConverter<ItemStack[]> {
final EquivalentConverter<ItemStack> stackConverter = BukkitConverters.getItemStackConverter();
public Object getGeneric(Class<?>genericType, ItemStack[] specific) {
Class<?> nmsStack = MinecraftReflection.getItemStackClass();
Object[] result = (Object[]) Array.newInstance(nmsStack, specific.length);
// Unwrap every item
for (int i = 0; i < result.length; i++) {
result[i] = stackConverter.getGeneric(nmsStack, specific[i]);
}
return result;
}
@Override
public ItemStack[] getSpecific(Object generic) {
Object[] input = (Object[]) generic;
ItemStack[] result = new ItemStack[input.length];
// Add the wrapper
for (int i = 0; i < result.length; i++) {
result[i] = stackConverter.getSpecific(input[i]);
}
return result;
}
@Override
public Class<ItemStack[]> getSpecificType() {
return ItemStack[].class;
}
}
} }

View File

@ -173,19 +173,7 @@ class NetworkServerInjector extends PlayerInjector {
// Share callback filter - that way, we avoid generating a new class for // Share callback filter - that way, we avoid generating a new class for
// every logged in player. // every logged in player.
if (callbackFilter == null) { if (callbackFilter == null) {
final Method sendPacket = MinecraftMethods.getSendPacketMethod(); callbackFilter = new SendMethodFilter();
callbackFilter = new CallbackFilter() {
@Override
public int accept(Method method) {
if (isCallableEqual(sendPacket, method)) {
foundSendPacket = true;
return 0;
} else {
return 1;
}
}
};
} }
ex.setClassLoader(classLoader); ex.setClassLoader(classLoader);
@ -229,20 +217,6 @@ class NetworkServerInjector extends PlayerInjector {
} }
} }
/**
* Determine if the two methods are equal in terms of call semantics.
* <p>
* Two methods are equal if they have the same name, parameter types and return type.
* @param first - first method.
* @param second - second method.
* @return TRUE if they are, FALSE otherwise.
*/
private boolean isCallableEqual(Method first, Method second) {
return first.getName().equals(second.getName()) &&
first.getReturnType().equals(second.getReturnType()) &&
Arrays.equals(first.getParameterTypes(), second.getParameterTypes());
}
private Object getProxyServerHandler() { private Object getProxyServerHandler() {
if (proxyServerField != null && !proxyServerField.equals(serverHandlerRef.getField())) { if (proxyServerField != null && !proxyServerField.equals(serverHandlerRef.getField())) {
try { try {
@ -349,4 +323,36 @@ class NetworkServerInjector extends PlayerInjector {
public PlayerInjectHooks getHookType() { public PlayerInjectHooks getHookType() {
return PlayerInjectHooks.NETWORK_SERVER_OBJECT; return PlayerInjectHooks.NETWORK_SERVER_OBJECT;
} }
/**
* Represents a CallbackFilter that only matches the SendPacket method.
* @author Kristian
*/
private static class SendMethodFilter implements CallbackFilter {
private Method sendPacket = MinecraftMethods.getSendPacketMethod();
@Override
public int accept(Method method) {
if (isCallableEqual(sendPacket, method)) {
NetworkServerInjector.foundSendPacket = true;
return 0;
} else {
return 1;
}
}
/**
* Determine if the two methods are equal in terms of call semantics.
* <p>
* Two methods are equal if they have the same name, parameter types and return type.
* @param first - first method.
* @param second - second method.
* @return TRUE if they are, FALSE otherwise.
*/
private boolean isCallableEqual(Method first, Method second) {
return first.getName().equals(second.getName()) &&
first.getReturnType().equals(second.getReturnType()) &&
Arrays.equals(first.getParameterTypes(), second.getParameterTypes());
}
}
} }

View File

@ -18,6 +18,7 @@
package com.comphenix.protocol.injector.player; package com.comphenix.protocol.injector.player;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -81,7 +82,7 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
private NetLoginInjector netLoginInjector; private NetLoginInjector netLoginInjector;
// The last successful player hook // The last successful player hook
private PlayerInjector lastSuccessfulHook; private WeakReference<PlayerInjector> lastSuccessfulHook;
// Dummy injection // Dummy injection
private Cache<Player, PlayerInjector> dummyInjectors = private Cache<Player, PlayerInjector> dummyInjectors =
@ -399,7 +400,7 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
// Update values // Update values
if (injector != null) if (injector != null)
lastSuccessfulHook = injector; lastSuccessfulHook = new WeakReference<PlayerInjector>(injector);
if (permanentHook != getPlayerHook(phase)) if (permanentHook != getPlayerHook(phase))
setPlayerHook(phase, tempHook); setPlayerHook(phase, tempHook);
@ -649,13 +650,23 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
@Override @Override
public void checkListener(Set<PacketListener> listeners) { public void checkListener(Set<PacketListener> listeners) {
// Make sure the current listeners are compatible // Make sure the current listeners are compatible
if (lastSuccessfulHook != null) { if (getLastSuccessfulHook() != null) {
for (PacketListener listener : listeners) { for (PacketListener listener : listeners) {
checkListener(listener); checkListener(listener);
} }
} }
} }
/**
* Retrieve the last successful hook.
* <p>
* May be NULL if the hook has been uninjected.
* @return Last successful hook.
*/
private PlayerInjector getLastSuccessfulHook() {
return lastSuccessfulHook != null ? lastSuccessfulHook.get() : null;
}
/** /**
* Determine if a listener is valid or not. * Determine if a listener is valid or not.
* <p> * <p>
@ -664,8 +675,10 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
*/ */
@Override @Override
public void checkListener(PacketListener listener) { public void checkListener(PacketListener listener) {
if (lastSuccessfulHook != null) { PlayerInjector last = getLastSuccessfulHook();
UnsupportedListener result = lastSuccessfulHook.checkListener(version, listener);
if (last != null) {
UnsupportedListener result = last.checkListener(version, listener);
// We won't prevent the listener, as it may still have valid packets // We won't prevent the listener, as it may still have valid packets
if (result != null) { if (result != null) {