Hack for WrappedSignedProperty on Cauldron 1.7.10. FIXES #54
Dieser Commit ist enthalten in:
Ursprung
4ccd8853c4
Commit
d717ff1586
@ -0,0 +1,316 @@
|
|||||||
|
package com.comphenix.protocol.wrappers;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||||
|
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
||||||
|
import com.comphenix.protocol.wrappers.collection.ConvertedSet;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Multiset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap multimap and multiset from another version of Guava by using reflection.
|
||||||
|
* <p>
|
||||||
|
* This is often the last resort, if we can't remap manually.
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
class GuavaReflection {
|
||||||
|
/**
|
||||||
|
* Wrap a Bukkit multimap around Minecraft's internal multimap.
|
||||||
|
* @param multimap - the multimap to wrap.
|
||||||
|
* @return The Bukkit multimap.
|
||||||
|
*/
|
||||||
|
public static <TKey, TValue> Multimap<TKey, TValue> getBukkitMultimap(
|
||||||
|
final Object multimap) {
|
||||||
|
return new Multimap<TKey, TValue>() {
|
||||||
|
private Class<?> multimapClass = multimap.getClass();
|
||||||
|
private MethodAccessor methodAsMap = Accessors.getMethodAccessor(multimapClass, "asMap");
|
||||||
|
private MethodAccessor methodClear = Accessors.getMethodAccessor(multimapClass, "clear");
|
||||||
|
private MethodAccessor methodContainsEntry = Accessors.getMethodAccessor(multimapClass, "containsEntry",Object.class, Object.class);
|
||||||
|
private MethodAccessor methodContainsKey = Accessors.getMethodAccessor(multimapClass, "containsKey", Object.class);
|
||||||
|
private MethodAccessor methodContainsValue = Accessors.getMethodAccessor(multimapClass, "containsValue", Object.class);
|
||||||
|
private MethodAccessor methodEntries = Accessors.getMethodAccessor(multimapClass, "entries");
|
||||||
|
private MethodAccessor methodGet = Accessors.getMethodAccessor(multimapClass, "get", Object.class);
|
||||||
|
private MethodAccessor methodIsEmpty = Accessors.getMethodAccessor(multimapClass, "isEmpty");
|
||||||
|
private MethodAccessor methodKeySet = Accessors.getMethodAccessor(multimapClass, "keySet");
|
||||||
|
private MethodAccessor methodKeys = Accessors.getMethodAccessor(multimapClass, "keys");
|
||||||
|
private MethodAccessor methodPut = Accessors.getMethodAccessor(multimapClass, "put", Object.class, Object.class);
|
||||||
|
private MethodAccessor methodPutAll = Accessors.getMethodAccessor(multimapClass, "putAll", Object.class, Iterable.class);
|
||||||
|
private MethodAccessor methodRemove = Accessors.getMethodAccessor(multimapClass, "remove", Object.class, Object.class);
|
||||||
|
private MethodAccessor methodRemoveAll = Accessors.getMethodAccessor(multimapClass, "removeAll", Object.class);
|
||||||
|
private MethodAccessor methodReplaceValues = Accessors.getMethodAccessor(multimapClass, "replaceValues", Object.class, Iterable.class);
|
||||||
|
private MethodAccessor methodSize = Accessors.getMethodAccessor(multimapClass, "size");
|
||||||
|
private MethodAccessor methodValues = Accessors.getMethodAccessor(multimapClass, "values");
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Map<TKey, Collection<TValue>> asMap() {
|
||||||
|
return (Map<TKey, Collection<TValue>>) methodAsMap.invoke(multimap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
methodClear.invoke(multimap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsEntry(Object arg0, Object arg1) {
|
||||||
|
return (Boolean) methodContainsEntry.invoke(multimap, arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(Object arg0) {
|
||||||
|
return (Boolean) methodContainsKey.invoke(multimap, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsValue(Object arg0) {
|
||||||
|
return (Boolean) methodContainsValue.invoke(multimap, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Collection<Entry<TKey, TValue>> entries() {
|
||||||
|
return (Collection<Entry<TKey, TValue>>) methodEntries.invoke(multimap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object arg0) {
|
||||||
|
return multimap.equals(arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return multimap.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return multimap.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Collection<TValue> get(TKey arg0) {
|
||||||
|
return (Collection<TValue>) methodGet.invoke(multimap, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return (Boolean) methodIsEmpty.invoke(multimap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Set<TKey> keySet() {
|
||||||
|
return (Set<TKey>) methodKeySet.invoke(multimap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Multiset<TKey> keys() {
|
||||||
|
return getBukkitMultiset(methodKeys.invoke(multimap));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean put(TKey arg0, TValue arg1) {
|
||||||
|
return (Boolean) methodPut.invoke(multimap, arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean putAll(com.google.common.collect.Multimap<? extends TKey, ? extends TValue> arg0) {
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
// Add each entry
|
||||||
|
for (Entry<? extends TKey, ? extends TValue> entry : arg0.entries()) {
|
||||||
|
result |= (Boolean) methodPut.invoke(multimap, entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean putAll(TKey arg0, Iterable<? extends TValue> arg1) {
|
||||||
|
return (Boolean) methodPutAll.invoke(arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object arg0, Object arg1) {
|
||||||
|
return (Boolean) methodRemove.invoke(multimap, arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Collection<TValue> removeAll(Object arg0) {
|
||||||
|
return (Collection<TValue>) methodRemoveAll.invoke(multimap, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Collection<TValue> replaceValues(TKey arg0, Iterable<? extends TValue> arg1) {
|
||||||
|
return (Collection<TValue>) methodReplaceValues.invoke(multimap, arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return (Integer) methodSize.invoke(multimap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Collection<TValue> values() {
|
||||||
|
return (Collection<TValue>) methodValues.invoke(multimap);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <TValue> Multiset<TValue> getBukkitMultiset(final Object multiset) {
|
||||||
|
return new Multiset<TValue>() {
|
||||||
|
private Class<?> multisetClass = multiset.getClass();
|
||||||
|
private MethodAccessor methodAddMany = Accessors.getMethodAccessor(multisetClass, "add", Object.class, int.class);
|
||||||
|
private MethodAccessor methodAddOne = Accessors.getMethodAccessor(multisetClass, "add", Object.class);
|
||||||
|
private MethodAccessor methodAddAll = Accessors.getMethodAccessor(multisetClass, "addAll", Collection.class);
|
||||||
|
private MethodAccessor methodClear = Accessors.getMethodAccessor(multisetClass, "clear");
|
||||||
|
private MethodAccessor methodContains = Accessors.getMethodAccessor(multisetClass, "contains", Object.class);
|
||||||
|
private MethodAccessor methodContainsAll = Accessors.getMethodAccessor(multisetClass, "containsAll", Collection.class);
|
||||||
|
private MethodAccessor methodCount = Accessors.getMethodAccessor(multisetClass, "count", Object.class);
|
||||||
|
private MethodAccessor methodElementSet = Accessors.getMethodAccessor(multisetClass, "elementSet");
|
||||||
|
private MethodAccessor methodEntrySet = Accessors.getMethodAccessor(multisetClass, "entrySet");
|
||||||
|
private MethodAccessor methodIsEmpty = Accessors.getMethodAccessor(multisetClass, "isEmpty");
|
||||||
|
private MethodAccessor methodIterator = Accessors.getMethodAccessor(multisetClass, "iterator");
|
||||||
|
private MethodAccessor methodRemoveCount = Accessors.getMethodAccessor(multisetClass, "remove", Object.class, int.class);
|
||||||
|
private MethodAccessor methodRemoveOne = Accessors.getMethodAccessor(multisetClass, "remove", Object.class);
|
||||||
|
private MethodAccessor methodRemoveAll = Accessors.getMethodAccessor(multisetClass, "removeAll", Collection.class);
|
||||||
|
private MethodAccessor methodRetainAll = Accessors.getMethodAccessor(multisetClass, "retainAll", Collection.class);
|
||||||
|
private MethodAccessor methodSetCountOldNew = Accessors.getMethodAccessor(multisetClass, "setCount", Object.class, int.class, int.class);
|
||||||
|
private MethodAccessor methodSetCountNew = Accessors.getMethodAccessor(multisetClass, "setCount", Object.class, int.class);
|
||||||
|
private MethodAccessor methodSize = Accessors.getMethodAccessor(multisetClass, "size");
|
||||||
|
private MethodAccessor methodToArray = Accessors.getMethodAccessor(multisetClass, "toArray");
|
||||||
|
private MethodAccessor methodToArrayBuffer = Accessors.getMethodAccessor(multisetClass, "toArray", Object[].class);
|
||||||
|
|
||||||
|
public int add(TValue arg0, int arg1) {
|
||||||
|
return (Integer) methodAddMany.invoke(multiset, arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(TValue arg0) {
|
||||||
|
return (Boolean) methodAddOne.invoke(multiset, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addAll(Collection<? extends TValue> c) {
|
||||||
|
return (Boolean) methodAddAll.invoke(multiset, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
methodClear.invoke(multiset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object arg0) {
|
||||||
|
return (Boolean) methodContains.invoke(multiset, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsAll(Collection<?> arg0) {
|
||||||
|
return (Boolean) methodContainsAll.invoke(multiset, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int count(Object arg0) {
|
||||||
|
return (Integer) methodCount.invoke(multiset, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Set<TValue> elementSet() {
|
||||||
|
return (Set<TValue>) methodElementSet.invoke(multiset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
public Set<Multiset.Entry<TValue>> entrySet() {
|
||||||
|
return new ConvertedSet<
|
||||||
|
Object,
|
||||||
|
Multiset.Entry<TValue>>
|
||||||
|
((Set) methodEntrySet.invoke(multiset)) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected com.google.common.collect.Multiset.Entry<TValue> toOuter(
|
||||||
|
Object inner) {
|
||||||
|
return getBukkitEntry(inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object toInner(
|
||||||
|
com.google.common.collect.Multiset.Entry<TValue> outer) {
|
||||||
|
throw new UnsupportedOperationException("Cannot convert " + outer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object arg0) {
|
||||||
|
return multiset.equals(arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return multiset.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return (Boolean) methodIsEmpty.invoke(multiset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Iterator<TValue> iterator() {
|
||||||
|
return (Iterator<TValue>) methodIterator.invoke(multiset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int remove(Object arg0, int arg1) {
|
||||||
|
return (Integer) methodRemoveCount.invoke(multiset, arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object arg0) {
|
||||||
|
return (Boolean) methodRemoveOne.invoke(multiset, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeAll(Collection<?> arg0) {
|
||||||
|
return (Boolean) methodRemoveAll.invoke(multiset, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean retainAll(Collection<?> arg0) {
|
||||||
|
return (Boolean) methodRetainAll.invoke(multiset, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setCount(TValue arg0, int arg1, int arg2) {
|
||||||
|
return (Boolean) methodSetCountOldNew.invoke(multiset, arg0, arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int setCount(TValue arg0, int arg1) {
|
||||||
|
return (Integer) methodSetCountNew.invoke(multiset, arg0, arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return (Integer) methodSize.invoke(multiset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return (Object[]) methodToArray.invoke(multiset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T[] toArray(T[] a) {
|
||||||
|
return (T[]) methodToArrayBuffer.invoke(multiset, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return multiset.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <TValue> Multiset.Entry<TValue> getBukkitEntry(final Object entry) {
|
||||||
|
return new Multiset.Entry<TValue>() {
|
||||||
|
private Class<?> entryClass = entry.getClass();
|
||||||
|
private MethodAccessor methodEquals = Accessors.getMethodAccessor(entryClass, "equals", Object.class);
|
||||||
|
private MethodAccessor methodGetCount = Accessors.getMethodAccessor(entryClass, "getCount");
|
||||||
|
private MethodAccessor methodGetElement = Accessors.getMethodAccessor(entryClass, "getElement");
|
||||||
|
|
||||||
|
public boolean equals(Object arg0) {
|
||||||
|
return (Boolean) methodEquals.invoke(entry, arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return (Integer) methodGetCount.invoke(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public TValue getElement() {
|
||||||
|
return (TValue) methodGetElement.invoke(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return entry.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return entry.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,8 @@ import com.google.common.collect.Multiset;
|
|||||||
* @author Kristian
|
* @author Kristian
|
||||||
*/
|
*/
|
||||||
class GuavaWrappers {
|
class GuavaWrappers {
|
||||||
|
private static volatile boolean USE_REFLECTION_FALLBACK = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap a Bukkit multimap around Minecraft's internal multimap.
|
* Wrap a Bukkit multimap around Minecraft's internal multimap.
|
||||||
* @param multimap - the multimap to wrap.
|
* @param multimap - the multimap to wrap.
|
||||||
@ -22,7 +24,12 @@ class GuavaWrappers {
|
|||||||
*/
|
*/
|
||||||
public static <TKey, TValue> Multimap<TKey, TValue> getBukkitMultimap(
|
public static <TKey, TValue> Multimap<TKey, TValue> getBukkitMultimap(
|
||||||
final net.minecraft.util.com.google.common.collect.Multimap<TKey, TValue> multimap) {
|
final net.minecraft.util.com.google.common.collect.Multimap<TKey, TValue> multimap) {
|
||||||
return new Multimap<TKey, TValue>() {
|
|
||||||
|
if (USE_REFLECTION_FALLBACK) {
|
||||||
|
return GuavaReflection.getBukkitMultimap(multimap);
|
||||||
|
}
|
||||||
|
|
||||||
|
Multimap<TKey, TValue> result = new Multimap<TKey, TValue>() {
|
||||||
public Map<TKey, Collection<TValue>> asMap() {
|
public Map<TKey, Collection<TValue>> asMap() {
|
||||||
return multimap.asMap();
|
return multimap.asMap();
|
||||||
}
|
}
|
||||||
@ -109,12 +116,23 @@ class GuavaWrappers {
|
|||||||
return multimap.values();
|
return multimap.values();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
result.size(); // Test
|
||||||
|
return result;
|
||||||
|
} catch (LinkageError e) {
|
||||||
|
// Occurs on Cauldron 1.7.10
|
||||||
|
USE_REFLECTION_FALLBACK = true;
|
||||||
|
return GuavaReflection.getBukkitMultimap(multimap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <TValue> Multiset<TValue> getBukkitMultiset(net.minecraft.util.com.google.common.collect.Multiset<TValue> multiset2) {
|
public static <TValue> Multiset<TValue> getBukkitMultiset(final net.minecraft.util.com.google.common.collect.Multiset<TValue> multiset) {
|
||||||
return new Multiset<TValue>() {
|
if (USE_REFLECTION_FALLBACK) {
|
||||||
private net.minecraft.util.com.google.common.collect.Multiset<TValue> multiset;
|
return GuavaReflection.getBukkitMultiset(multiset);
|
||||||
|
}
|
||||||
|
|
||||||
|
Multiset<TValue> result = new Multiset<TValue>() {
|
||||||
public int add(TValue arg0, int arg1) {
|
public int add(TValue arg0, int arg1) {
|
||||||
return multiset.add(arg0, arg1);
|
return multiset.add(arg0, arg1);
|
||||||
}
|
}
|
||||||
@ -223,6 +241,14 @@ class GuavaWrappers {
|
|||||||
return multiset.toString();
|
return multiset.toString();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
result.size(); // Test
|
||||||
|
return result;
|
||||||
|
} catch (LinkageError e) {
|
||||||
|
USE_REFLECTION_FALLBACK = true;
|
||||||
|
return GuavaReflection.getBukkitMultiset(multiset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <TValue> Multiset.Entry<TValue> getBukkitEntry(final net.minecraft.util.com.google.common.collect.Multiset.Entry<TValue> entry) {
|
private static <TValue> Multiset.Entry<TValue> getBukkitEntry(final net.minecraft.util.com.google.common.collect.Multiset.Entry<TValue> entry) {
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren