Refactored the SortedCopyOnWriteArray out into a separate package.
Made it extend the java.util.Collection interface.
Dieser Commit ist enthalten in:
Ursprung
fffa3881dd
Commit
616213924b
@ -51,15 +51,15 @@ public class ProtocolLibrary extends JavaPlugin {
|
|||||||
Server server = getServer();
|
Server server = getServer();
|
||||||
PluginManager manager = server.getPluginManager();
|
PluginManager manager = server.getPluginManager();
|
||||||
|
|
||||||
|
// Notify server managers of incompatible plugins
|
||||||
|
checkForIncompatibility(manager);
|
||||||
|
|
||||||
// Player login and logout events
|
// Player login and logout events
|
||||||
protocolManager.registerEvents(manager, this);
|
protocolManager.registerEvents(manager, this);
|
||||||
|
|
||||||
// Inject our hook into already existing players
|
// Inject our hook into already existing players
|
||||||
protocolManager.initializePlayers(server.getOnlinePlayers());
|
protocolManager.initializePlayers(server.getOnlinePlayers());
|
||||||
|
|
||||||
// Notify server managers of incompatible plugins
|
|
||||||
checkForIncompatibility(manager);
|
|
||||||
|
|
||||||
// Try to enable statistics
|
// Try to enable statistics
|
||||||
try {
|
try {
|
||||||
statistisc = new Statistics(this);
|
statistisc = new Statistics(this);
|
||||||
@ -77,7 +77,9 @@ public class ProtocolLibrary extends JavaPlugin {
|
|||||||
for (String plugin : incompatiblePlugins) {
|
for (String plugin : incompatiblePlugins) {
|
||||||
if (manager.getPlugin(plugin) != null) {
|
if (manager.getPlugin(plugin) != null) {
|
||||||
// Check for versions, ect.
|
// Check for versions, ect.
|
||||||
logger.severe(ChatColor.RED + "Detected incompatible plugin: " + plugin);
|
logger.severe("Detected incompatible plugin: " + plugin);
|
||||||
|
logger.info("Using woraround.");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,223 @@
|
|||||||
|
package com.comphenix.protocol.concurrency;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implicitly sorted array list that preserves insertion order and maintains duplicates.
|
||||||
|
* @param <T> - type of the elements in the list.
|
||||||
|
*/
|
||||||
|
public class SortedCopyOnWriteArray<T extends Comparable<T>> implements Iterable<T>, Collection<T> {
|
||||||
|
// Prevent reordering
|
||||||
|
private volatile List<T> list;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an empty sorted array.
|
||||||
|
*/
|
||||||
|
public SortedCopyOnWriteArray() {
|
||||||
|
list = new ArrayList<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a sorted array from the given list. The elements will be automatically sorted.
|
||||||
|
* @param wrapped - the collection whose elements are to be placed into the list.
|
||||||
|
*/
|
||||||
|
public SortedCopyOnWriteArray(Collection<T> wrapped) {
|
||||||
|
this.list = new ArrayList<T>(wrapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a sorted array from the given list.
|
||||||
|
* @param wrapped - the collection whose elements are to be placed into the list.
|
||||||
|
* @param sort - TRUE to automatically sort the collection, FALSE if it is already sorted.
|
||||||
|
*/
|
||||||
|
public SortedCopyOnWriteArray(Collection<T> wrapped, boolean sort) {
|
||||||
|
this.list = new ArrayList<T>(wrapped);
|
||||||
|
|
||||||
|
if (sort) {
|
||||||
|
Collections.sort(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts the given element in the proper location.
|
||||||
|
* @param value - element to insert.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized boolean add(T value) {
|
||||||
|
|
||||||
|
// We use NULL as a special marker, so we don't allow it
|
||||||
|
if (value == null)
|
||||||
|
throw new IllegalArgumentException("value cannot be NULL");
|
||||||
|
|
||||||
|
List<T> copy = new ArrayList<T>();
|
||||||
|
|
||||||
|
for (T element : list) {
|
||||||
|
// If the value is now greater than the current element, it should be placed right before it
|
||||||
|
if (value != null && value.compareTo(element) < 0) {
|
||||||
|
copy.add(value);
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
copy.add(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't forget to add it
|
||||||
|
if (value != null)
|
||||||
|
copy.add(value);
|
||||||
|
|
||||||
|
list = copy;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean addAll(Collection<? extends T> values) {
|
||||||
|
|
||||||
|
if (values == null)
|
||||||
|
throw new IllegalArgumentException("values cannot be NULL");
|
||||||
|
if (values.size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
List<T> copy = new ArrayList<T>();
|
||||||
|
|
||||||
|
// Insert the new content and sort it
|
||||||
|
copy.addAll(list);
|
||||||
|
copy.addAll(values);
|
||||||
|
Collections.sort(copy);
|
||||||
|
|
||||||
|
list = copy;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes from the list by making a new list with every element except the one given.
|
||||||
|
* <p>
|
||||||
|
* Objects will be compared using the given objects equals() method.
|
||||||
|
* @param value - value to remove.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized boolean remove(Object value) {
|
||||||
|
List<T> copy = new ArrayList<T>();
|
||||||
|
|
||||||
|
// Note that there's not much to be gained from using BinarySearch, as we
|
||||||
|
// have to copy (and thus read) the entire list regardless.
|
||||||
|
|
||||||
|
// Copy every element except the one given to us.
|
||||||
|
for (T element : list) {
|
||||||
|
if (value != null && !Objects.equal(value, element)) {
|
||||||
|
copy.add(element);
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list = copy;
|
||||||
|
return value == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(Collection<?> values) {
|
||||||
|
// Special cases
|
||||||
|
if (values == null)
|
||||||
|
throw new IllegalArgumentException("values cannot be NULL");
|
||||||
|
if (values.size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
List<T> copy = new ArrayList<T>();
|
||||||
|
|
||||||
|
copy.addAll(list);
|
||||||
|
copy.removeAll(values);
|
||||||
|
|
||||||
|
list = copy;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(Collection<?> values) {
|
||||||
|
// Special cases
|
||||||
|
if (values == null)
|
||||||
|
throw new IllegalArgumentException("values cannot be NULL");
|
||||||
|
if (values.size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
List<T> copy = new ArrayList<T>();
|
||||||
|
|
||||||
|
copy.addAll(list);
|
||||||
|
copy.removeAll(values);
|
||||||
|
|
||||||
|
list = copy;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes from the list by making a copy of every element except the one with the given index.
|
||||||
|
* @param index - index of the element to remove.
|
||||||
|
*/
|
||||||
|
public synchronized void remove(int index) {
|
||||||
|
|
||||||
|
List<T> copy = new ArrayList<T>(list);
|
||||||
|
|
||||||
|
copy.remove(index);
|
||||||
|
list = copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an element by index.
|
||||||
|
* @param index - index of element to retrieve.
|
||||||
|
* @return The element at the given location.
|
||||||
|
*/
|
||||||
|
public T get(int index) {
|
||||||
|
return list.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the size of the list.
|
||||||
|
* @return Size of the list.
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an iterator over the elements in the given list.
|
||||||
|
* Warning: No not attempt to remove elements using the iterator.
|
||||||
|
*/
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return Iterables.unmodifiableIterable(list).iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
list = new ArrayList<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object value) {
|
||||||
|
return list.contains(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsAll(Collection<?> values) {
|
||||||
|
return list.containsAll(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return list.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] toArray() {
|
||||||
|
return list.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("hiding")
|
||||||
|
@Override
|
||||||
|
public <T> T[] toArray(T[] a) {
|
||||||
|
return list.toArray(a);
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ import java.util.concurrent.ConcurrentMap;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.concurrency.SortedCopyOnWriteArray;
|
||||||
import com.comphenix.protocol.events.ListenerPriority;
|
import com.comphenix.protocol.events.ListenerPriority;
|
||||||
import com.comphenix.protocol.events.ListeningWhitelist;
|
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||||
import com.comphenix.protocol.events.PacketAdapter;
|
import com.comphenix.protocol.events.PacketAdapter;
|
||||||
|
@ -50,6 +50,22 @@ class PlayerInjector {
|
|||||||
public interface FakePacket {
|
public interface FakePacket {
|
||||||
// Nothing
|
// Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the inject hook type. Different types allow for maximum compatibility.
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
public enum InjectHooks {
|
||||||
|
/**
|
||||||
|
* Override the packet queue lists in NetworkHandler.
|
||||||
|
*/
|
||||||
|
NETWORK_HANDLER_FIELDS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the NetworkHandler itself, and it's sendPacket-method.
|
||||||
|
*/
|
||||||
|
OVERRIDE_NETWORK_HANDLER
|
||||||
|
}
|
||||||
|
|
||||||
// Cache previously retrieved fields
|
// Cache previously retrieved fields
|
||||||
private static Field serverHandlerField;
|
private static Field serverHandlerField;
|
||||||
@ -68,6 +84,7 @@ class PlayerInjector {
|
|||||||
private boolean hasInitialized;
|
private boolean hasInitialized;
|
||||||
|
|
||||||
// Reference to the player's network manager
|
// Reference to the player's network manager
|
||||||
|
private VolatileField networkManagerRef;
|
||||||
private Object networkManager;
|
private Object networkManager;
|
||||||
|
|
||||||
// Current net handler
|
// Current net handler
|
||||||
@ -98,6 +115,9 @@ class PlayerInjector {
|
|||||||
CraftPlayer craft = (CraftPlayer) player;
|
CraftPlayer craft = (CraftPlayer) player;
|
||||||
EntityPlayer notchEntity = craft.getHandle();
|
EntityPlayer notchEntity = craft.getHandle();
|
||||||
|
|
||||||
|
Object serverHandler = null;
|
||||||
|
Object networkManager = null;
|
||||||
|
|
||||||
if (!hasInitialized) {
|
if (!hasInitialized) {
|
||||||
// Do this first, in case we encounter an exception
|
// Do this first, in case we encounter an exception
|
||||||
hasInitialized = true;
|
hasInitialized = true;
|
||||||
@ -105,12 +125,13 @@ class PlayerInjector {
|
|||||||
// Retrieve the server handler
|
// Retrieve the server handler
|
||||||
if (serverHandlerField == null)
|
if (serverHandlerField == null)
|
||||||
serverHandlerField = FuzzyReflection.fromObject(notchEntity).getFieldByType(".*NetServerHandler");
|
serverHandlerField = FuzzyReflection.fromObject(notchEntity).getFieldByType(".*NetServerHandler");
|
||||||
Object serverHandler = FieldUtils.readField(serverHandlerField, notchEntity);
|
serverHandler = FieldUtils.readField(serverHandlerField, notchEntity);
|
||||||
|
|
||||||
// Next, get the network manager
|
// Next, get the network manager
|
||||||
if (networkManagerField == null)
|
if (networkManagerField == null)
|
||||||
networkManagerField = FuzzyReflection.fromObject(serverHandler).getFieldByType(".*NetworkManager");
|
networkManagerField = FuzzyReflection.fromObject(serverHandler).getFieldByType(".*NetworkManager");
|
||||||
networkManager = FieldUtils.readField(networkManagerField, serverHandler);
|
networkManagerRef = new VolatileField(networkManagerField, serverHandler);
|
||||||
|
networkManager = networkManagerRef.getValue();
|
||||||
|
|
||||||
// Create the network manager modifier from the actual object type
|
// Create the network manager modifier from the actual object type
|
||||||
if (networkManager != null && networkModifier == null)
|
if (networkManager != null && networkModifier == null)
|
||||||
@ -195,6 +216,8 @@ class PlayerInjector {
|
|||||||
*/
|
*/
|
||||||
public void sendServerPacket(Packet packet, boolean filtered) throws InvocationTargetException {
|
public void sendServerPacket(Packet packet, boolean filtered) throws InvocationTargetException {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (networkManager != null) {
|
if (networkManager != null) {
|
||||||
try {
|
try {
|
||||||
if (!filtered) {
|
if (!filtered) {
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
package com.comphenix.protocol.injector;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An implicitly sorted array list that preserves insertion order and maintains duplicates.
|
|
||||||
* @param <T> - type of the elements in the list.
|
|
||||||
*/
|
|
||||||
class SortedCopyOnWriteArray<T> implements Iterable<T> {
|
|
||||||
// Prevent reordering
|
|
||||||
private volatile List<T> list;
|
|
||||||
|
|
||||||
public SortedCopyOnWriteArray() {
|
|
||||||
this(new ArrayList<T>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public SortedCopyOnWriteArray(List<T> wrapped) {
|
|
||||||
this.list = wrapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts the given element in the proper location.
|
|
||||||
* @param value - element to insert.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public synchronized void add(T value) {
|
|
||||||
|
|
||||||
// We use NULL as a special marker, so we don't allow it
|
|
||||||
if (value == null)
|
|
||||||
throw new IllegalArgumentException("value cannot be NULL");
|
|
||||||
|
|
||||||
List<T> copy = new ArrayList<T>();
|
|
||||||
Comparable<T> compare = (Comparable<T>) value;
|
|
||||||
|
|
||||||
for (T element : list) {
|
|
||||||
// If the value is now greater than the current element, it should be placed right before it
|
|
||||||
if (value != null && compare.compareTo(element) < 0) {
|
|
||||||
copy.add(value);
|
|
||||||
value = null;
|
|
||||||
}
|
|
||||||
copy.add(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't forget to add it
|
|
||||||
if (value != null)
|
|
||||||
copy.add(value);
|
|
||||||
|
|
||||||
list = copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes from the list by making a new list with every element except the one given.
|
|
||||||
* <p>
|
|
||||||
* Objects will be compared using the given objects equals() method.
|
|
||||||
* @param value - value to remove.
|
|
||||||
*/
|
|
||||||
public synchronized void remove(T value) {
|
|
||||||
List<T> copy = new ArrayList<T>();
|
|
||||||
|
|
||||||
// Copy every element except the one given to us
|
|
||||||
for (T element : list) {
|
|
||||||
if (value != null && !Objects.equal(value, element)) {
|
|
||||||
copy.add(element);
|
|
||||||
value = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list = copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes from the list by making a copy of every element except the one with the given index.
|
|
||||||
* @param index - index of the element to remove.
|
|
||||||
*/
|
|
||||||
public synchronized void remove(int index) {
|
|
||||||
|
|
||||||
List<T> copy = new ArrayList<T>(list);
|
|
||||||
|
|
||||||
copy.remove(index);
|
|
||||||
list = copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves an element by index.
|
|
||||||
* @param index - index of element to retrieve.
|
|
||||||
* @return The element at the given location.
|
|
||||||
*/
|
|
||||||
public T get(int index) {
|
|
||||||
return list.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the size of the list.
|
|
||||||
* @return Size of the list.
|
|
||||||
*/
|
|
||||||
public int size() {
|
|
||||||
return list.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves an iterator over the elements in the given list.
|
|
||||||
* Warning: No not attempt to remove elements using the iterator.
|
|
||||||
*/
|
|
||||||
public Iterator<T> iterator() {
|
|
||||||
return Iterables.unmodifiableIterable(list).iterator();
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,6 +8,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.concurrency.SortedCopyOnWriteArray;
|
||||||
import com.comphenix.protocol.events.ListenerPriority;
|
import com.comphenix.protocol.events.ListenerPriority;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
|
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren