Merge branch 'pr-1659'

This commit is contained in:
Dan Mulloy 2022-07-24 11:07:39 -04:00
commit 84cb541866
No known key found for this signature in database
GPG Key ID: BFACD592A5F0DFD6
46 changed files with 283 additions and 405 deletions

View File

@ -27,7 +27,6 @@ import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.error.Report;
import com.comphenix.protocol.error.ReportType;
import com.comphenix.protocol.events.PacketEvent;
import com.google.common.collect.Sets;
/**
* A command to apply JavaScript filtering to the packet command.

View File

@ -21,7 +21,6 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.comphenix.protocol.utility.MinecraftVersion;
import org.bukkit.plugin.Plugin;
/**
* @author dmulloy2

View File

@ -121,16 +121,10 @@ public class AsyncListenerHandler {
}
private void startWarningTask() {
warningTask = filterManager.getScheduler().scheduleSyncDelayedTask(getPlugin(), new Runnable() {
@Override
public void run() {
ProtocolLibrary.getErrorReporter().reportWarning(AsyncListenerHandler.this, Report.
newBuilder(REPORT_HANDLER_NOT_STARTED).
messageParam(listener.getPlugin(), AsyncListenerHandler.this).
build()
);
}
}, 2 * TICKS_PER_SECOND);
warningTask = filterManager.getScheduler().scheduleSyncDelayedTask(getPlugin(), () -> ProtocolLibrary.getErrorReporter().reportWarning(AsyncListenerHandler.this, Report.
newBuilder(REPORT_HANDLER_NOT_STARTED).
messageParam(listener.getPlugin(), AsyncListenerHandler.this).
build()), 2 * TICKS_PER_SECOND);
}
private void stopWarningTask() {
@ -287,19 +281,16 @@ public class AsyncListenerHandler {
final AsyncRunnable listenerLoop = getListenerLoop();
stopWarningTask();
scheduleAsync(new Runnable() {
@Override
public void run() {
Thread thread = Thread.currentThread();
String previousName = thread.getName();
String workerName = getFriendlyWorkerName(listenerLoop.getID());
scheduleAsync(() -> {
Thread thread = Thread.currentThread();
// Add the friendly worker name
thread.setName(workerName);
listenerLoop.run();
thread.setName(previousName);
}
String previousName = thread.getName();
String workerName = getFriendlyWorkerName(listenerLoop.getID());
// Add the friendly worker name
thread.setName(workerName);
listenerLoop.run();
thread.setName(previousName);
});
}
@ -335,12 +326,7 @@ public class AsyncListenerHandler {
final AsyncRunnable listenerLoop = getListenerLoop();
final Function<AsyncRunnable, Void> delegateCopy = executor;
scheduleAsync(new Runnable() {
@Override
public void run() {
delegateCopy.apply(listenerLoop);
}
});
scheduleAsync(() -> delegateCopy.apply(listenerLoop));
}
private void scheduleAsync(Runnable runnable) {
@ -423,31 +409,28 @@ public class AsyncListenerHandler {
if (syncTask < 0) {
stopWarningTask();
syncTask = filterManager.getScheduler().scheduleSyncRepeatingTask(getPlugin(), new Runnable() {
@Override
public void run() {
long stopTime = System.nanoTime() + unit.convert(time, TimeUnit.NANOSECONDS);
while (!cancelled) {
PacketEvent packet = queuedPackets.poll();
if (packet == INTERUPT_PACKET || packet == WAKEUP_PACKET) {
// Sorry, asynchronous threads!
queuedPackets.add(packet);
// Try again next tick
break;
} else if (packet != null && packet.getAsyncMarker() != null) {
processPacket(workerID, packet, "onSyncPacket()");
} else {
// No more packets left - wait a tick
break;
}
// Check time here, ensuring that we at least process one packet
if (System.nanoTime() < stopTime)
break;
syncTask = filterManager.getScheduler().scheduleSyncRepeatingTask(getPlugin(), () -> {
long stopTime = System.nanoTime() + unit.convert(time, TimeUnit.NANOSECONDS);
while (!cancelled) {
PacketEvent packet = queuedPackets.poll();
if (packet == INTERUPT_PACKET || packet == WAKEUP_PACKET) {
// Sorry, asynchronous threads!
queuedPackets.add(packet);
// Try again next tick
break;
} else if (packet != null && packet.getAsyncMarker() != null) {
processPacket(workerID, packet, "onSyncPacket()");
} else {
// No more packets left - wait a tick
break;
}
// Check time here, ensuring that we at least process one packet
if (System.nanoTime() < stopTime)
break;
}
}, tickDelay, tickDelay);

View File

@ -17,6 +17,15 @@
package com.comphenix.protocol.async;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import com.comphenix.protocol.PacketStream;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLogger;
@ -28,14 +37,6 @@ import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.google.common.primitives.Longs;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
/**
* Contains information about the packet that is being processed by asynchronous listeners.

View File

@ -17,13 +17,9 @@
package com.comphenix.protocol.async;
import org.bukkit.plugin.Plugin;
import com.comphenix.protocol.events.*;
import com.comphenix.protocol.events.ListenerOptions;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.ListeningWhitelist;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.events.PacketListener;
import org.bukkit.plugin.Plugin;
/**
* Represents a NO OPERATION listener.

View File

@ -17,15 +17,17 @@
package com.comphenix.protocol.async;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.FieldAccessException;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.PriorityBlockingQueue;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.FieldAccessException;
import org.bukkit.entity.Player;
/**
@ -38,9 +40,9 @@ abstract class PacketSendingQueue {
public static final int INITIAL_CAPACITY = 10;
// Whether or not packet transmission must occur on a specific thread
private final boolean notThreadSafe;
private PriorityBlockingQueue<PacketEventHolder> sendingQueue;
private final PriorityBlockingQueue<PacketEventHolder> sendingQueue;
// Asynchronous packet sending
private Executor asynchronousSender;
private final Executor asynchronousSender;
// Whether or not we've run the cleanup procedure
private boolean cleanedUp = false;
@ -50,7 +52,7 @@ abstract class PacketSendingQueue {
* @param notThreadSafe - whether or not to synchronize with the main thread or a background thread.
*/
public PacketSendingQueue(boolean notThreadSafe, Executor asynchronousSender) {
this.sendingQueue = new PriorityBlockingQueue<PacketEventHolder>(INITIAL_CAPACITY);
this.sendingQueue = new PriorityBlockingQueue<>(INITIAL_CAPACITY);
this.notThreadSafe = notThreadSafe;
this.asynchronousSender = asynchronousSender;
}
@ -103,10 +105,10 @@ abstract class PacketSendingQueue {
/***
* Invoked when a list of packet IDs are no longer associated with any listeners.
* @param packetsRemoved - packets that no longer have any listeners.
* @param onMainThread - whether or not this is occuring on the main thread.
* @param onMainThread - whether or not this is occurring on the main thread.
*/
public synchronized void signalPacketUpdate(List<PacketType> packetsRemoved, boolean onMainThread) {
Set<PacketType> lookup = new HashSet<PacketType>(packetsRemoved);
Set<PacketType> lookup = new HashSet<>(packetsRemoved);
// Note that this is O(n), so it might be expensive
for (PacketEventHolder holder : sendingQueue) {
@ -197,13 +199,8 @@ abstract class PacketSendingQueue {
// Let's give it what it wants
if (onMainThread && wantAsync) {
asynchronousSender.execute(new Runnable() {
@Override
public void run() {
// We know this isn't on the main thread
processPacketHolder(false, holder);
}
});
// We know this isn't on the main thread
asynchronousSender.execute(() -> processPacketHolder(false, holder));
// Scheduler will do the rest
return true;

View File

@ -24,8 +24,6 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import org.bukkit.entity.Player;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.concurrency.ConcurrentPlayerMap;
import com.comphenix.protocol.error.ErrorReporter;
@ -33,6 +31,8 @@ import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.SortedPacketListenerList;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.bukkit.entity.Player;
/**
* Contains every sending queue for every player.
*

View File

@ -17,13 +17,12 @@
package com.comphenix.protocol.async;
import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Queue;
import javax.annotation.Nullable;
import com.google.common.base.Preconditions;
/**

View File

@ -8,7 +8,6 @@ import java.util.PriorityQueue;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.base.Ticker;
@ -49,19 +48,14 @@ public class ExpireHashMap<K, V> {
}
}
private Map<K, ExpireEntry> keyLookup = new HashMap<K, ExpireEntry>();
private PriorityQueue<ExpireEntry> expireQueue = new PriorityQueue<ExpireEntry>();
private final Map<K, ExpireEntry> keyLookup = new HashMap<>();
private final PriorityQueue<ExpireEntry> expireQueue = new PriorityQueue<>();
// View of keyLookup with direct values
private Map<K, V> valueView = Maps.transformValues(keyLookup, new Function<ExpireEntry, V>() {
@Override
public V apply(ExpireEntry entry) {
return entry.expireValue;
}
});
private final Map<K, V> valueView = Maps.transformValues(keyLookup, entry -> entry.expireValue);
// Supplied by the constructor
private Ticker ticker;
private final Ticker ticker;
/**
* Construct a new hash map where each entry may expire at a given time.

View File

@ -2,11 +2,11 @@ package com.comphenix.protocol.error;
import java.io.PrintStream;
import org.bukkit.plugin.Plugin;
import com.comphenix.protocol.error.Report.ReportBuilder;
import com.comphenix.protocol.reflect.PrettyPrinter;
import org.bukkit.plugin.Plugin;
/**
* Represents a basic error reporter that prints error reports to the standard error stream.
* <p>

View File

@ -1,9 +1,9 @@
package com.comphenix.protocol.error;
import org.bukkit.plugin.Plugin;
import com.comphenix.protocol.error.Report.ReportBuilder;
import org.bukkit.plugin.Plugin;
/**
* Construct an error reporter that delegates to another error reporter.
* @author Kristian

View File

@ -30,13 +30,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.comphenix.protocol.ProtocolConfig;
import com.comphenix.protocol.ProtocolLibrary;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import com.comphenix.protocol.ProtocolLogger;
import com.comphenix.protocol.collections.ExpireHashMap;
import com.comphenix.protocol.error.Report.ReportBuilder;
@ -45,6 +39,11 @@ import com.comphenix.protocol.reflect.PrettyPrinter;
import com.google.common.base.Preconditions;
import com.google.common.primitives.Primitives;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
/**
* Internal class used to handle exceptions.
*

View File

@ -17,10 +17,10 @@
package com.comphenix.protocol.error;
import org.bukkit.plugin.Plugin;
import com.comphenix.protocol.error.Report.ReportBuilder;
import org.bukkit.plugin.Plugin;
/**
* Represents an object that can forward an error {@link Report} to the display and permanent storage.
*

View File

@ -4,11 +4,11 @@ import java.io.File;
import java.net.URLDecoder;
import java.security.CodeSource;
import com.google.common.base.Preconditions;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import com.google.common.base.Preconditions;
public final class PluginContext {
// Determine plugin folder
private static File pluginFolder;

View File

@ -1,10 +1,9 @@
package com.comphenix.protocol.error;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
/**
* Represents a error or warning report.
*

View File

@ -1,10 +1,10 @@
package com.comphenix.protocol.error;
import org.bukkit.plugin.Plugin;
import com.comphenix.protocol.error.Report.ReportBuilder;
import com.google.common.base.Joiner;
import org.bukkit.plugin.Plugin;
/**
* Represents an error reporter that rethrows every exception instead.
* @author Kristian

View File

@ -1,5 +1,10 @@
package com.comphenix.protocol.events;
import javax.annotation.Nonnull;
import java.lang.reflect.Array;
import java.time.Instant;
import java.util.*;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.reflect.StructureModifier;
@ -12,7 +17,7 @@ import com.comphenix.protocol.wrappers.nbt.NbtBase;
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
import com.google.common.base.Preconditions;
import java.time.Instant;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.Sound;
@ -25,10 +30,6 @@ import org.bukkit.inventory.MerchantRecipe;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;
import javax.annotation.Nonnull;
import java.lang.reflect.Array;
import java.util.*;
public abstract class AbstractStructure {
protected transient Object handle;
protected transient StructureModifier<Object> structureModifier;

View File

@ -1,12 +1,11 @@
package com.comphenix.protocol.events;
import java.util.Optional;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.Converters;
import java.util.List;
import java.util.Optional;
public class InternalStructure extends AbstractStructure {
protected InternalStructure(Object handle, StructureModifier<Object> structureModifier) {

View File

@ -17,16 +17,12 @@
package com.comphenix.protocol.events;
import java.util.*;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.injector.GamePhase;
import com.google.common.base.Objects;
import com.google.common.collect.Sets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
/**
* Determines which packets will be observed by a listener, and with what priority.

View File

@ -1,14 +1,12 @@
package com.comphenix.protocol.events;
import javax.annotation.Nonnull;
import java.util.*;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager;
import com.google.common.base.Preconditions;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import javax.annotation.Nonnull;
import org.bukkit.entity.Player;
/**

View File

@ -17,13 +17,15 @@
package com.comphenix.protocol.events;
import javax.annotation.Nonnull;
import java.util.Set;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.injector.GamePhase;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.util.Set;
import javax.annotation.Nonnull;
import org.bukkit.plugin.Plugin;
/**

View File

@ -17,32 +17,6 @@
package com.comphenix.protocol.events;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.injector.StructureCache;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.ObjectWriter;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.cloning.AggregateCloner;
import com.comphenix.protocol.reflect.cloning.AggregateCloner.BuilderParameters;
import com.comphenix.protocol.reflect.cloning.BukkitCloner;
import com.comphenix.protocol.reflect.cloning.Cloner;
import com.comphenix.protocol.reflect.cloning.CollectionCloner;
import com.comphenix.protocol.reflect.cloning.FieldCloner;
import com.comphenix.protocol.reflect.cloning.GuavaOptionalCloner;
import com.comphenix.protocol.reflect.cloning.ImmutableDetector;
import com.comphenix.protocol.reflect.cloning.JavaOptionalCloner;
import com.comphenix.protocol.reflect.cloning.SerializableCloner;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.reflect.instances.MinecraftGenerator;
import com.comphenix.protocol.utility.MinecraftMethods;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.comphenix.protocol.wrappers.Converters;
import com.google.common.base.Function;
import com.google.common.collect.Sets;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.ObjectInputStream;
@ -56,6 +30,25 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.injector.StructureCache;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.ObjectWriter;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.reflect.cloning.*;
import com.comphenix.protocol.reflect.cloning.AggregateCloner.BuilderParameters;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.reflect.instances.MinecraftGenerator;
import com.comphenix.protocol.utility.MinecraftMethods;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.comphenix.protocol.wrappers.Converters;
import com.google.common.base.Function;
import com.google.common.collect.Sets;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
/**
* Represents a Minecraft packet indirectly.
*

View File

@ -17,6 +17,12 @@
package com.comphenix.protocol.events;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.WeakReference;
import java.util.EventObject;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.async.AsyncMarker;
@ -29,11 +35,7 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.WeakReference;
import java.util.EventObject;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;

View File

@ -16,14 +16,15 @@
*/
package com.comphenix.protocol.events;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang.Validate;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang.Validate;
/**
* Stores and retrieves metadata for applicable packet objects.
* @author dmulloy2

View File

@ -1,9 +1,9 @@
package com.comphenix.protocol.events;
import org.bukkit.plugin.Plugin;
import com.google.common.base.Preconditions;
import org.bukkit.plugin.Plugin;
/**
* Represents an adapter version of a post listener.
* @author Kristian

View File

@ -1,12 +1,12 @@
package com.comphenix.protocol.events;
import org.bukkit.entity.Player;
import com.comphenix.protocol.PacketStream;
import com.comphenix.protocol.PacketType.Sender;
import com.comphenix.protocol.ProtocolLibrary;
import com.google.common.base.Preconditions;
import org.bukkit.entity.Player;
/**
* Represents a packet that is scheduled for transmission at a later stage.
* @author Kristian

View File

@ -28,6 +28,13 @@ import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import com.comphenix.protocol.utility.ByteBuddyFactory;
import org.bukkit.*;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.profile.PlayerProfile;
import net.bytebuddy.description.ByteCodeElement;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
@ -42,13 +49,6 @@ import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import org.bukkit.*;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.profile.PlayerProfile;
import com.comphenix.protocol.utility.ByteBuddyFactory;
/**
* Represents a player object that can be serialized by Java.
*

View File

@ -224,17 +224,14 @@ public class BukkitUnwrapper implements Unwrapper {
if (Player.class.isAssignableFrom(type)) {
final Method getHandle = MinecraftReflection.getCraftPlayerClass().getMethod("getHandle");
Unwrapper unwrapper = new Unwrapper() {
@Override
public Object unwrapItem(Object wrapped) {
Unwrapper unwrapper = wrapped -> {
try {
return getHandle.invoke(((Player) wrapped).getPlayer());
} catch (Throwable ex) {
try {
return getHandle.invoke(((Player) wrapped).getPlayer());
} catch (Throwable ex) {
try {
return getHandle.invoke(Bukkit.getPlayer(((Player) wrapped).getUniqueId()));
} catch (ReflectiveOperationException ex1) {
throw new RuntimeException("Failed to unwrap proxy " + wrapped, ex);
}
return getHandle.invoke(Bukkit.getPlayer(((Player) wrapped).getUniqueId()));
} catch (ReflectiveOperationException ex1) {
throw new RuntimeException("Failed to unwrap proxy " + wrapped, ex);
}
}
};

View File

@ -16,6 +16,7 @@ import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.logging.Level;
@ -150,14 +151,9 @@ public class Metrics {
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
submitData();
}
});
Bukkit.getScheduler().runTask(plugin, Metrics.this::submitData);
}
}, 1000*60*5, 1000*60*30);
}, 1000L * 60 * 5, 1000L * 60 * 30);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
// WARNING: Just don't do it!
@ -260,17 +256,14 @@ public class Metrics {
data.put("plugins", pluginData);
// Create a new thread for the connection to the bStats server
new Thread(new Runnable() {
@Override
public void run() {
try {
// Send the data
sendData(data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
new Thread(() -> {
try {
// Send the data
sendData(data);
} catch (Exception e) {
// Something went wrong! :(
if (logFailedRequests) {
plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
}
}
}).start();
@ -326,7 +319,7 @@ public class Metrics {
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
gzip.write(str.getBytes("UTF-8"));
gzip.write(str.getBytes(StandardCharsets.UTF_8));
gzip.close();
return outputStream.toByteArray();
}

View File

@ -17,8 +17,6 @@
package com.comphenix.protocol.reflect;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.google.common.primitives.Primitives;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@ -27,6 +25,9 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.google.common.primitives.Primitives;
/**
* Used to print the content of an arbitrary class.
*
@ -37,7 +38,7 @@ public class PrettyPrinter {
/**
* How far we will recurse.
*/
public final static int RECURSE_DEPTH = 3;
public static final int RECURSE_DEPTH = 3;
/**
* Print the contents of an object.

View File

@ -2,43 +2,41 @@
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland
*
* 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
* 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
* 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;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* 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.
* 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;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 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
* 02111-1307 USA
*/
package com.comphenix.protocol.reflect.cloning;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import com.comphenix.protocol.reflect.instances.DefaultInstances;
import com.comphenix.protocol.reflect.instances.ExistingGenerator;
import com.comphenix.protocol.reflect.instances.InstanceProvider;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Implements a cloning procedure by trying multiple methods in turn until one is successful.
*
*
* @author Kristian
*/
public class AggregateCloner implements Cloner {
/**
* Supplies the cloner factories with necessary parameters.
*
*
* @author Kristian
*/
public static class BuilderParameters {
@ -48,11 +46,11 @@ public class AggregateCloner implements Cloner {
// Used to construct the different types
private InstanceProvider typeConstructor;
private BuilderParameters() {
// Only allow inner classes to construct it.
}
/**
* Retrieve the instance provider last set in the builder.
* @return Current instance provider.
@ -69,23 +67,23 @@ public class AggregateCloner implements Cloner {
return aggregateCloner;
}
}
/**
* Represents a builder for aggregate (combined) cloners.
*
*
* @author Kristian
*/
public static class Builder {
private final List<Function<BuilderParameters, Cloner>> factories = new ArrayList<>();
private final BuilderParameters parameters;
/**
* Create a new aggregate builder.
*/
public Builder() {
this.parameters = new BuilderParameters();
}
/**
* Set the instance provider supplied to all cloners in this builder.
* @param provider - new instance provider.
@ -103,23 +101,16 @@ public class AggregateCloner implements Cloner {
*/
public Builder andThen(final Class<? extends Cloner> type) {
// Use reflection to generate a factory on the fly
return andThen(new Function<BuilderParameters, Cloner>() {
@Override
public Cloner apply(@Nullable BuilderParameters param) {
Object result = param.typeConstructor.create(type);
if (result == null) {
throw new IllegalStateException("Constructed NULL instead of " + type);
}
if (type.isAssignableFrom(result.getClass()))
return (Cloner) result;
else
throw new IllegalStateException("Constructed " + result.getClass() + " instead of " + type);
}
return andThen(param -> {
final Object result = param.typeConstructor.create(type);
if (result == null) throw new IllegalStateException("Constructed NULL instead of " + type);
if (type.isAssignableFrom(result.getClass())) return (Cloner) result;
else throw new IllegalStateException("Constructed " + result.getClass() + " instead of " + type);
});
}
/**
* Add the next cloner that will be considered in turn.
* @param factory - factory constructing the next cloner.
@ -129,45 +120,41 @@ public class AggregateCloner implements Cloner {
factories.add(factory);
return this;
}
/**
* Build a new aggregate cloner using the supplied values.
* @return A new aggregate cloner.
*/
public AggregateCloner build() {
AggregateCloner newCloner = new AggregateCloner();
// The parameters we will pass to our cloners
Cloner paramCloner = new NullableCloner(newCloner);
InstanceProvider paramProvider = parameters.instanceProvider;
// Initialize parameters
parameters.aggregateCloner = paramCloner;
parameters.typeConstructor = DefaultInstances.fromArray(
ExistingGenerator.fromObjectArray(new Object[] { paramCloner, paramProvider })
);
// Build every cloner in the correct order
final List<Cloner> cloners = new ArrayList<>();
for (int i = 0; i < factories.size(); i++) {
Cloner cloner = factories.get(i).apply(parameters);
// See if we were successful
if (cloner != null)
cloners.add(cloner);
else
throw new IllegalArgumentException(
String.format("Cannot create cloner from %s (%s)", factories.get(i), i)
);
if (cloner != null) cloners.add(cloner);
else throw new IllegalArgumentException(String.format("Cannot create cloner from %s (%s)", factories.get(i), i));
}
// We're done
newCloner.setCloners(cloners);
return newCloner;
}
}
/**
* Represents a default aggregate cloner.
*/
@ -178,13 +165,13 @@ public class AggregateCloner implements Cloner {
andThen(CollectionCloner.class).
andThen(FieldCloner.class).
build();
// List of clone methods
private List<Cloner> cloners;
private WeakReference<Object> lastObject;
private int lastResult;
/**
* Begins constructing a new aggregate cloner.
* @return A builder for a new aggregate cloner.
@ -192,14 +179,14 @@ public class AggregateCloner implements Cloner {
public static Builder newBuilder() {
return new Builder();
}
/**
* Construct a new, empty aggregate cloner.
*/
private AggregateCloner() {
// Only used by our builder above.
}
/**
* Retrieves a view of the current list of cloners.
* @return Current cloners.
@ -207,23 +194,23 @@ public class AggregateCloner implements Cloner {
public List<Cloner> getCloners() {
return Collections.unmodifiableList(cloners);
}
/**
* Set the cloners that will be used.
* @param cloners - the cloners that will be used.
*/
private void setCloners(Iterable<? extends Cloner> cloners) {
this.cloners = Lists.newArrayList(cloners);
private void setCloners(Collection<? extends Cloner> cloners) {
this.cloners = new ArrayList<>(cloners);
}
@Override
public boolean canClone(Object source) {
// Optimize a bit
lastResult = getFirstCloner(source);
lastObject = new WeakReference<Object>(source);
lastObject = new WeakReference<>(source);
return lastResult >= 0 && lastResult < cloners.size();
}
/**
* Retrieve the index of the first cloner capable of cloning the given object.
* <p>
@ -236,7 +223,7 @@ public class AggregateCloner implements Cloner {
if (cloners.get(i).canClone(source))
return i;
}
return cloners.size();
}
@ -245,7 +232,7 @@ public class AggregateCloner implements Cloner {
if (source == null)
throw new IllegalAccessError("source cannot be NULL.");
int index = 0;
// Are we dealing with the same object?
if (lastObject != null && lastObject.get() == source) {
index = lastResult;

View File

@ -30,7 +30,6 @@ import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.*;
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
import com.google.common.collect.Maps;
import net.md_5.bungee.api.chat.BaseComponent;
@ -90,8 +89,7 @@ public class BukkitCloner implements Cloner {
} catch (Throwable ignored) { }
try {
fromManual(AdventureComponentConverter::getComponentClass, source ->
AdventureComponentConverter.clone(source));
fromManual(AdventureComponentConverter::getComponentClass, AdventureComponentConverter::clone);
} catch (Throwable ignored) { }
}

View File

@ -1,14 +1,15 @@
package com.comphenix.protocol.reflect.fuzzy;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.MethodInfo;
import com.google.common.collect.ImmutableList;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.MethodInfo;
import com.google.common.collect.ImmutableList;
/**
* Determine if a given class implements a given fuzzy (duck typed) contract.
*

View File

@ -1,5 +1,12 @@
package com.comphenix.protocol.utility;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.concurrent.Callable;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.reflect.FuzzyReflection;
@ -7,14 +14,10 @@ import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.concurrent.Callable;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.Origin;

View File

@ -17,6 +17,16 @@
package com.comphenix.protocol.utility;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLogger;
import com.comphenix.protocol.injector.BukkitUnwrapper;
@ -29,15 +39,7 @@ import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.wrappers.EnumWrappers;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Server;

View File

@ -19,10 +19,8 @@ package com.comphenix.protocol.wrappers;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
import com.comphenix.protocol.reflect.instances.DefaultInstances;
import com.google.common.base.Defaults;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;

View File

@ -13,7 +13,6 @@ import com.comphenix.protocol.reflect.FuzzyReflection;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.google.common.collect.Maps;
import org.apache.commons.lang.Validate;
import org.bukkit.GameMode;

View File

@ -16,7 +16,6 @@
*/
package com.comphenix.protocol.wrappers;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import org.bukkit.Location;

View File

@ -17,8 +17,6 @@
package com.comphenix.protocol.wrappers.collection;
import javax.annotation.Nullable;
import com.google.common.base.Function;
/**
@ -31,20 +29,10 @@ import com.google.common.base.Function;
*/
public abstract class AbstractConverted<VInner, VOuter> {
// Inner conversion
private Function<VOuter, VInner> innerConverter = new Function<VOuter, VInner>() {
@Override
public VInner apply(@Nullable VOuter param) {
return toInner(param);
}
};
private final Function<VOuter, VInner> innerConverter = this::toInner;
// Outer conversion
private Function<VInner, VOuter> outerConverter = new Function<VInner, VOuter>() {
@Override
public VOuter apply(@Nullable VInner param) {
return toOuter(param);
}
};
private final Function<VInner, VOuter> outerConverter = this::toOuter;
/**
* Convert a value from the inner map to the outer visible map.

View File

@ -17,16 +17,13 @@
package com.comphenix.protocol.wrappers.collection;
import com.google.common.collect.Collections2;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
/**
* Represents a map that wraps another map by transforming the entries going in and out.
*
@ -40,20 +37,10 @@ public abstract class ConvertedMap<Key, VInner, VOuter> extends AbstractConverte
private Map<Key, VInner> inner;
// Inner conversion
private BiFunction<Key, VOuter, VInner> innerConverter = new BiFunction<Key, VOuter, VInner>() {
@Override
public VInner apply(Key key, VOuter outer) {
return toInner(key, outer);
}
};
private final BiFunction<Key, VOuter, VInner> innerConverter = this::toInner;
// Outer conversion
private BiFunction<Key, VInner, VOuter> outerConverter = new BiFunction<Key, VInner, VOuter>() {
@Override
public VOuter apply(Key key, VInner inner) {
return toOuter(key, inner);
}
};
private final BiFunction<Key, VInner, VOuter> outerConverter = this::toOuter;
public ConvertedMap(Map<Key, VInner> inner) {
if (inner == null)
@ -143,12 +130,7 @@ public abstract class ConvertedMap<Key, VInner, VOuter> extends AbstractConverte
@Override
public Collection<VOuter> values() {
return Collections2.transform(entrySet(), new Function<Entry<Key, VOuter>, VOuter>() {
@Override
public VOuter apply(@Nullable java.util.Map.Entry<Key, VOuter> entry) {
return entry.getValue();
}
});
return Collections2.transform(entrySet(), Entry::getValue);
}
/**

View File

@ -183,18 +183,7 @@ public abstract class ConvertedMultimap<Key, VInner, VOuter> extends AbstractCon
@Override
public Collection<Entry<Key, VOuter>> entries() {
return ConvertedMap.convertedEntrySet(inner.entries(),
new BiFunction<Key, VOuter, VInner>() {
public VInner apply(Key key, VOuter outer) {
return toInner(outer);
}
},
new BiFunction<Key, VInner, VOuter>() {
public VOuter apply(Key key, VInner inner) {
return toOuter(inner);
}
}
);
return ConvertedMap.convertedEntrySet(inner.entries(), (key, outer) -> toInner(outer), (key, inner) -> toOuter(inner));
}
@Override

View File

@ -4,7 +4,6 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.comphenix.protocol.reflect.StructureModifier;
import com.google.common.collect.Maps;
public abstract class NameProperty {
private static final Map<Class<?>, StructureModifier<String>> MODIFIERS = new ConcurrentHashMap<>();

View File

@ -17,19 +17,16 @@
package com.comphenix.protocol.wrappers.nbt;
import com.comphenix.protocol.wrappers.collection.ConvertedList;
import com.comphenix.protocol.wrappers.nbt.io.NbtBinarySerializer;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import java.io.DataOutput;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Nullable;
import com.comphenix.protocol.wrappers.collection.ConvertedList;
import com.comphenix.protocol.wrappers.nbt.io.NbtBinarySerializer;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
/**
* Represents a concrete implementation of an NBT list that wraps an underlying NMS list.
* @author Kristian
@ -38,7 +35,7 @@ import com.google.common.collect.Iterables;
*/
class WrappedList<TType> implements NbtWrapper<List<NbtBase<TType>>>, NbtList<TType> {
// A list container
private WrappedElement<List<Object>> container;
private final WrappedElement<List<Object>> container;
// Saved wrapper list
private ConvertedList<Object, NbtBase<TType>> savedList;
@ -105,7 +102,7 @@ class WrappedList<TType> implements NbtWrapper<List<NbtBase<TType>>>, NbtList<TT
* @param handle - NMS instance.
*/
public WrappedList(Object handle) {
this.container = new WrappedElement<List<Object>>(handle);
this.container = new WrappedElement<>(handle);
this.elementType = container.getSubType();
}
@ -115,7 +112,7 @@ class WrappedList<TType> implements NbtWrapper<List<NbtBase<TType>>>, NbtList<TT
* @param name - name of the current list.
*/
public WrappedList(Object handle, String name) {
this.container = new WrappedElement<List<Object>>(handle, name);
this.container = new WrappedElement<>(handle, name);
this.elementType = container.getSubType();
}
@ -385,12 +382,7 @@ class WrappedList<TType> implements NbtWrapper<List<NbtBase<TType>>>, NbtList<TT
@Override
public Iterator<TType> iterator() {
return Iterables.transform(getValue(), new Function<NbtBase<TType>, TType>() {
@Override
public TType apply(@Nullable NbtBase<TType> param) {
return param.getValue();
}
}).iterator();
return Iterables.transform(getValue(), NbtBase::getValue).iterator();
}
@Override

View File

@ -3,13 +3,10 @@ package com.comphenix.protocol.wrappers.nbt.io;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;

View File

@ -1,20 +1,10 @@
package com.comphenix.integration.protocol;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.reflect.ExactReflection;
import com.comphenix.protocol.reflect.accessors.Accessors;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.simple.SimpleLogger;
import org.bukkit.Bukkit;
@ -23,6 +13,16 @@ import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginLoadOrder;
import org.bukkit.plugin.PluginManager;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class SimpleCraftBukkitITCase {
/**
@ -64,12 +64,9 @@ public class SimpleCraftBukkitITCase {
ProtocolLibrary.disableUpdates();
// Wait until the server and all the plugins have loaded
Bukkit.getScheduler().callSyncMethod(FAKE_PLUGIN, new Callable<Object>() {
@Override
public Object call() throws Exception {
initializePlugin(FAKE_PLUGIN);
return null;
}
Bukkit.getScheduler().callSyncMethod(FAKE_PLUGIN, () -> {
initializePlugin(FAKE_PLUGIN);
return null;
}).get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
// Plugins are now ready

View File

@ -1,17 +1,18 @@
package com.comphenix.integration.protocol;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import java.util.concurrent.Callable;
import org.bukkit.plugin.Plugin;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.bukkit.plugin.Plugin;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestPingPacket {
@ -56,28 +57,25 @@ public class TestPingPacket {
}
private Future<String> testInterception(Plugin test) {
final CountDownLatch latch = new CountDownLatch(1);
ProtocolLibrary.getProtocolManager().addPacketListener(
new PacketAdapter(test, PacketType.Status.Server.SERVER_INFO) {
@Override
public void onPacketSending(PacketEvent event) {
TestPingPacket.this.source = event.getPacket().getServerPings().read(0).toJson();
latch.countDown();
}
});
// Invoke the client on a separate thread
return Executors.newSingleThreadExecutor().submit(new Callable<String>() {
@Override
public String call() throws Exception {
SimpleMinecraftClient client = new SimpleMinecraftClient(PROTOCOL_VERSION);
String information = client.queryLocalPing();
return Executors.newSingleThreadExecutor().submit(() -> {
SimpleMinecraftClient client = new SimpleMinecraftClient(PROTOCOL_VERSION);
String information = client.queryLocalPing();
// Wait for the listener to catch up
for (int i = 0; i < 1000 && (TestPingPacket.this.source == null); i++) {
Thread.sleep(1);
}
return information;
}
// Wait for the listener to catch up
latch.await(1, TimeUnit.SECONDS);
return information;
});
}
}