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:
Ursprung
0b3fe5470a
Commit
5e5243e3fb
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren