mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2024-11-09 12:20:16 +01:00
Correct a missing noEntryValue in Spigot.
Again.
This commit is contained in:
parent
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.reflect.FuzzyReflection;
|
||||
import com.comphenix.protocol.reflect.VolatileField;
|
||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
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.wrappers.TroveWrapper;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
@ -164,18 +165,16 @@ class LegacyPacketRegistry {
|
||||
FuzzyFieldContract.newBuilder().typeMatches(mapLike).build());
|
||||
Object troveMap = FieldUtils.readStaticField(packetsField, true);
|
||||
|
||||
// Check for stupid no_entry_values
|
||||
try {
|
||||
Field field = FieldUtils.getField(troveMap.getClass(), "no_entry_value", true);
|
||||
Integer value = (Integer) FieldUtils.readField(field, troveMap, true);
|
||||
|
||||
// Fix incorrect no entry values
|
||||
TroveWrapper.transformNoEntryValue(troveMap, new Function<Integer, Integer>() {
|
||||
public Integer apply(Integer value) {
|
||||
if (value >= 0 && value < 256) {
|
||||
// Someone forgot to set the no entry value. Let's help them.
|
||||
FieldUtils.writeField(field, troveMap, -1);
|
||||
return -1;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new CannotCorrectTroveMapException(e);
|
||||
return value;
|
||||
}
|
||||
});
|
||||
|
||||
// We'll assume this a Trove map
|
||||
return TroveWrapper.getDecoratedMap(troveMap);
|
||||
@ -333,12 +332,4 @@ class LegacyPacketRegistry {
|
||||
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.ReportType;
|
||||
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.reflect.FieldAccessException;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.TroveWrapper.CannotFindTroveNoEntryValue;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
@ -119,7 +119,7 @@ public class PacketRegistry {
|
||||
PacketRegistry.class, Report.newBuilder(REPORT_INSUFFICIENT_SERVER_PACKETS).messageParam(e.getPacketCount())
|
||||
);
|
||||
}
|
||||
} catch (CannotCorrectTroveMapException e) {
|
||||
} catch (CannotFindTroveNoEntryValue e) {
|
||||
ProtocolLibrary.getErrorReporter().reportWarning(PacketRegistry.class,
|
||||
Report.newBuilder(REPORT_CANNOT_CORRECT_TROVE_MAP).error(e.getCause()));
|
||||
}
|
||||
|
@ -10,11 +10,13 @@ import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
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.ReadOnlyFieldAccessor;
|
||||
import com.comphenix.protocol.reflect.fuzzy.AbstractFuzzyMatcher;
|
||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers;
|
||||
import com.comphenix.protocol.utility.ClassSource;
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* Wrap a GNU Trove Collection class with an equivalent Java Collection class.
|
||||
@ -38,9 +40,24 @@ public class TroveWrapper {
|
||||
* @return The read only 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() {
|
||||
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() {
|
||||
return accessor.getField();
|
||||
@ -131,6 +148,28 @@ public class TroveWrapper {
|
||||
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.
|
||||
* @param clazz - the class source.
|
||||
@ -189,4 +228,12 @@ public class TroveWrapper {
|
||||
|
||||
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)) {
|
||||
// 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())) {
|
||||
TYPE_MAP_ACCESSOR = accessor;
|
||||
|
Loading…
Reference in New Issue
Block a user