Skip to content

Commit 56fb51e

Browse files
authored
Improve injector listener tracking and fix terminal packets breaking injection (#2951)
1 parent 76432f9 commit 56fb51e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2192
-2615
lines changed

src/main/java/com/comphenix/protocol/CommandProtocol.java

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.io.FileWriter;
2121
import java.io.IOException;
2222
import java.io.PrintWriter;
23+
import java.nio.file.Path;
2324
import java.text.SimpleDateFormat;
2425
import java.util.Date;
2526
import java.util.HashSet;
@@ -35,8 +36,8 @@
3536
import com.comphenix.protocol.error.DetailedErrorReporter;
3637
import com.comphenix.protocol.error.ErrorReporter;
3738
import com.comphenix.protocol.events.PacketListener;
38-
import com.comphenix.protocol.timing.TimedListenerManager;
39-
import com.comphenix.protocol.timing.TimingReportGenerator;
39+
import com.comphenix.protocol.timing.TimingReport;
40+
import com.comphenix.protocol.timing.TimingTrackerManager;
4041
import com.comphenix.protocol.updater.Updater;
4142
import com.comphenix.protocol.updater.Updater.UpdateType;
4243
import com.comphenix.protocol.utility.Closer;
@@ -143,15 +144,14 @@ public void run() {
143144
}
144145

145146
private void toggleTimings(CommandSender sender, String[] args) {
146-
TimedListenerManager manager = TimedListenerManager.getInstance();
147-
boolean state = !manager.isTiming(); // toggle
147+
boolean isNotTracking = !TimingTrackerManager.isTracking();
148148

149149
// Parse the boolean parameter
150150
if (args.length == 2) {
151151
Boolean parsed = parseBoolean(toQueue(args, 2), "start");
152152

153153
if (parsed != null) {
154-
state = parsed;
154+
isNotTracking = parsed;
155155
} else {
156156
sender.sendMessage(ChatColor.RED + "Specify a state: ON or OFF.");
157157
return;
@@ -161,31 +161,25 @@ private void toggleTimings(CommandSender sender, String[] args) {
161161
return;
162162
}
163163

164-
// Now change the state
165-
if (state) {
166-
if (manager.startTiming())
164+
if (isNotTracking) {
165+
if (TimingTrackerManager.startTracking())
167166
sender.sendMessage(ChatColor.GOLD + "Started timing packet listeners.");
168167
else
169168
sender.sendMessage(ChatColor.RED + "Packet timing already started.");
170169
} else {
171-
if (manager.stopTiming()) {
172-
saveTimings(manager);
170+
if (TimingTrackerManager.stopTracking()) {
171+
saveTimings(TimingTrackerManager.createReportAndReset());
173172
sender.sendMessage(ChatColor.GOLD + "Stopped and saved result in plugin folder.");
174173
} else {
175174
sender.sendMessage(ChatColor.RED + "Packet timing already stopped.");
176175
}
177176
}
178177
}
179-
180-
private void saveTimings(TimedListenerManager manager) {
178+
179+
private void saveTimings(TimingReport report) {
181180
try {
182-
File destination = new File(plugin.getDataFolder(), "Timings - " + System.currentTimeMillis() + ".txt");
183-
TimingReportGenerator generator = new TimingReportGenerator();
184-
185-
// Print to a text file
186-
generator.saveTo(destination, manager);
187-
manager.clear();
188-
181+
Path path = plugin.getDataFolder().toPath().resolve("timings_" + System.currentTimeMillis() + ".txt");
182+
report.saveTo(path);
189183
} catch (IOException e) {
190184
reporter.reportMinimal(plugin, "saveTimings()", e);
191185
}

src/main/java/com/comphenix/protocol/async/AsyncFilterManager.java

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717

1818
package com.comphenix.protocol.async;
1919

20-
import java.util.Collection;
2120
import java.util.List;
2221
import java.util.Set;
2322
import java.util.concurrent.ConcurrentHashMap;
2423
import java.util.concurrent.atomic.AtomicInteger;
2524

25+
import org.bukkit.entity.Player;
26+
import org.bukkit.plugin.Plugin;
27+
2628
import com.comphenix.protocol.AsynchronousManager;
2729
import com.comphenix.protocol.PacketStream;
2830
import com.comphenix.protocol.PacketType;
@@ -31,16 +33,13 @@
3133
import com.comphenix.protocol.events.ListeningWhitelist;
3234
import com.comphenix.protocol.events.PacketEvent;
3335
import com.comphenix.protocol.events.PacketListener;
34-
import com.comphenix.protocol.injector.PrioritizedListener;
35-
import com.comphenix.protocol.injector.SortedPacketListenerList;
36+
import com.comphenix.protocol.injector.collection.InboundPacketListenerSet;
37+
import com.comphenix.protocol.injector.collection.OutboundPacketListenerSet;
3638
import com.comphenix.protocol.scheduler.ProtocolScheduler;
3739
import com.google.common.base.Objects;
3840
import com.google.common.collect.ImmutableSet;
3941
import com.google.common.collect.Iterables;
4042

41-
import org.bukkit.entity.Player;
42-
import org.bukkit.plugin.Plugin;
43-
4443
/**
4544
* Represents a filter manager for asynchronous packets.
4645
* <p>
@@ -50,8 +49,8 @@
5049
*/
5150
public class AsyncFilterManager implements AsynchronousManager {
5251

53-
private SortedPacketListenerList serverTimeoutListeners;
54-
private SortedPacketListenerList clientTimeoutListeners;
52+
private OutboundPacketListenerSet outboundTimeoutListeners;
53+
private InboundPacketListenerSet inboundTimeoutListeners;
5554
private Set<PacketListener> timeoutListeners;
5655

5756
private PacketProcessingQueue serverProcessingQueue;
@@ -84,11 +83,11 @@ public class AsyncFilterManager implements AsynchronousManager {
8483
*/
8584
public AsyncFilterManager(ErrorReporter reporter, ProtocolScheduler scheduler) {
8685
// Initialize timeout listeners
87-
this.serverTimeoutListeners = new SortedPacketListenerList();
88-
this.clientTimeoutListeners = new SortedPacketListenerList();
86+
this.outboundTimeoutListeners = new OutboundPacketListenerSet(null, reporter);
87+
this.inboundTimeoutListeners = new InboundPacketListenerSet(null, reporter);
8988
this.timeoutListeners = ConcurrentHashMap.newKeySet();
9089

91-
this.playerSendingHandler = new PlayerSendingHandler(reporter, serverTimeoutListeners, clientTimeoutListeners);
90+
this.playerSendingHandler = new PlayerSendingHandler(outboundTimeoutListeners, inboundTimeoutListeners);
9291
this.serverProcessingQueue = new PacketProcessingQueue(playerSendingHandler);
9392
this.clientProcessingQueue = new PacketProcessingQueue(playerSendingHandler);
9493
this.playerSendingHandler.initializeScheduler();
@@ -130,9 +129,9 @@ public void registerTimeoutHandler(PacketListener listener) {
130129
ListeningWhitelist receiving = listener.getReceivingWhitelist();
131130

132131
if (!ListeningWhitelist.isEmpty(sending))
133-
serverTimeoutListeners.addListener(listener, sending);
132+
outboundTimeoutListeners.addListener(listener);
134133
if (!ListeningWhitelist.isEmpty(receiving))
135-
serverTimeoutListeners.addListener(listener, receiving);
134+
inboundTimeoutListeners.addListener(listener);
136135
}
137136

138137
@Override
@@ -145,9 +144,8 @@ public Set<PacketListener> getAsyncHandlers() {
145144
ImmutableSet.Builder<PacketListener> builder = ImmutableSet.builder();
146145

147146
// Add every asynchronous packet listener
148-
for (PrioritizedListener<AsyncListenerHandler> handler :
149-
Iterables.concat(serverProcessingQueue.values(), clientProcessingQueue.values())) {
150-
builder.add(handler.getListener().getAsyncListener());
147+
for (AsyncListenerHandler handler : Iterables.concat(serverProcessingQueue.values(), clientProcessingQueue.values())) {
148+
builder.add(handler.getAsyncListener());
151149
}
152150
return builder.build();
153151
}
@@ -203,13 +201,9 @@ public void unregisterTimeoutHandler(PacketListener listener) {
203201
if (listener == null)
204202
throw new IllegalArgumentException("listener cannot be NULL.");
205203

206-
ListeningWhitelist sending = listener.getSendingWhitelist();
207-
ListeningWhitelist receiving = listener.getReceivingWhitelist();
208-
209-
// Do it in the opposite order
210-
if (serverTimeoutListeners.removeListener(listener, sending).size() > 0 ||
211-
clientTimeoutListeners.removeListener(listener, receiving).size() > 0) {
212-
timeoutListeners.remove(listener);
204+
if (timeoutListeners.remove(listener)) {
205+
outboundTimeoutListeners.removeListener(listener);
206+
inboundTimeoutListeners.removeListener(listener);
213207
}
214208
}
215209

@@ -233,9 +227,9 @@ private AsyncListenerHandler findHandler(PacketProcessingQueue queue, ListeningW
233227
return null;
234228

235229
for (PacketType type : search.getTypes()) {
236-
for (PrioritizedListener<AsyncListenerHandler> element : queue.getListener(type)) {
237-
if (element.getListener().getAsyncListener() == target) {
238-
return element.getListener();
230+
for (AsyncListenerHandler element : queue.get(type)) {
231+
if (element.getAsyncListener() == target) {
232+
return element;
239233
}
240234
}
241235
}
@@ -292,10 +286,10 @@ public void unregisterAsyncHandlers(Plugin plugin) {
292286
private void unregisterAsyncHandlers(PacketProcessingQueue processingQueue, Plugin plugin) {
293287

294288
// Iterate through every packet listener
295-
for (PrioritizedListener<AsyncListenerHandler> listener : processingQueue.values()) {
289+
for (AsyncListenerHandler listener : processingQueue.values()) {
296290
// Remove the listener
297-
if (Objects.equal(listener.getListener().getPlugin(), plugin)) {
298-
unregisterAsyncHandler(listener.getListener());
291+
if (Objects.equal(listener.getPlugin(), plugin)) {
292+
unregisterAsyncHandler(listener);
299293
}
300294
}
301295
}
@@ -346,8 +340,7 @@ public ProtocolScheduler getScheduler() {
346340

347341
@Override
348342
public boolean hasAsynchronousListeners(PacketEvent packet) {
349-
Collection<?> list = getProcessingQueue(packet).getListener(packet.getPacketType());
350-
return list != null && list.size() > 0;
343+
return getProcessingQueue(packet).contains(packet.getPacketType());
351344
}
352345

353346
/**
@@ -388,8 +381,8 @@ public void cleanupAll() {
388381
playerSendingHandler.cleanupAll();
389382
timeoutListeners.clear();
390383

391-
serverTimeoutListeners = null;
392-
clientTimeoutListeners = null;
384+
outboundTimeoutListeners = null;
385+
inboundTimeoutListeners = null;
393386
}
394387

395388
@Override
@@ -417,11 +410,11 @@ private void signalPacketTransmission(PacketEvent packet, boolean onMainThread)
417410
// Now, get the next non-cancelled listener
418411
if (!marker.hasExpired()) {
419412
for (; marker.getListenerTraversal().hasNext(); ) {
420-
AsyncListenerHandler handler = marker.getListenerTraversal().next().getListener();
421-
413+
AsyncListenerHandler handler = marker.getListenerTraversal().next();
414+
422415
if (!handler.isCancelled()) {
423-
marker.incrementProcessingDelay();
424-
handler.enqueuePacket(packet);
416+
marker.incrementProcessingDelay();
417+
handler.enqueuePacket(packet);
425418
return;
426419
}
427420
}
@@ -473,12 +466,12 @@ public PacketProcessingQueue getProcessingQueue(PacketEvent packet) {
473466
* @param onMainThread whether or not this method was run by the main thread.
474467
*/
475468
public void signalFreeProcessingSlot(PacketEvent packet, boolean onMainThread) {
476-
PacketProcessingQueue queue = getProcessingQueue(packet);
477-
// mark slot as done
478-
queue.signalProcessingDone();
479-
480-
// start processing next slot if possible
481-
queue.signalBeginProcessing(onMainThread);
469+
PacketProcessingQueue queue = getProcessingQueue(packet);
470+
// mark slot as done
471+
queue.signalProcessingDone();
472+
473+
// start processing next slot if possible
474+
queue.signalBeginProcessing(onMainThread);
482475
}
483476

484477
/**

src/main/java/com/comphenix/protocol/async/AsyncListenerHandler.java

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@
3434
import com.comphenix.protocol.events.PacketEvent;
3535
import com.comphenix.protocol.events.PacketListener;
3636
import com.comphenix.protocol.scheduler.Task;
37-
import com.comphenix.protocol.timing.TimedListenerManager;
38-
import com.comphenix.protocol.timing.TimedListenerManager.ListenerType;
39-
import com.comphenix.protocol.timing.TimedTracker;
37+
import com.comphenix.protocol.timing.TimingListenerType;
38+
import com.comphenix.protocol.timing.TimingTrackerManager;
4039
import com.google.common.base.Function;
4140
import com.google.common.base.Joiner;
4241

@@ -100,9 +99,6 @@ public class AsyncListenerHandler {
10099
// Warn plugins that the async listener handler must be started
101100
private Task warningTask;
102101

103-
// Timing manager
104-
private TimedListenerManager timedManager = TimedListenerManager.getInstance();
105-
106102
/**
107103
* Construct a manager for an asynchronous packet handler.
108104
* @param mainThread - the main game thread.
@@ -326,9 +322,9 @@ public synchronized void start(Function<AsyncRunnable, Void> executor) {
326322

327323
scheduleAsync(() -> delegateCopy.apply(listenerLoop));
328324
}
329-
325+
330326
private void scheduleAsync(Runnable runnable) {
331-
filterManager.getScheduler().runTaskAsync(runnable);
327+
filterManager.getScheduler().runTaskAsync(runnable);
332328
}
333329

334330
/**
@@ -600,27 +596,13 @@ private void processPacket(int workerID, PacketEvent packet, String methodName)
600596
marker.setListenerHandler(this);
601597
marker.setWorkerID(workerID);
602598

603-
// We're not THAT worried about performance here
604-
if (timedManager.isTiming()) {
605-
// Retrieve the tracker to use
606-
TimedTracker tracker = timedManager.getTracker(listener,
607-
packet.isServerPacket() ? ListenerType.ASYNC_SERVER_SIDE : ListenerType.ASYNC_CLIENT_SIDE);
608-
long token = tracker.beginTracking();
609-
610-
if (packet.isServerPacket())
611-
listener.onPacketSending(packet);
612-
else
613-
listener.onPacketReceiving(packet);
614-
615-
// And we're done
616-
tracker.endTracking(token, packet.getPacketType());
617-
618-
} else {
619-
if (packet.isServerPacket())
620-
listener.onPacketSending(packet);
621-
else
622-
listener.onPacketReceiving(packet);
623-
}
599+
TimingTrackerManager.get(listener, packet.isServerPacket() ? TimingListenerType.ASYNC_OUTBOUND : TimingListenerType.ASYNC_INBOUND)
600+
.track(packet.getPacketType(), () -> {
601+
if (packet.isServerPacket())
602+
listener.onPacketSending(packet);
603+
else
604+
listener.onPacketReceiving(packet);
605+
});
624606
}
625607

626608
} catch (OutOfMemoryError e) {

src/main/java/com/comphenix/protocol/async/AsyncMarker.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import com.comphenix.protocol.ProtocolLogger;
3232
import com.comphenix.protocol.events.NetworkMarker;
3333
import com.comphenix.protocol.events.PacketEvent;
34-
import com.comphenix.protocol.injector.PrioritizedListener;
3534
import com.comphenix.protocol.reflect.FieldAccessException;
3635
import com.comphenix.protocol.reflect.FuzzyReflection;
3736
import com.comphenix.protocol.utility.MinecraftReflection;
@@ -70,7 +69,7 @@ public class AsyncMarker implements Serializable, Comparable<AsyncMarker> {
7069
/**
7170
* Current list of async packet listeners.
7271
*/
73-
private transient Iterator<PrioritizedListener<AsyncListenerHandler>> listenerTraversal;
72+
private transient Iterator<AsyncListenerHandler> listenerTraversal;
7473

7574
// Timeout handling
7675
private long initialTime;
@@ -366,15 +365,15 @@ void setWorkerID(int workerID) {
366365
* Retrieve iterator for the next listener in line.
367366
* @return Next async packet listener iterator.
368367
*/
369-
Iterator<PrioritizedListener<AsyncListenerHandler>> getListenerTraversal() {
368+
Iterator<AsyncListenerHandler> getListenerTraversal() {
370369
return listenerTraversal;
371370
}
372371

373372
/**
374373
* Set the iterator for the next listener.
375374
* @param listenerTraversal - the new async packet listener iterator.
376375
*/
377-
void setListenerTraversal(Iterator<PrioritizedListener<AsyncListenerHandler>> listenerTraversal) {
376+
void setListenerTraversal(Iterator<AsyncListenerHandler> listenerTraversal) {
378377
this.listenerTraversal = listenerTraversal;
379378
}
380379

0 commit comments

Comments
 (0)