Asynchronous client packets are handled twice. FIXES 118

This causes wierd artifacts such as double placing of half-slabs and so
on, as Minecraft will process the packets again (except chat packets). 
We correct this by uncancelling the asynchronous packet, and then 
cancelling it again.
This commit is contained in:
Kristian S. Stangeland 2013-08-15 01:04:56 +02:00
parent ccc123b26f
commit 3923e05178
6 changed files with 53 additions and 19 deletions

View File

@ -669,9 +669,12 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
incrementPhases(GamePhase.PLAYING);
Object mcPacket = packet.getHandle();
boolean cancelled = packetInjector.isCancelled(mcPacket);
// Make sure the packet isn't cancelled
packetInjector.undoCancel(packet.getID(), mcPacket);
if (cancelled) {
packetInjector.setCancelled(mcPacket, false);
}
if (filters) {
byte[] data = NetworkMarker.getByteBuffer(marker);
@ -691,6 +694,11 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
}
playerInjection.recieveClientPacket(sender, mcPacket);
// Let it stay cancelled
if (cancelled) {
packetInjector.setCancelled(mcPacket, true);
}
}
@Override

View File

@ -14,12 +14,19 @@ import com.comphenix.protocol.events.PacketEvent;
*/
public interface PacketInjector {
/**
* Undo a packet cancel.
* @param id - the id of the packet.
* @param packet - packet to uncancel.
* Determine if a packet is cancelled or not.
* @param packet - the packet to check.
* @return TRUE if it is, FALSE otherwise.
*/
public abstract void undoCancel(Integer id, Object packet);
public abstract boolean isCancelled(Object packet);
/**
* Set whether or not a packet is cancelled.
* @param packet - the packet to set.
* @param cancelled - TRUE to cancel the packet, FALSE otherwise.
*/
public abstract void setCancelled(Object packet, boolean cancelled);
/**
* Start intercepting packets with the given packet ID.
* @param packetID - the ID of the packets to start intercepting.

View File

@ -176,15 +176,16 @@ class ProxyPacketInjector implements PacketInjector {
initialize();
}
/**
* Undo a packet cancel.
* @param id - the id of the packet.
* @param packet - packet to uncancel.
*/
@Override
public void undoCancel(Integer id, Object packet) {
// See if this packet has been cancelled before
if (ReadPacketModifier.hasCancelled(packet)) {
public boolean isCancelled(Object packet) {
return ReadPacketModifier.isCancelled(packet);
}
@Override
public void setCancelled(Object packet, boolean cancelled) {
if (cancelled) {
ReadPacketModifier.setOverride(packet, null);
} else {
ReadPacketModifier.removeOverride(packet);
}
}

View File

@ -74,16 +74,27 @@ class ReadPacketModifier implements MethodInterceptor {
public static Object getOverride(Object packet) {
return override.get(packet);
}
/**
* Set the packet instance to delegate to instead, or mark the packet as cancelled.
* <p>
* To undo a override, use {@link #removeOverride(Object)}.
* @param packet - the packet.
* @param override - the override method. NULL to cancel this packet.
*/
public static void setOverride(Object packet, Object overridePacket) {
override.put(packet, overridePacket != null ? overridePacket : CANCEL_MARKER);
}
/**
* Determine if the given packet has been cancelled before.
* @param packet - the packet to check.
* @return TRUE if it has been cancelled, FALSE otherwise.
*/
public static boolean hasCancelled(Object packet) {
public static boolean isCancelled(Object packet) {
return getOverride(packet) == CANCEL_MARKER;
}
@Override
public Object intercept(Object thisObj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// Atomic retrieval
@ -105,7 +116,7 @@ class ReadPacketModifier implements MethodInterceptor {
if (overridenObject != null) {
// This packet has been cancelled
if (overridenObject == CANCEL_MARKER) {
if (overridenObject == CANCEL_MARKER) {
// So, cancel all void methods
if (method.getReturnType().equals(Void.TYPE))
return null;

View File

@ -28,8 +28,14 @@ class DummyPacketInjector implements PacketInjector {
}
@Override
public void undoCancel(Integer id, Object packet) {
// Do nothing yet
public boolean isCancelled(Object packet) {
// No, it's never cancelled
return false;
}
@Override
public void setCancelled(Object packet, boolean cancelled) {
throw new UnsupportedOperationException();
}
@Override

View File

@ -38,6 +38,7 @@ import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.MethodInfo;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Maps;