From 3923e051784346df8a8cc51a4b2a9189e6529869 Mon Sep 17 00:00:00 2001 From: "Kristian S. Stangeland" Date: Thu, 15 Aug 2013 01:04:56 +0200 Subject: [PATCH] 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. --- .../protocol/injector/PacketFilterManager.java | 10 +++++++++- .../injector/packet/PacketInjector.java | 17 ++++++++++++----- .../injector/packet/ProxyPacketInjector.java | 17 +++++++++-------- .../injector/packet/ReadPacketModifier.java | 17 ++++++++++++++--- .../injector/spigot/DummyPacketInjector.java | 10 ++++++++-- .../injector/spigot/SpigotPacketInjector.java | 1 + 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java index c4d28b14..a43421e9 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java @@ -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 diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/PacketInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/PacketInjector.java index 12090aae..e08bd0ab 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/PacketInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/PacketInjector.java @@ -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. diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/ProxyPacketInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/ProxyPacketInjector.java index c65c10a2..48364818 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/ProxyPacketInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/ProxyPacketInjector.java @@ -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); } } diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/ReadPacketModifier.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/ReadPacketModifier.java index 1be0c28c..2f5e3e61 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/ReadPacketModifier.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/ReadPacketModifier.java @@ -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. + *

+ * 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; diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/spigot/DummyPacketInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/spigot/DummyPacketInjector.java index 3b3c4f90..9870d184 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/spigot/DummyPacketInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/spigot/DummyPacketInjector.java @@ -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 diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/spigot/SpigotPacketInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/spigot/SpigotPacketInjector.java index 8b7a1eeb..e13c87f0 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/spigot/SpigotPacketInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/spigot/SpigotPacketInjector.java @@ -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;