Archiviert
13
0

Correct a missing noEntryValue in Spigot.

Again.
Dieser Commit ist enthalten in:
Kristian S. Stangeland 2013-12-14 04:39:12 +01:00
Ursprung 9b349299a0
Commit 85d415de7c
5 geänderte Dateien mit 70 neuen und 24 gelöschten Zeilen

Datei anzeigen

@ -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;

Datei anzeigen

@ -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);
}
}
} }

Datei anzeigen

@ -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()));
} }

Datei anzeigen

@ -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);
}
}
} }

Datei anzeigen

@ -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;