Archiviert
13
0

Update ProtocolLib for 1.6.1.

A lot of methods changed from accepting DataInputStream to DataInput, 
which messed with the part that dynamically finds the "readPacket" 
method. Changed to accepting any method whose signature contains a 
parameter derived from DataInput.
Dieser Commit ist enthalten in:
Kristian S. Stangeland 2013-07-02 17:41:43 +02:00
Ursprung 0b3fe5470a
Commit 5e5243e3fb
3 geänderte Dateien mit 189 neuen und 146 gelöschten Zeilen

Datei anzeigen

@ -17,6 +17,7 @@
package com.comphenix.protocol.injector.packet; package com.comphenix.protocol.injector.packet;
import java.io.DataInput;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -33,6 +34,8 @@ import net.sf.cglib.proxy.NoOp;
import com.comphenix.protocol.Packets; import com.comphenix.protocol.Packets;
import com.comphenix.protocol.error.ErrorReporter; import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.error.Report;
import com.comphenix.protocol.error.ReportType;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.ListenerInvoker; import com.comphenix.protocol.injector.ListenerInvoker;
@ -50,6 +53,8 @@ import com.comphenix.protocol.utility.MinecraftReflection;
* @author Kristian * @author Kristian
*/ */
class ProxyPacketInjector implements PacketInjector { class ProxyPacketInjector implements PacketInjector {
public static final ReportType REPORT_CANNOT_FIND_READ_PACKET_METHOD = new ReportType("Cannot find read packet method for ID %s.");
/** /**
* Represents a way to update the packet ID to class lookup table. * Represents a way to update the packet ID to class lookup table.
* @author Kristian * @author Kristian
@ -134,7 +139,7 @@ class ProxyPacketInjector implements PacketInjector {
*/ */
private static FuzzyMethodContract readPacket = FuzzyMethodContract.newBuilder(). private static FuzzyMethodContract readPacket = FuzzyMethodContract.newBuilder().
returnTypeVoid(). returnTypeVoid().
parameterExactType(DataInputStream.class). parameterDerivedOf(DataInput.class).
parameterCount(1). parameterCount(1).
build(); build();
@ -154,6 +159,9 @@ class ProxyPacketInjector implements PacketInjector {
// Share callback filter // Share callback filter
private CallbackFilter filter; private CallbackFilter filter;
// Determine if the read packet method was found
private boolean readPacketIntercepted = false;
public ProxyPacketInjector(ClassLoader classLoader, ListenerInvoker manager, public ProxyPacketInjector(ClassLoader classLoader, ListenerInvoker manager,
PlayerInjectionHandler playerInjection, ErrorReporter reporter) throws FieldAccessException { PlayerInjectionHandler playerInjection, ErrorReporter reporter) throws FieldAccessException {
@ -224,16 +232,20 @@ class ProxyPacketInjector implements PacketInjector {
} }
if (filter == null) { if (filter == null) {
readPacketIntercepted = false;
filter = new CallbackFilter() { filter = new CallbackFilter() {
@Override @Override
public int accept(Method method) { public int accept(Method method) {
// Skip methods defined in Object // Skip methods defined in Object
if (method.getDeclaringClass().equals(Object.class)) if (method.getDeclaringClass().equals(Object.class)) {
return 0; return 0;
else if (readPacket.isMatch(MethodInfo.fromMethod(method), null)) } else if (readPacket.isMatch(MethodInfo.fromMethod(method), null)) {
readPacketIntercepted = true;
return 1; return 1;
else } else {
return 2; return 2;
}
} }
}; };
} }
@ -252,6 +264,12 @@ class ProxyPacketInjector implements PacketInjector {
// Add a static reference // Add a static reference
Enhancer.registerStaticCallbacks(proxy, new Callback[] { NoOp.INSTANCE, modifierReadPacket, modifierRest }); Enhancer.registerStaticCallbacks(proxy, new Callback[] { NoOp.INSTANCE, modifierReadPacket, modifierRest });
// Check that we found the read method
if (!readPacketIntercepted) {
reporter.reportWarning(this,
Report.newBuilder(REPORT_CANNOT_FIND_READ_PACKET_METHOD).messageParam(packetID));
}
// Override values // Override values
previous.put(packetID, old); previous.put(packetID, old);
registry.put(proxy, packetID); registry.put(proxy, packetID);

Datei anzeigen

@ -1,140 +1,140 @@
/* /*
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland * Copyright (C) 2012 Kristian S. Stangeland
* *
* This program is free software; you can redistribute it and/or modify it under the terms of the * This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of * GNU General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version. * the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along with this program; * You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA * 02111-1307 USA
*/ */
package com.comphenix.protocol.injector.packet; package com.comphenix.protocol.injector.packet;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map; import java.util.Map;
import com.comphenix.protocol.error.ErrorReporter; import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.error.Report; import com.comphenix.protocol.error.Report;
import com.comphenix.protocol.error.ReportType; import com.comphenix.protocol.error.ReportType;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.events.PacketEvent;
import com.google.common.collect.MapMaker; import com.google.common.collect.MapMaker;
import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.MethodProxy;
class ReadPacketModifier implements MethodInterceptor { class ReadPacketModifier implements MethodInterceptor {
public static final ReportType REPORT_CANNOT_HANDLE_CLIENT_PACKET = new ReportType("Cannot handle client packet."); public static final ReportType REPORT_CANNOT_HANDLE_CLIENT_PACKET = new ReportType("Cannot handle client packet.");
// A cancel marker // A cancel marker
private static final Object CANCEL_MARKER = new Object(); private static final Object CANCEL_MARKER = new Object();
// Common for all packets of the same type // Common for all packets of the same type
private ProxyPacketInjector packetInjector; private ProxyPacketInjector packetInjector;
private int packetID; private int packetID;
// Report errors // Report errors
private ErrorReporter reporter; private ErrorReporter reporter;
// If this is a read packet data method // If this is a read packet data method
private boolean isReadPacketDataMethod; private boolean isReadPacketDataMethod;
// Whether or not a packet has been cancelled // Whether or not a packet has been cancelled
private static Map<Object, Object> override = new MapMaker().weakKeys().makeMap(); private static Map<Object, Object> override = new MapMaker().weakKeys().makeMap();
public ReadPacketModifier(int packetID, ProxyPacketInjector packetInjector, ErrorReporter reporter, boolean isReadPacketDataMethod) { public ReadPacketModifier(int packetID, ProxyPacketInjector packetInjector, ErrorReporter reporter, boolean isReadPacketDataMethod) {
this.packetID = packetID; this.packetID = packetID;
this.packetInjector = packetInjector; this.packetInjector = packetInjector;
this.reporter = reporter; this.reporter = reporter;
this.isReadPacketDataMethod = isReadPacketDataMethod; this.isReadPacketDataMethod = isReadPacketDataMethod;
} }
/** /**
* Remove any packet overrides. * Remove any packet overrides.
* @param packet - the packet to rever * @param packet - the packet to rever
*/ */
public static void removeOverride(Object packet) { public static void removeOverride(Object packet) {
override.remove(packet); override.remove(packet);
} }
/** /**
* Retrieve the packet that overrides the methods of the given packet. * Retrieve the packet that overrides the methods of the given packet.
* @param packet - the given packet. * @param packet - the given packet.
* @return Overriden object. * @return Overriden object.
*/ */
public static Object getOverride(Object packet) { public static Object getOverride(Object packet) {
return override.get(packet); return override.get(packet);
} }
/** /**
* Determine if the given packet has been cancelled before. * Determine if the given packet has been cancelled before.
* @param packet - the packet to check. * @param packet - the packet to check.
* @return TRUE if it has been cancelled, FALSE otherwise. * @return TRUE if it has been cancelled, FALSE otherwise.
*/ */
public static boolean hasCancelled(Object packet) { public static boolean hasCancelled(Object packet) {
return getOverride(packet) == CANCEL_MARKER; return getOverride(packet) == CANCEL_MARKER;
} }
@Override @Override
public Object intercept(Object thisObj, Method method, Object[] args, MethodProxy proxy) throws Throwable { public Object intercept(Object thisObj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// Atomic retrieval // Atomic retrieval
Object overridenObject = override.get(thisObj); Object overridenObject = override.get(thisObj);
Object returnValue = null; Object returnValue = null;
if (overridenObject != null) { if (overridenObject != null) {
// This packet has been cancelled // This packet has been cancelled
if (overridenObject == CANCEL_MARKER) { if (overridenObject == CANCEL_MARKER) {
// So, cancel all void methods // So, cancel all void methods
if (method.getReturnType().equals(Void.TYPE)) if (method.getReturnType().equals(Void.TYPE))
return null; return null;
else // Revert to normal for everything else else // Revert to normal for everything else
overridenObject = thisObj; overridenObject = thisObj;
} }
returnValue = proxy.invokeSuper(overridenObject, args); returnValue = proxy.invokeSuper(overridenObject, args);
} else { } else {
returnValue = proxy.invokeSuper(thisObj, args); returnValue = proxy.invokeSuper(thisObj, args);
} }
// Is this a readPacketData method? // Is this a readPacketData method?
if (isReadPacketDataMethod) { if (isReadPacketDataMethod) {
try { try {
// We need this in order to get the correct player // We need this in order to get the correct player
DataInputStream input = (DataInputStream) args[0]; DataInputStream input = (DataInputStream) args[0];
// Let the people know // Let the people know
PacketContainer container = new PacketContainer(packetID, thisObj); PacketContainer container = new PacketContainer(packetID, thisObj);
PacketEvent event = packetInjector.packetRecieved(container, input); PacketEvent event = packetInjector.packetRecieved(container, input);
// Handle override // Handle override
if (event != null) { if (event != null) {
Object result = event.getPacket().getHandle(); Object result = event.getPacket().getHandle();
if (event.isCancelled()) { if (event.isCancelled()) {
override.put(thisObj, CANCEL_MARKER); override.put(thisObj, CANCEL_MARKER);
} else if (!objectEquals(thisObj, result)) { } else if (!objectEquals(thisObj, result)) {
override.put(thisObj, result); override.put(thisObj, result);
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
// Minecraft cannot handle this error // Minecraft cannot handle this error
reporter.reportDetailed(this, reporter.reportDetailed(this,
Report.newBuilder(REPORT_CANNOT_HANDLE_CLIENT_PACKET).callerParam(args[0]).error(e) Report.newBuilder(REPORT_CANNOT_HANDLE_CLIENT_PACKET).callerParam(args[0]).error(e)
); );
} }
} }
return returnValue; return returnValue;
} }
private boolean objectEquals(Object a, Object b) { private boolean objectEquals(Object a, Object b) {
return System.identityHashCode(a) != System.identityHashCode(b); return System.identityHashCode(a) != System.identityHashCode(b);
} }
} }

Datei anzeigen

@ -161,14 +161,26 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
/** /**
* Add a new required parameter whose type must be a superclass 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 method parameter is of type Number, then any derived class here (Integer, Long, etc.) will match it.
* @param type - a type or derived type of the matching parameter. * @param type - a type or less 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(FuzzyMatchers.matchSuper(type))); member.paramMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchSuper(type)));
return this; return this;
} }
/**
* Add a new required parameter whose type must be a derived class of the given class.
* <p>
* If the method parameter has the type Integer, then the class Number here will match it.
* @param type - a type or more derived type of the matching parameter.
* @return This builder, for chaining.
*/
public Builder parameterDerivedOf(Class<?> type) {
member.paramMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchDerived(type)));
return this;
}
/** /**
* Add a new required parameter whose type must match the given class matcher. * Add a new required parameter whose type must match the given class matcher.
@ -204,6 +216,19 @@ public class FuzzyMethodContract extends AbstractFuzzyMember<MethodInfo> {
return this; return this;
} }
/**
* Add a new required parameter whose type must be a derived class of the given class.
* <p>
* If the method parameter has the type Integer, then the class Number here will match it.
* @param type - a type or more derived type of the matching parameter.
* @param index - the expected position in the parameter list.
* @return This builder, for chaining.
*/
public Builder parameterDerivedOf(Class<?> type, int index) {
member.paramMatchers.add(new ParameterClassMatcher(FuzzyMatchers.matchDerived(type), index));
return this;
}
/** /**
* Add a new required parameter whose type must match the given class matcher and index. * Add a new required parameter whose type must match the given class matcher and index.
* @param classMatcher - the class matcher. * @param classMatcher - the class matcher.