From 85d415de7c26d12c0318057af3f1669064344e43 Mon Sep 17 00:00:00 2001 From: "Kristian S. Stangeland" Date: Sat, 14 Dec 2013 04:39:12 +0100 Subject: [PATCH] Correct a missing noEntryValue in Spigot. Again. --- .../injector/netty/NettyProtocolInjector.java | 1 - .../injector/packet/LegacyPacketRegistry.java | 29 ++++------- .../injector/packet/PacketRegistry.java | 4 +- .../protocol/wrappers/TroveWrapper.java | 49 ++++++++++++++++++- .../protocol/wrappers/WrappedDataWatcher.java | 11 ++++- 5 files changed, 70 insertions(+), 24 deletions(-) diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/NettyProtocolInjector.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/NettyProtocolInjector.java index e198dd16..7350da72 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/NettyProtocolInjector.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/NettyProtocolInjector.java @@ -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; diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/LegacyPacketRegistry.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/LegacyPacketRegistry.java index c56d8f5c..6dd07377 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/LegacyPacketRegistry.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/LegacyPacketRegistry.java @@ -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); - - if (value >= 0 && value < 256) { - // Someone forgot to set the no entry value. Let's help them. - FieldUtils.writeField(field, troveMap, -1); + // Fix incorrect no entry values + TroveWrapper.transformNoEntryValue(troveMap, new Function() { + public Integer apply(Integer value) { + if (value >= 0 && value < 256) { + // Someone forgot to set the no entry value. Let's help them. + return -1; + } + return value; } - } catch (IllegalArgumentException e) { - throw new CannotCorrectTroveMapException(e); - } + }); // 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); - } - } } diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/PacketRegistry.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/PacketRegistry.java index 32f54e86..2168836b 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/PacketRegistry.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/packet/PacketRegistry.java @@ -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())); } diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/TroveWrapper.java b/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/TroveWrapper.java index 52284f97..08132b1e 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/TroveWrapper.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/TroveWrapper.java @@ -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 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 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); + } + } } diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/WrappedDataWatcher.java b/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/WrappedDataWatcher.java index 4d403a57..bf66f630 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/WrappedDataWatcher.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/wrappers/WrappedDataWatcher.java @@ -598,7 +598,16 @@ public class WrappedDataWatcher extends AbstractWrapper implements Iterable() { + @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;