Correct a missing noEntryValue in Spigot.
Again.
Dieser Commit ist enthalten in:
Ursprung
9b349299a0
Commit
85d415de7c
@ -35,7 +35,6 @@ import com.comphenix.protocol.injector.spigot.AbstractPacketInjector;
|
|||||||
import com.comphenix.protocol.injector.spigot.AbstractPlayerHandler;
|
import com.comphenix.protocol.injector.spigot.AbstractPlayerHandler;
|
||||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
import com.comphenix.protocol.reflect.VolatileField;
|
import com.comphenix.protocol.reflect.VolatileField;
|
||||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
|
||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
|||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
import com.comphenix.protocol.wrappers.TroveWrapper;
|
import com.comphenix.protocol.wrappers.TroveWrapper;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
@ -164,18 +165,16 @@ class LegacyPacketRegistry {
|
|||||||
FuzzyFieldContract.newBuilder().typeMatches(mapLike).build());
|
FuzzyFieldContract.newBuilder().typeMatches(mapLike).build());
|
||||||
Object troveMap = FieldUtils.readStaticField(packetsField, true);
|
Object troveMap = FieldUtils.readStaticField(packetsField, true);
|
||||||
|
|
||||||
// Check for stupid no_entry_values
|
// Fix incorrect no entry values
|
||||||
try {
|
TroveWrapper.transformNoEntryValue(troveMap, new Function<Integer, Integer>() {
|
||||||
Field field = FieldUtils.getField(troveMap.getClass(), "no_entry_value", true);
|
public Integer apply(Integer value) {
|
||||||
Integer value = (Integer) FieldUtils.readField(field, troveMap, true);
|
if (value >= 0 && value < 256) {
|
||||||
|
// Someone forgot to set the no entry value. Let's help them.
|
||||||
if (value >= 0 && value < 256) {
|
return -1;
|
||||||
// Someone forgot to set the no entry value. Let's help them.
|
}
|
||||||
FieldUtils.writeField(field, troveMap, -1);
|
return value;
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
});
|
||||||
throw new CannotCorrectTroveMapException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We'll assume this a Trove map
|
// We'll assume this a Trove map
|
||||||
return TroveWrapper.getDecoratedMap(troveMap);
|
return TroveWrapper.getDecoratedMap(troveMap);
|
||||||
@ -333,12 +332,4 @@ class LegacyPacketRegistry {
|
|||||||
return packetCount;
|
return packetCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CannotCorrectTroveMapException extends RuntimeException {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
private CannotCorrectTroveMapException(Throwable inner) {
|
|
||||||
super("Cannot correct trove map.", inner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,10 @@ import com.comphenix.protocol.ProtocolLibrary;
|
|||||||
import com.comphenix.protocol.error.Report;
|
import com.comphenix.protocol.error.Report;
|
||||||
import com.comphenix.protocol.error.ReportType;
|
import com.comphenix.protocol.error.ReportType;
|
||||||
import com.comphenix.protocol.injector.netty.NettyProtocolRegistry;
|
import com.comphenix.protocol.injector.netty.NettyProtocolRegistry;
|
||||||
import com.comphenix.protocol.injector.packet.LegacyPacketRegistry.CannotCorrectTroveMapException;
|
|
||||||
import com.comphenix.protocol.injector.packet.LegacyPacketRegistry.InsufficientPacketsException;
|
import com.comphenix.protocol.injector.packet.LegacyPacketRegistry.InsufficientPacketsException;
|
||||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
|
import com.comphenix.protocol.wrappers.TroveWrapper.CannotFindTroveNoEntryValue;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
@ -119,7 +119,7 @@ public class PacketRegistry {
|
|||||||
PacketRegistry.class, Report.newBuilder(REPORT_INSUFFICIENT_SERVER_PACKETS).messageParam(e.getPacketCount())
|
PacketRegistry.class, Report.newBuilder(REPORT_INSUFFICIENT_SERVER_PACKETS).messageParam(e.getPacketCount())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (CannotCorrectTroveMapException e) {
|
} catch (CannotFindTroveNoEntryValue e) {
|
||||||
ProtocolLibrary.getErrorReporter().reportWarning(PacketRegistry.class,
|
ProtocolLibrary.getErrorReporter().reportWarning(PacketRegistry.class,
|
||||||
Report.newBuilder(REPORT_CANNOT_CORRECT_TROVE_MAP).error(e.getCause()));
|
Report.newBuilder(REPORT_CANNOT_CORRECT_TROVE_MAP).error(e.getCause()));
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,13 @@ import java.util.Set;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||||
|
import com.comphenix.protocol.reflect.FieldUtils;
|
||||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||||
import com.comphenix.protocol.reflect.accessors.ReadOnlyFieldAccessor;
|
import com.comphenix.protocol.reflect.accessors.ReadOnlyFieldAccessor;
|
||||||
import com.comphenix.protocol.reflect.fuzzy.AbstractFuzzyMatcher;
|
import com.comphenix.protocol.reflect.fuzzy.AbstractFuzzyMatcher;
|
||||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers;
|
import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers;
|
||||||
import com.comphenix.protocol.utility.ClassSource;
|
import com.comphenix.protocol.utility.ClassSource;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap a GNU Trove Collection class with an equivalent Java Collection class.
|
* Wrap a GNU Trove Collection class with an equivalent Java Collection class.
|
||||||
@ -38,9 +40,24 @@ public class TroveWrapper {
|
|||||||
* @return The read only accessor.
|
* @return The read only accessor.
|
||||||
*/
|
*/
|
||||||
public static ReadOnlyFieldAccessor wrapMapField(final FieldAccessor accessor) {
|
public static ReadOnlyFieldAccessor wrapMapField(final FieldAccessor accessor) {
|
||||||
|
return wrapMapField(accessor, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a read-only field accessor that automatically wraps the underlying Trove instance.
|
||||||
|
* @param accessor - the accessor.
|
||||||
|
* @param noEntryTransform - transform the no entry value, or NULL to ignore.
|
||||||
|
* @return The read only accessor.
|
||||||
|
*/
|
||||||
|
public static ReadOnlyFieldAccessor wrapMapField(final FieldAccessor accessor, final Function<Integer, Integer> noEntryTransform) {
|
||||||
return new ReadOnlyFieldAccessor() {
|
return new ReadOnlyFieldAccessor() {
|
||||||
public Object get(Object instance) {
|
public Object get(Object instance) {
|
||||||
return getDecoratedMap(accessor.get(instance));
|
Object troveMap = accessor.get(instance);
|
||||||
|
|
||||||
|
// Apply transform as well
|
||||||
|
if (noEntryTransform != null)
|
||||||
|
TroveWrapper.transformNoEntryValue(troveMap, noEntryTransform);
|
||||||
|
return getDecoratedMap(troveMap);
|
||||||
}
|
}
|
||||||
public Field getField() {
|
public Field getField() {
|
||||||
return accessor.getField();
|
return accessor.getField();
|
||||||
@ -131,6 +148,28 @@ public class TroveWrapper {
|
|||||||
return getClassSource(clazz) != null;
|
return getClassSource(clazz) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform the no entry value in the given map.
|
||||||
|
* @param troveMap - the trove map.
|
||||||
|
* @param transform - the transform.
|
||||||
|
*/
|
||||||
|
public static void transformNoEntryValue(Object troveMap, Function<Integer, Integer> transform) {
|
||||||
|
// Check for stupid no_entry_values
|
||||||
|
try {
|
||||||
|
Field field = FieldUtils.getField(troveMap.getClass(), "no_entry_value", true);
|
||||||
|
int current = (Integer) FieldUtils.readField(field, troveMap, true);
|
||||||
|
int transformed = transform.apply(current);
|
||||||
|
|
||||||
|
if (current != transformed) {
|
||||||
|
FieldUtils.writeField(field, troveMap, transformed);
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new CannotFindTroveNoEntryValue(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalStateException("Cannot access reflection.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the correct class source from the given class.
|
* Retrieve the correct class source from the given class.
|
||||||
* @param clazz - the class source.
|
* @param clazz - the class source.
|
||||||
@ -189,4 +228,12 @@ public class TroveWrapper {
|
|||||||
|
|
||||||
throw new IllegalArgumentException("Cannot find decorator for " + trove + " (" + trove.getClass() + ")");
|
throw new IllegalArgumentException("Cannot find decorator for " + trove + " (" + trove.getClass() + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CannotFindTroveNoEntryValue extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private CannotFindTroveNoEntryValue(Throwable inner) {
|
||||||
|
super("Cannot correct trove map.", inner);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -598,7 +598,16 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable<Wrap
|
|||||||
|
|
||||||
if (TroveWrapper.isTroveClass(type)) {
|
if (TroveWrapper.isTroveClass(type)) {
|
||||||
// Create a wrapper accessor
|
// Create a wrapper accessor
|
||||||
final ReadOnlyFieldAccessor accessor = TroveWrapper.wrapMapField(Accessors.getFieldAccessor(lookup, true));
|
final ReadOnlyFieldAccessor accessor = TroveWrapper.wrapMapField(
|
||||||
|
Accessors.getFieldAccessor(lookup, true), new Function<Integer, Integer>() {
|
||||||
|
@Override
|
||||||
|
public Integer apply(@Nullable Integer value) {
|
||||||
|
// Do not use zero for no entry value
|
||||||
|
if (value == 0)
|
||||||
|
return -1;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (Modifier.isStatic(lookup.getModifiers())) {
|
if (Modifier.isStatic(lookup.getModifiers())) {
|
||||||
TYPE_MAP_ACCESSOR = accessor;
|
TYPE_MAP_ACCESSOR = accessor;
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren