From 9e5bdf41240b8b6e6f579a90e52fe56a68f40509 Mon Sep 17 00:00:00 2001 From: Dan Mulloy Date: Mon, 24 Jul 2017 14:15:56 -0400 Subject: [PATCH] Major rework of underlying conversion logic This shouldn't affect plugins utlilizing the API, but will make updates and adding wrappers to PacketWrapper easier. In case you're wondering, major changes include: - Added AutoWrapper - Added Covnerters utility class - Removed generic type parameter from EquivalentConverter --- .../protocol/events/PacketContainer.java | 321 ++++---- .../protocol/reflect/EquivalentConverter.java | 30 +- .../protocol/reflect/GenericConverter.java | 33 + .../protocol/reflect/SpecificConverter.java | 33 + .../protocol/reflect/StructureModifier.java | 2 +- .../reflect/cloning/BukkitCloner.java | 12 +- .../compiler/CompiledStructureModifier.java | 2 +- .../protocol/wrappers/AutoWrapper.java | 163 ++++ .../protocol/wrappers/BlockPosition.java | 4 +- .../protocol/wrappers/BukkitConverters.java | 722 ++++++++---------- .../protocol/wrappers/ChunkCoordIntPair.java | 2 +- .../protocol/wrappers/ChunkPosition.java | 4 +- .../protocol/wrappers/Converters.java | 106 +++ .../protocol/wrappers/EnumWrappers.java | 57 +- .../protocol/wrappers/MinecraftKey.java | 2 +- .../wrappers/MultiBlockChangeInfo.java | 10 +- .../protocol/wrappers/PlayerInfoData.java | 6 +- .../comphenix/protocol/wrappers/Vector3F.java | 11 +- .../protocol/wrappers/WrappedServerPing.java | 2 +- .../wrappers/WrappedWatchableObject.java | 12 +- .../protocol/BukkitInitialization.java | 2 + .../wrappers/ChunkCoordIntPairTest.java | 2 +- .../protocol/wrappers/EnumWrappersTest.java | 1 - .../wrappers/MultiBlockChangeTest.java | 2 +- .../protocol/wrappers/PlayerInfoDataTest.java | 2 +- .../wrappers/WrappedBlockDataTest.java | 2 +- pom.xml | 4 +- 27 files changed, 887 insertions(+), 662 deletions(-) create mode 100644 modules/API/src/main/java/com/comphenix/protocol/reflect/GenericConverter.java create mode 100644 modules/API/src/main/java/com/comphenix/protocol/reflect/SpecificConverter.java create mode 100644 modules/API/src/main/java/com/comphenix/protocol/wrappers/AutoWrapper.java create mode 100644 modules/API/src/main/java/com/comphenix/protocol/wrappers/Converters.java diff --git a/modules/API/src/main/java/com/comphenix/protocol/events/PacketContainer.java b/modules/API/src/main/java/com/comphenix/protocol/events/PacketContainer.java index 0575cae0..0073be3e 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/events/PacketContainer.java +++ b/modules/API/src/main/java/com/comphenix/protocol/events/PacketContainer.java @@ -69,11 +69,7 @@ import com.comphenix.protocol.reflect.instances.DefaultInstances; import com.comphenix.protocol.utility.MinecraftMethods; import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.utility.StreamSerializer; -import com.comphenix.protocol.wrappers.BlockPosition; -import com.comphenix.protocol.wrappers.BukkitConverters; -import com.comphenix.protocol.wrappers.ChunkCoordIntPair; -import com.comphenix.protocol.wrappers.ChunkPosition; -import com.comphenix.protocol.wrappers.EnumWrappers; +import com.comphenix.protocol.wrappers.*; import com.comphenix.protocol.wrappers.EnumWrappers.ChatType; import com.comphenix.protocol.wrappers.EnumWrappers.ChatVisibility; import com.comphenix.protocol.wrappers.EnumWrappers.ClientCommand; @@ -94,16 +90,6 @@ import com.comphenix.protocol.wrappers.EnumWrappers.ScoreboardAction; import com.comphenix.protocol.wrappers.EnumWrappers.SoundCategory; import com.comphenix.protocol.wrappers.EnumWrappers.TitleAction; import com.comphenix.protocol.wrappers.EnumWrappers.WorldBorderAction; -import com.comphenix.protocol.wrappers.MultiBlockChangeInfo; -import com.comphenix.protocol.wrappers.PlayerInfoData; -import com.comphenix.protocol.wrappers.WrappedAttribute; -import com.comphenix.protocol.wrappers.WrappedBlockData; -import com.comphenix.protocol.wrappers.WrappedChatComponent; -import com.comphenix.protocol.wrappers.WrappedDataWatcher; -import com.comphenix.protocol.wrappers.WrappedGameProfile; -import com.comphenix.protocol.wrappers.WrappedServerPing; -import com.comphenix.protocol.wrappers.WrappedStatistic; -import com.comphenix.protocol.wrappers.WrappedWatchableObject; import com.comphenix.protocol.wrappers.nbt.NbtBase; import com.comphenix.protocol.wrappers.nbt.NbtCompound; import com.comphenix.protocol.wrappers.nbt.NbtFactory; @@ -134,30 +120,29 @@ public class PacketContainer implements Serializable { private static ConcurrentMap, Method> readMethods = Maps.newConcurrentMap(); // Used to clone packets - private static final AggregateCloner DEEP_CLONER = AggregateCloner.newBuilder(). - instanceProvider(DefaultInstances.DEFAULT). - andThen(BukkitCloner.class). - andThen(ImmutableDetector.class). - andThen(OptionalCloner.class). - andThen(CollectionCloner.class). - andThen(getSpecializedDeepClonerFactory()). - build(); + private static final AggregateCloner DEEP_CLONER = AggregateCloner + .newBuilder() + .instanceProvider(DefaultInstances.DEFAULT) + .andThen(BukkitCloner.class) + .andThen(ImmutableDetector.class) + .andThen(OptionalCloner.class) + .andThen(CollectionCloner.class) + .andThen(getSpecializedDeepClonerFactory()) + .build(); - private static final AggregateCloner SHALLOW_CLONER = AggregateCloner.newBuilder(). - instanceProvider(DefaultInstances.DEFAULT). - andThen(new Function() { - @Override - public Cloner apply(@Nullable BuilderParameters param) { - if (param == null) - throw new IllegalArgumentException("Cannot be NULL."); - - return new FieldCloner(param.getAggregateCloner(), param.getInstanceProvider()) {{ - // Use a default writer with no concept of cloning - writer = new ObjectWriter(); - }}; - } - }). - build(); + private static final AggregateCloner SHALLOW_CLONER = AggregateCloner + .newBuilder() + .instanceProvider(DefaultInstances.DEFAULT) + .andThen(param -> { + if (param == null) + throw new IllegalArgumentException("Cannot be NULL."); + + return new FieldCloner(param.getAggregateCloner(), param.getInstanceProvider()) {{ + // Use a default writer with no concept of cloning + writer = new ObjectWriter(); + }}; + }) + .build(); // Packets that cannot be cloned by our default deep cloner private static final Set CLONING_UNSUPPORTED = Sets.newHashSet( @@ -385,8 +370,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getItemModifier() { // Convert to and from the Bukkit wrapper - return structureModifier.withType( - MinecraftReflection.getItemStackClass(), BukkitConverters.getItemStackConverter()); + return structureModifier.withType( + MinecraftReflection.getItemStackClass(), + BukkitConverters.getItemStackConverter()); } /** @@ -398,9 +384,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getItemArrayModifier() { // Convert to and from the Bukkit wrapper - return structureModifier.withType( + return structureModifier.withType( MinecraftReflection.getItemStackArrayClass(), - BukkitConverters.getIgnoreNull(new ItemStackArrayConverter())); + Converters.ignoreNull(new ItemStackArrayConverter())); } /** @@ -414,10 +400,7 @@ public class PacketContainer implements Serializable { // Convert to and from the Bukkit wrapper return structureModifier.withType( List.class, - BukkitConverters.getListConverter( - MinecraftReflection.getItemStackClass(), - BukkitConverters.getItemStackConverter() - ) + BukkitConverters.getListConverter(BukkitConverters.getItemStackConverter()) ); } @@ -428,12 +411,9 @@ public class PacketContainer implements Serializable { * @return A modifier for maps of statistics. */ public StructureModifier> getStatisticMaps() { - return structureModifier.withType(Map.class, - BukkitConverters.getMapConverter( - MinecraftReflection.getStatisticClass(), - BukkitConverters.getWrappedStatisticConverter() - ) - ); + return getMaps( + BukkitConverters.getWrappedStatisticConverter(), + Converters.passthrough(Integer.class)); } /** @@ -445,7 +425,7 @@ public class PacketContainer implements Serializable { */ public StructureModifier getWorldTypeModifier() { // Convert to and from the Bukkit wrapper - return structureModifier.withType( + return structureModifier.withType( MinecraftReflection.getWorldTypeClass(), BukkitConverters.getWorldTypeConverter()); } @@ -456,7 +436,7 @@ public class PacketContainer implements Serializable { */ public StructureModifier getDataWatcherModifier() { // Convert to and from the Bukkit wrapper - return structureModifier.withType( + return structureModifier.withType( MinecraftReflection.getDataWatcherClass(), BukkitConverters.getDataWatcherConverter()); } @@ -475,7 +455,7 @@ public class PacketContainer implements Serializable { public StructureModifier getEntityModifier(@Nonnull World world) { Preconditions.checkNotNull(world, "world cannot be NULL."); // Convert to and from the Bukkit wrapper - return structureModifier.withType( + return structureModifier.withType( int.class, BukkitConverters.getEntityConverter(world)); } @@ -547,10 +527,7 @@ public class PacketContainer implements Serializable { // Convert to and from the ProtocolLib wrapper return structureModifier.withType( Collection.class, - BukkitConverters.getListConverter( - MinecraftReflection.getNBTBaseClass(), - BukkitConverters.getNbtConverter() - ) + BukkitConverters.getListConverter(BukkitConverters.getNbtConverter()) ); } @@ -576,9 +553,7 @@ public class PacketContainer implements Serializable { // Convert to and from the ProtocolLib wrapper return structureModifier.withType( Collection.class, - BukkitConverters.getListConverter( - MinecraftReflection.getAttributeSnapshotClass(), - BukkitConverters.getWrappedAttributeConverter()) + BukkitConverters.getListConverter(BukkitConverters.getWrappedAttributeConverter()) ); } @@ -594,10 +569,7 @@ public class PacketContainer implements Serializable { // Convert to and from the ProtocolLib wrapper return structureModifier.withType( Collection.class, - BukkitConverters.getListConverter( - MinecraftReflection.getChunkPositionClass(), - ChunkPosition.getConverter()) - ); + BukkitConverters.getListConverter(ChunkPosition.getConverter())); } /** @@ -612,10 +584,7 @@ public class PacketContainer implements Serializable { // Convert to and from the ProtocolLib wrapper return structureModifier.withType( Collection.class, - BukkitConverters.getListConverter( - MinecraftReflection.getBlockPositionClass(), - BlockPosition.getConverter()) - ); + BukkitConverters.getListConverter(BlockPosition.getConverter())); } /** @@ -629,10 +598,7 @@ public class PacketContainer implements Serializable { // Convert to and from the ProtocolLib wrapper return structureModifier.withType( Collection.class, - BukkitConverters.getListConverter( - MinecraftReflection.getDataWatcherItemClass(), - BukkitConverters.getWatchableObjectConverter()) - ); + BukkitConverters.getListConverter(BukkitConverters.getWatchableObjectConverter())); } /** @@ -644,7 +610,7 @@ public class PacketContainer implements Serializable { */ public StructureModifier getBlocks() { // Convert to and from the Bukkit wrapper - return structureModifier.withType( + return structureModifier.withType( MinecraftReflection.getBlockClass(), BukkitConverters.getBlockConverter()); } @@ -657,7 +623,7 @@ public class PacketContainer implements Serializable { */ public StructureModifier getGameProfiles() { // Convert to and from the Bukkit wrapper - return structureModifier.withType( + return structureModifier.withType( MinecraftReflection.getGameProfileClass(), BukkitConverters.getWrappedGameProfileConverter()); } @@ -670,7 +636,7 @@ public class PacketContainer implements Serializable { */ public StructureModifier getBlockData() { // Convert to and from our wrapper - return structureModifier.withType( + return structureModifier.withType( MinecraftReflection.getIBlockDataClass(), BukkitConverters.getWrappedBlockDataConverter()); } @@ -685,7 +651,7 @@ public class PacketContainer implements Serializable { ChunkCoordIntPair chunk = getChunkCoordIntPairs().read(0); // Convert to and from our wrapper - return structureModifier.withType( + return structureModifier.withType( MinecraftReflection.getMultiBlockChangeInfoArrayClass(), MultiBlockChangeInfo.getArrayConverter(chunk)); } @@ -698,7 +664,7 @@ public class PacketContainer implements Serializable { */ public StructureModifier getChatComponents() { // Convert to and from the Bukkit wrapper - return structureModifier.withType( + return structureModifier.withType( MinecraftReflection.getIChatBaseComponentClass(), BukkitConverters.getWrappedChatComponentConverter()); } @@ -715,22 +681,23 @@ public class PacketContainer implements Serializable { */ public StructureModifier getChatComponentArrays() { // Convert to and from the Bukkit wrapper - return structureModifier.withType( + return structureModifier.withType( ComponentArrayConverter.getGenericType(), - BukkitConverters.getIgnoreNull(new ComponentArrayConverter())); + Converters.ignoreNull(new ComponentArrayConverter())); } /** * Retrieve a read/write structure for the ServerPing fields in the following packet:
*
    - *
  • {@link PacketType.Status.Server#OUT_SERVER_INFO} + *
  • {@link PacketType.Status.Server#SERVER_INFO} *
* @return A modifier for ServerPing fields. */ public StructureModifier getServerPings() { // Convert to and from the wrapper - return structureModifier.withType( - MinecraftReflection.getServerPingClass(), BukkitConverters.getWrappedServerPingConverter()); + return structureModifier.withType( + MinecraftReflection.getServerPingClass(), + BukkitConverters.getWrappedServerPingConverter()); } /** @@ -744,10 +711,7 @@ public class PacketContainer implements Serializable { // Convert to and from the ProtocolLib wrapper return structureModifier.withType( Collection.class, - BukkitConverters.getListConverter( - MinecraftReflection.getPlayerInfoDataClass(), - PlayerInfoData.getConverter()) - ); + BukkitConverters.getListConverter(PlayerInfoData.getConverter())); } /** @@ -756,8 +720,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getProtocols() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getProtocolClass(), EnumWrappers.getProtocolConverter()); + return structureModifier.withType( + EnumWrappers.getProtocolClass(), + EnumWrappers.getProtocolConverter()); } /** @@ -766,8 +731,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getClientCommands() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getClientCommandClass(), EnumWrappers.getClientCommandConverter()); + return structureModifier.withType( + EnumWrappers.getClientCommandClass(), + EnumWrappers.getClientCommandConverter()); } /** @@ -776,8 +742,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getChatVisibilities() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getChatVisibilityClass(), EnumWrappers.getChatVisibilityConverter()); + return structureModifier.withType( + EnumWrappers.getChatVisibilityClass(), + EnumWrappers.getChatVisibilityConverter()); } /** @@ -786,8 +753,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getDifficulties() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getDifficultyClass(), EnumWrappers.getDifficultyConverter()); + return structureModifier.withType( + EnumWrappers.getDifficultyClass(), + EnumWrappers.getDifficultyConverter()); } /** @@ -796,8 +764,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getEntityUseActions() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getEntityUseActionClass(), EnumWrappers.getEntityUseActionConverter()); + return structureModifier.withType( + EnumWrappers.getEntityUseActionClass(), + EnumWrappers.getEntityUseActionConverter()); } /** @@ -806,8 +775,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getGameModes() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getGameModeClass(), EnumWrappers.getGameModeConverter()); + return structureModifier.withType( + EnumWrappers.getGameModeClass(), + EnumWrappers.getGameModeConverter()); } /** @@ -816,8 +786,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getResourcePackStatus() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getResourcePackStatusClass(), EnumWrappers.getResourcePackStatusConverter()); + return structureModifier.withType( + EnumWrappers.getResourcePackStatusClass(), + EnumWrappers.getResourcePackStatusConverter()); } /** @@ -826,8 +797,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getPlayerInfoAction() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getPlayerInfoActionClass(), EnumWrappers.getPlayerInfoActionConverter()); + return structureModifier.withType( + EnumWrappers.getPlayerInfoActionClass(), + EnumWrappers.getPlayerInfoActionConverter()); } /** @@ -836,8 +808,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getTitleActions() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getTitleActionClass(), EnumWrappers.getTitleActionConverter()); + return structureModifier.withType( + EnumWrappers.getTitleActionClass(), + EnumWrappers.getTitleActionConverter()); } /** @@ -846,8 +819,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getWorldBorderActions() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getWorldBorderActionClass(), EnumWrappers.getWorldBorderActionConverter()); + return structureModifier.withType( + EnumWrappers.getWorldBorderActionClass(), + EnumWrappers.getWorldBorderActionConverter()); } /** @@ -856,8 +830,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getCombatEvents() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getCombatEventTypeClass(), EnumWrappers.getCombatEventTypeConverter()); + return structureModifier.withType( + EnumWrappers.getCombatEventTypeClass(), + EnumWrappers.getCombatEventTypeConverter()); } /** @@ -866,8 +841,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getPlayerDigTypes() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getPlayerDigTypeClass(), EnumWrappers.getPlayerDiggingActionConverter()); + return structureModifier.withType( + EnumWrappers.getPlayerDigTypeClass(), + EnumWrappers.getPlayerDiggingActionConverter()); } /** @@ -876,8 +852,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getPlayerActions() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getPlayerActionClass(), EnumWrappers.getEntityActionConverter()); + return structureModifier.withType( + EnumWrappers.getPlayerActionClass(), + EnumWrappers.getEntityActionConverter()); } /** @@ -886,8 +863,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getScoreboardActions() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getScoreboardActionClass(), EnumWrappers.getUpdateScoreActionConverter()); + return structureModifier.withType( + EnumWrappers.getScoreboardActionClass(), + EnumWrappers.getUpdateScoreActionConverter()); } /** @@ -896,8 +874,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getParticles() { // Convert to and from the wrapper - return structureModifier.withType( - EnumWrappers.getParticleClass(), EnumWrappers.getParticleConverter()); + return structureModifier.withType( + EnumWrappers.getParticleClass(), + EnumWrappers.getParticleConverter()); } /** @@ -906,8 +885,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getEffectTypes() { // Convert to and from Bukkit - return structureModifier.withType( - MinecraftReflection.getMobEffectListClass(), BukkitConverters.getEffectTypeConverter()); + return structureModifier.withType( + MinecraftReflection.getMobEffectListClass(), + BukkitConverters.getEffectTypeConverter()); } /** @@ -916,8 +896,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getSoundCategories() { // Convert to and from the enums - return structureModifier.withType( - EnumWrappers.getSoundCategoryClass(), EnumWrappers.getSoundCategoryConverter()); + return structureModifier.withType( + EnumWrappers.getSoundCategoryClass(), + EnumWrappers.getSoundCategoryConverter()); } /** @@ -926,8 +907,9 @@ public class PacketContainer implements Serializable { */ public StructureModifier getSoundEffects() { // Convert to and from Bukkit - return structureModifier.withType( - MinecraftReflection.getSoundEffectClass(), BukkitConverters.getSoundConverter()); + return structureModifier.withType( + MinecraftReflection.getSoundEffectClass(), + BukkitConverters.getSoundConverter()); } /** @@ -935,8 +917,9 @@ public class PacketContainer implements Serializable { * @return A modifier for ItemSlot enum fields. */ public StructureModifier getItemSlots() { - return structureModifier.withType( - EnumWrappers.getItemSlotClass(), EnumWrappers.getItemSlotConverter()); + return structureModifier.withType( + EnumWrappers.getItemSlotClass(), + EnumWrappers.getItemSlotConverter()); } /** @@ -944,8 +927,9 @@ public class PacketContainer implements Serializable { * @return A modifier for Hand enum fields. */ public StructureModifier getHands() { - return structureModifier.withType( - EnumWrappers.getHandClass(), EnumWrappers.getHandConverter()); + return structureModifier.withType( + EnumWrappers.getHandClass(), + EnumWrappers.getHandConverter()); } /** @@ -953,8 +937,9 @@ public class PacketContainer implements Serializable { * @return A modifier for Direction enum fields. */ public StructureModifier getDirections() { - return structureModifier.withType( - EnumWrappers.getDirectionClass(), EnumWrappers.getDirectionConverter()); + return structureModifier.withType( + EnumWrappers.getDirectionClass(), + EnumWrappers.getDirectionConverter()); } /** @@ -962,8 +947,52 @@ public class PacketContainer implements Serializable { * @return A modifier for ChatType enum fields. */ public StructureModifier getChatTypes() { - return structureModifier.withType( - EnumWrappers.getChatTypeClass(), EnumWrappers.getChatTypeConverter()); + return structureModifier.withType( + EnumWrappers.getChatTypeClass(), + EnumWrappers.getChatTypeConverter()); + } + + /** + * Retrieve a read/write structure for the MinecraftKey class. + * @return A modifier for MinecraftKey fields. + */ + public StructureModifier getMinecraftKeys() { + return structureModifier.withType( + MinecraftReflection.getMinecraftKeyClass(), + MinecraftKey.getConverter()); + } + + /** + * Retrieve a read/write structure for the Map class. + * @param keyConverter Converter for map keys + * @param valConverter Converter for map values + * @param Key param + * @param Value param + * @return A modifier for Map fields. + * + * @see BukkitConverters + * @see EquivalentConverter + */ + public StructureModifier> getMaps(EquivalentConverter keyConverter, + EquivalentConverter valConverter) { + return structureModifier.withType( + Map.class, + BukkitConverters.getMapConverter(keyConverter, valConverter)); + } + + /** + * Retrieve a read/write structure for the Set class. + * @param converter Converter for elements + * @param Element param + * @return A modifier for Set fields + * + * @see BukkitConverters + * @see EquivalentConverter + */ + public StructureModifier> getSets(EquivalentConverter converter) { + return structureModifier.withType( + Set.class, + BukkitConverters.getSetConverter(converter)); } /** @@ -977,7 +1006,9 @@ public class PacketContainer implements Serializable { * @return The modifier */ public > StructureModifier getEnumModifier(Class enumClass, Class nmsClass) { - return structureModifier.withType(nmsClass, new EnumConverter(enumClass)); + return structureModifier.withType( + nmsClass, + new EnumConverter<>(nmsClass, enumClass)); } /** @@ -990,7 +1021,9 @@ public class PacketContainer implements Serializable { * @see #getEnumModifier(Class, Class) */ public > StructureModifier getEnumModifier(Class enumClass, int index) { - return getEnumModifier(enumClass, structureModifier.getField(index).getType()); + return getEnumModifier( + enumClass, + structureModifier.getField(index).getType()); } /** @@ -1036,7 +1069,7 @@ public class PacketContainer implements Serializable { * @return A deep copy of the current packet. */ public PacketContainer deepClone() { - Object clonedPacket = null; + Object clonedPacket; // Fall back on the alternative (but slower) method of reading and writing back the packet if (CLONING_UNSUPPORTED.contains(type)) { @@ -1183,7 +1216,7 @@ public class PacketContainer implements Serializable { */ public void addMetadata(String key, Object value) { if (metadata == null) { - metadata = new HashMap(); + metadata = new HashMap<>(); } metadata.put(key, value); @@ -1259,13 +1292,13 @@ public class PacketContainer implements Serializable { final EquivalentConverter stackConverter = BukkitConverters.getItemStackConverter(); @Override - public Object getGeneric(ClassgenericType, ItemStack[] specific) { + public Object getGeneric(ItemStack[] specific) { Class nmsStack = MinecraftReflection.getItemStackClass(); Object[] result = (Object[]) Array.newInstance(nmsStack, specific.length); // Unwrap every item for (int i = 0; i < result.length; i++) { - result[i] = stackConverter.getGeneric(nmsStack, specific[i]); + result[i] = stackConverter.getGeneric(specific[i]); } return result; } @@ -1296,13 +1329,13 @@ public class PacketContainer implements Serializable { final EquivalentConverter componentConverter = BukkitConverters.getWrappedChatComponentConverter(); @Override - public Object getGeneric(Class genericType, WrappedChatComponent[] specific) { + public Object getGeneric(WrappedChatComponent[] specific) { Class nmsComponent = MinecraftReflection.getIChatBaseComponentClass(); Object[] result = (Object[]) Array.newInstance(nmsComponent, specific.length); // Unwrap every item for (int i = 0; i < result.length; i++) { - result[i] = componentConverter.getGeneric(nmsComponent, specific[i]); + result[i] = componentConverter.getGeneric(specific[i]); } return result; } @@ -1351,7 +1384,7 @@ public class PacketContainer implements Serializable { } @Override - public Object getGeneric(Class genericType, WrappedChatComponent[] specific) { + public Object getGeneric(WrappedChatComponent[] specific) { NbtCompound compound = NbtFactory.ofCompound(""); for (int i = 0; i < lines; i++) { @@ -1365,7 +1398,7 @@ public class PacketContainer implements Serializable { compound.put("Text" + (i + 1), component.getJson()); } - return nbtConverter.getGeneric(genericType, compound); + return nbtConverter.getGeneric(compound); } @Override @@ -1394,8 +1427,8 @@ public class PacketContainer implements Serializable { } @Override - public Object getGeneric(Class genericType, WrappedChatComponent[] specific) { - return DELEGATE.getGeneric(genericType, specific); + public Object getGeneric(WrappedChatComponent[] specific) { + return DELEGATE.getGeneric(specific); } @Override diff --git a/modules/API/src/main/java/com/comphenix/protocol/reflect/EquivalentConverter.java b/modules/API/src/main/java/com/comphenix/protocol/reflect/EquivalentConverter.java index fef48f24..4a64f52b 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/reflect/EquivalentConverter.java +++ b/modules/API/src/main/java/com/comphenix/protocol/reflect/EquivalentConverter.java @@ -21,32 +21,12 @@ package com.comphenix.protocol.reflect; * Interface that converts generic objects into types and back. * * @author Kristian - * @param The specific type. + * @param The specific type. */ -public interface EquivalentConverter { +public interface EquivalentConverter extends SpecificConverter, GenericConverter { /** - * Retrieve a copy of the specific type using an instance of the generic type. - *

- * This is usually a wrapper type in the Bukkit API. - * @param generic - the generic type. - * @return The new specific type. - */ - public TType getSpecific(Object generic); - - /** - * Retrieve a copy of the generic type from a specific type. - *

- * This is usually a native net.minecraft.server type in Minecraft. - * @param genericType - class or super class of the generic type. - * @param specific - the specific type we need to copy. - * @return A copy of the specific type. - */ - public Object getGeneric(Class genericType, TType specific); - - /** - * Due to type erasion, we need to explicitly keep a reference to the specific type. + * Due to type erasure, we need to explicitly keep a reference to the specific type. * @return The specific type. */ - public Class getSpecificType(); -} - + Class getSpecificType(); +} \ No newline at end of file diff --git a/modules/API/src/main/java/com/comphenix/protocol/reflect/GenericConverter.java b/modules/API/src/main/java/com/comphenix/protocol/reflect/GenericConverter.java new file mode 100644 index 00000000..9451fac4 --- /dev/null +++ b/modules/API/src/main/java/com/comphenix/protocol/reflect/GenericConverter.java @@ -0,0 +1,33 @@ +/** + * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. + * Copyright (C) 2017 Dan Mulloy + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ +package com.comphenix.protocol.reflect; + +/** + * Converts specific objects into generic objects. + * @author Dan + * @param Specific type + */ +public interface GenericConverter { + /** + * Retrieve a copy of the generic type from a specific type. + *

+ * This is usually a native net.minecraft.server type in Minecraft. + * @param specific - the specific type we need to copy. + * @return A copy of the specific type. + */ + Object getGeneric(T specific); +} \ No newline at end of file diff --git a/modules/API/src/main/java/com/comphenix/protocol/reflect/SpecificConverter.java b/modules/API/src/main/java/com/comphenix/protocol/reflect/SpecificConverter.java new file mode 100644 index 00000000..2d39cfae --- /dev/null +++ b/modules/API/src/main/java/com/comphenix/protocol/reflect/SpecificConverter.java @@ -0,0 +1,33 @@ +/** + * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. + * Copyright (C) 2017 Dan Mulloy + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ +package com.comphenix.protocol.reflect; + +/** + * Converts generic objects into specific objects. + * @author Dan + * @param The specific type + */ +public interface SpecificConverter { + /** + * Retrieve a copy of the specific type using an instance of the generic type. + *

+ * This is usually a wrapper type in the Bukkit API or ProtocolLib API. + * @param generic - the generic type. + * @return The new specific type. + */ + T getSpecific(Object generic); +} \ No newline at end of file diff --git a/modules/API/src/main/java/com/comphenix/protocol/reflect/StructureModifier.java b/modules/API/src/main/java/com/comphenix/protocol/reflect/StructureModifier.java index 37902ae5..bcf9cef8 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/reflect/StructureModifier.java +++ b/modules/API/src/main/java/com/comphenix/protocol/reflect/StructureModifier.java @@ -352,7 +352,7 @@ public class StructureModifier { throw new FieldAccessException(String.format("Field index out of bounds. (Index: %s, Size: %s)", fieldIndex, data.size())); // Use the converter, if it exists - Object obj = needConversion() ? converter.getGeneric(getFieldType(fieldIndex), value) : value; + Object obj = needConversion() ? converter.getGeneric(value) : value; try { FieldUtils.writeField(data.get(fieldIndex), target, obj, true); diff --git a/modules/API/src/main/java/com/comphenix/protocol/reflect/cloning/BukkitCloner.java b/modules/API/src/main/java/com/comphenix/protocol/reflect/cloning/BukkitCloner.java index b4931abe..f64b3a9d 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/reflect/cloning/BukkitCloner.java +++ b/modules/API/src/main/java/com/comphenix/protocol/reflect/cloning/BukkitCloner.java @@ -113,24 +113,24 @@ public class BukkitCloner implements Cloner { return MinecraftReflection.getMinecraftItemStack(MinecraftReflection.getBukkitItemStack(source).clone()); case 1: EquivalentConverter dataConverter = BukkitConverters.getDataWatcherConverter(); - return dataConverter.getGeneric(clonableClasses.get(1), dataConverter.getSpecific(source).deepClone()); + return dataConverter.getGeneric(dataConverter.getSpecific(source).deepClone()); case 2: EquivalentConverter blockConverter = BlockPosition.getConverter(); - return blockConverter.getGeneric(clonableClasses.get(2), blockConverter.getSpecific(source)); + return blockConverter.getGeneric(blockConverter.getSpecific(source)); case 3: EquivalentConverter chunkConverter = ChunkPosition.getConverter(); - return chunkConverter.getGeneric(clonableClasses.get(3), chunkConverter.getSpecific(source)); + return chunkConverter.getGeneric(chunkConverter.getSpecific(source)); case 4: EquivalentConverter serverConverter = BukkitConverters.getWrappedServerPingConverter(); - return serverConverter.getGeneric(clonableClasses.get(4), serverConverter.getSpecific(source).deepClone()); + return serverConverter.getGeneric(serverConverter.getSpecific(source).deepClone()); case 5: return source; case 6: EquivalentConverter keyConverter = MinecraftKey.getConverter(); - return keyConverter.getGeneric(clonableClasses.get(6), keyConverter.getSpecific(source)); + return keyConverter.getGeneric(keyConverter.getSpecific(source)); case 7: EquivalentConverter blockDataConverter = BukkitConverters.getWrappedBlockDataConverter(); - return blockDataConverter.getGeneric(clonableClasses.get(7), blockDataConverter.getSpecific(source).deepClone()); + return blockDataConverter.getGeneric(blockDataConverter.getSpecific(source).deepClone()); case 8: return nonNullListCloner().clone(source); default: diff --git a/modules/API/src/main/java/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java b/modules/API/src/main/java/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java index f2365289..61ef12d1 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java +++ b/modules/API/src/main/java/com/comphenix/protocol/reflect/compiler/CompiledStructureModifier.java @@ -110,7 +110,7 @@ public abstract class CompiledStructureModifier extends StructureModifier write(int index, Object value) throws FieldAccessException { if (converter != null) - value = converter.getGeneric(getFieldType(index), value); + value = converter.getGeneric(value); return writeGenerated(index, value); } diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/AutoWrapper.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/AutoWrapper.java new file mode 100644 index 00000000..c0f67d96 --- /dev/null +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/AutoWrapper.java @@ -0,0 +1,163 @@ +/** + * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. + * Copyright (C) 2017 Dan Mulloy + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ +package com.comphenix.protocol.wrappers; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +import com.comphenix.protocol.reflect.EquivalentConverter; + +/** + * Automatically wraps an internal NMS class to a non-versioned, deofbuscated class. + * Requirements: + *
    + *
  • The wrapper must be public
  • + *
  • If the wrapper is an internal class, it must be static
  • + *
  • The wrapper must have one public constructor with no arguments (the default constructor is acceptable)
  • + *
  • The wrapper must have the the same number of fields as the NMS class
  • + *
  • Each field should correspond, in order, to its NMS counterpart
  • + *
  • Non-generic fields must have a converter
  • + *
+ * + * @author dmulloy2 + */ +public class AutoWrapper implements EquivalentConverter { + private Map> wrappers = new HashMap<>(); + private Map> unwrappers = new HashMap<>(); + + private Class wrapperClass; + private Class nmsClass; + + private AutoWrapper(Class wrapperClass, Class nmsClass) { + this.wrapperClass = wrapperClass; + this.nmsClass = nmsClass; + } + + public static AutoWrapper wrap(Class wrapperClass, Class nmsClass) { + return new AutoWrapper<>(wrapperClass, nmsClass); + } + + public AutoWrapper field(int index, Function wrapper, Function unwrapper) { + wrappers.put(index, wrapper); + unwrappers.put(index, unwrapper); + return this; + } + + public AutoWrapper field(int index, EquivalentConverter converter) { + return field(index, converter::getSpecific, specific -> converter.getGeneric(specific)); + } + + public T wrap(Object nmsObject) { + T instance; + + try { + instance = wrapperClass.newInstance(); + } catch (ReflectiveOperationException ex) { + throw new InvalidWrapperException(wrapperClass.getSimpleName() + " is not accessible!", ex); + } + + Field[] wrapperFields = wrapperClass.getDeclaredFields(); + Field[] nmsFields = nmsClass.getDeclaredFields(); + + for (int i = 0; i < wrapperFields.length; i++) { + try { + Field wrapperField = wrapperFields[i]; + + Field nmsField = nmsFields[i]; + if (!nmsField.isAccessible()) + nmsField.setAccessible(true); + + Object value = nmsField.get(nmsObject); + if (wrappers.containsKey(i)) + value = wrappers.get(i).apply(value); + + wrapperField.set(instance, value); + } catch (ReflectiveOperationException ex) { + throw new InvalidWrapperException("Failed to wrap field", ex); + } + } + + return instance; + } + + public Object unwrap(Object wrapper) { + Object instance; + + try { + instance = nmsClass.newInstance(); + } catch (ReflectiveOperationException ex) { + throw new InvalidWrapperException("Failed to construct new " + nmsClass.getSimpleName(), ex); + } + + Field[] wrapperFields = wrapperClass.getDeclaredFields(); + Field[] nmsFields = nmsClass.getDeclaredFields(); + + for (int i = 0; i < wrapperFields.length; i++) { + try { + Field wrapperField = wrapperFields[i]; + + Field nmsField = nmsFields[i]; + if (!nmsField.isAccessible()) + nmsField.setAccessible(true); + if (Modifier.isFinal(nmsField.getModifiers())) + unsetFinal(nmsField); + + Object value = wrapperField.get(wrapper); + if (unwrappers.containsKey(i)) + value = unwrappers.get(i).apply(value); + + nmsField.set(instance, value); + } catch (ReflectiveOperationException ex) { + throw new InvalidWrapperException("Failed to unwrap field", ex); + } + } + + return instance; + } + + private void unsetFinal(Field field) throws ReflectiveOperationException { + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + } + + // ---- Equivalent conversion + + @Override + public T getSpecific(Object generic) { + return wrap(generic); + } + + @Override + public Object getGeneric(Object specific) { + return unwrap(specific); + } + + @Override + public Class getSpecificType() { + return wrapperClass; + } + + public static class InvalidWrapperException extends RuntimeException { + private InvalidWrapperException(String message, Throwable cause) { + super(message, cause); + } + } +} diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/BlockPosition.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/BlockPosition.java index c1a667a2..9ac4b484 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/BlockPosition.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/BlockPosition.java @@ -164,7 +164,7 @@ public class BlockPosition { public static EquivalentConverter getConverter() { return new EquivalentConverter() { @Override - public Object getGeneric(Class genericType, BlockPosition specific) { + public Object getGeneric(BlockPosition specific) { if (blockPositionConstructor == null) { try { blockPositionConstructor = MinecraftReflection.getBlockPositionClass(). @@ -187,7 +187,7 @@ public class BlockPosition { public BlockPosition getSpecific(Object generic) { if (MinecraftReflection.isBlockPosition(generic)) { // Use a structure modifier - intModifier = new StructureModifier(generic.getClass(), null, false).withType(int.class); + intModifier = new StructureModifier<>(generic.getClass(), null, false).withType(int.class); // Damn it all if (intModifier.size() < 3) { diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java index 127a2e4f..acde6ae8 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java @@ -39,7 +39,6 @@ import com.comphenix.protocol.reflect.accessors.Accessors; import com.comphenix.protocol.reflect.accessors.FieldAccessor; import com.comphenix.protocol.reflect.accessors.MethodAccessor; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; -import com.comphenix.protocol.reflect.instances.DefaultInstances; import com.comphenix.protocol.utility.MinecraftReflection; import com.comphenix.protocol.wrappers.nbt.NbtBase; import com.comphenix.protocol.wrappers.nbt.NbtCompound; @@ -48,23 +47,27 @@ import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.World; import org.bukkit.WorldType; +import org.bukkit.advancement.Advancement; import org.bukkit.entity.Entity; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; +import static com.comphenix.protocol.utility.MinecraftReflection.*; +import static com.comphenix.protocol.wrappers.Converters.*; + /** * Contains several useful equivalent converters for normal Bukkit types. * * @author Kristian */ +@SuppressWarnings("unchecked") public class BukkitConverters { // Check whether or not certain classes exists private static boolean hasWorldType = false; @@ -118,23 +121,24 @@ public class BukkitConverters { * * @author Kristian * @param - type that can be converted. + * @deprecated Replaced by {@link Converters#ignoreNull(EquivalentConverter)} */ + @Deprecated public static abstract class IgnoreNullConverter implements EquivalentConverter { @Override - public final Object getGeneric(Class genericType, TType specific) { + public final Object getGeneric(TType specific) { if (specific != null) - return getGenericValue(genericType, specific); + return getGenericValue(specific); else return null; } /** * Retrieve a copy of the actual generic value. - * @param genericType - generic type. * @param specific - the specific type- * @return A copy of the specific type. */ - protected abstract Object getGenericValue(Class genericType, TType specific); + public abstract Object getGenericValue(TType specific); @Override public final TType getSpecific(Object generic) { @@ -149,7 +153,7 @@ public class BukkitConverters { * @param generic - generic type. * @return A copy of the specific type. */ - protected abstract TType getSpecificValue(Object generic); + public abstract TType getSpecificValue(Object generic); @Override public boolean equals(Object obj) { @@ -175,14 +179,14 @@ public class BukkitConverters { * @author Kristian * @param - instance types it converts. */ - private static abstract class WorldSpecificConverter extends IgnoreNullConverter { + private static abstract class WorldSpecificConverter implements EquivalentConverter { protected World world; /** * Initialize a new world-specificn converter. * @param world - the given world. */ - public WorldSpecificConverter(World world) { + WorldSpecificConverter(World world) { super(); this.world = world; } @@ -206,135 +210,128 @@ public class BukkitConverters { } } - /** - * Retrieve an equivalent converter for a map of generic keys and primitive values. - * @param Key type - * @param Value type - * @param genericKeyType - the generic key type. - * @param keyConverter - an equivalent converter for the generic type. - * @return An equivalent converter. - */ - public static EquivalentConverter> getMapConverter( - final Class genericKeyType, final EquivalentConverter keyConverter) { - // Convert to and from the wrapper - return new IgnoreNullConverter>() { - @SuppressWarnings("unchecked") - @Override - protected Map getSpecificValue(Object generic) { - if (generic instanceof Map) { - Map result = Maps.newHashMap(); - - // Copy everything to a new list - for (Entry entry : ((Map) generic).entrySet()) { - result.put( - keyConverter.getSpecific(entry.getKey()), - (U) entry.getValue() - ); - } - return result; - } - - // Not valid - return null; + public static EquivalentConverter> getMapConverter(EquivalentConverter keyConverter, + EquivalentConverter valConverter) { + return new EquivalentConverter>() { + @Override + public Map getSpecific(Object generic) { + Map genericMap = (Map) generic; + Map newMap; + + try { + newMap = (Map) genericMap.getClass().newInstance(); + } catch (ReflectiveOperationException ex) { + newMap = new HashMap<>(); } - @SuppressWarnings("unchecked") - @Override - protected Object getGenericValue(Class genericType, Map specific) { - Map newContainer = (Map) DefaultInstances.DEFAULT.getDefault(genericType); - - // Convert each object - for (Entry entry : specific.entrySet()) { - newContainer.put( - keyConverter.getGeneric(genericKeyType, entry.getKey()), - entry.getValue() - ); - } - return newContainer; + for (Map.Entry entry : genericMap.entrySet()) { + newMap.put(keyConverter.getSpecific(entry.getKey()), valConverter.getSpecific(entry.getValue())); } - @SuppressWarnings("unchecked") - @Override - public Class> getSpecificType() { - Class dummy = Map.class; - return (Class>) dummy; + return newMap; + } + + @Override + public Object getGeneric(Map specific) { + Map newMap; + + try { + newMap = specific.getClass().newInstance(); + } catch (ReflectiveOperationException ex) { + newMap = new HashMap<>(); } - }; + + for (Map.Entry entry : specific.entrySet()) { + newMap.put(keyConverter.getGeneric(entry.getKey()), valConverter.getGeneric(entry.getValue())); + } + + return newMap; + } + + @Override + public Class> getSpecificType() { + return null; + } + }; } - + /** * Retrieve an equivalent converter for a list of generic items. * @param Type - * @param genericItemType - the generic item type. * @param itemConverter - an equivalent converter for the generic type. * @return An equivalent converter. */ - public static EquivalentConverter> getListConverter(final Class genericItemType, final EquivalentConverter itemConverter) { + public static EquivalentConverter> getListConverter(final EquivalentConverter itemConverter) { // Convert to and from the wrapper - return new IgnoreNullConverter>() { - @SuppressWarnings("unchecked") - @Override - protected List getSpecificValue(Object generic) { - if (generic instanceof Collection) { - List items = new ArrayList(); - - // Copy everything to a new list - for (Object item : (Collection) generic) { - T result = itemConverter.getSpecific(item); - - if (item != null) - items.add(result); + return ignoreNull(new EquivalentConverter>() { + @Override + public List getSpecific(Object generic) { + if (generic instanceof Collection) { + List items = new ArrayList<>(); + + // Copy everything to a new list + for (Object item : (Collection) generic) { + T result = itemConverter.getSpecific(item); + + if (item != null) + items.add(result); + } + return items; + } + + // Not valid + return null; + } + + @Override + public Object getGeneric(List specific) { + List newList; + + try { + newList = (List) specific.getClass().newInstance(); + } catch (ReflectiveOperationException ex) { + newList = new ArrayList<>(); + } + + // Convert each object + for (T position : specific) { + if (position != null) { + Object converted = itemConverter.getGeneric(position); + if (converted != null) { + newList.add(converted); } - return items; + } else { + newList.add(null); } - - // Not valid - return null; } - @SuppressWarnings("unchecked") - @Override - protected Object getGenericValue(Class genericType, List specific) { - Collection newContainer = (Collection) DefaultInstances.DEFAULT.getDefault(genericType); - - // Convert each object - for (T position : specific) { - Object converted = itemConverter.getGeneric(genericItemType, position); - - if (position == null) - newContainer.add(null); - else if (converted != null) - newContainer.add(converted); - } - return newContainer; - } + return newList; + } - @SuppressWarnings("unchecked") - @Override - public Class> getSpecificType() { - // Damn you Java - Class dummy = List.class; - return (Class>) dummy; - } - }; + @Override + public Class> getSpecificType() { + // Damn you Java + Class dummy = List.class; + return (Class>) dummy; + } + }); } /** * Retrieve an equivalent converter for a set of generic items. - * @param Type - * @param genericItemType - the generic item type. + * @param Element type * @param itemConverter - an equivalent converter for the generic type. * @return An equivalent converter. */ @SuppressWarnings("unchecked") - public static EquivalentConverter> getSetConverter(final Class genericItemType, final EquivalentConverter itemConverter) { + public static EquivalentConverter> getSetConverter(final EquivalentConverter itemConverter) { // Convert to and from the wrapper - return new IgnoreNullConverter>() { + return ignoreNull(new EquivalentConverter>() { @Override - protected Set getSpecificValue(Object generic) { + public Set getSpecific(Object generic) { if (generic instanceof Collection) { - Set items = new HashSet(); + Set items = new HashSet<>(); // Copy everything to a new list for (Object item : (Collection) generic) { @@ -352,20 +349,28 @@ public class BukkitConverters { } @Override - protected Object getGenericValue(Class genericType, Set specific) { - Collection newContainer = (Collection) DefaultInstances.DEFAULT.getDefault(genericType); + public Object getGeneric(Set specific) { + Set newList; + + try { + newList = (Set) specific.getClass().newInstance(); + } catch (ReflectiveOperationException ex) { + newList = new HashSet<>(); + } // Convert each object for (T position : specific) { - Object converted = itemConverter.getGeneric(genericItemType, position); - - if (position == null) - newContainer.add(null); - else if (converted != null) - newContainer.add(converted); + if (position != null) { + Object converted = itemConverter.getGeneric(position); + if (converted != null) { + newList.add(converted); + } + } else { + newList.add(null); + } } - return newContainer; + return newList; } @Override @@ -374,7 +379,7 @@ public class BukkitConverters { Class dummy = Set.class; return (Class>) dummy; } - }; + }); } /** @@ -386,71 +391,55 @@ public class BukkitConverters { * @param itemConverter - an equivalent converter for the generic type. * @return An equivalent converter. */ - public static EquivalentConverter> getArrayConverter( - final Class genericItemType, final EquivalentConverter itemConverter) { + public static EquivalentConverter> getArrayConverter(final Class genericItemType, + final EquivalentConverter itemConverter) { // Convert to and from the wrapper - return new IgnoreNullConverter>() { - @Override - protected List getSpecificValue(Object generic) { - if (generic instanceof Object[]) { - ImmutableList.Builder builder = ImmutableList.builder(); + return ignoreNull(new EquivalentConverter>() { + @Override + public List getSpecific(Object generic) { + if (generic instanceof Object[]) { + ImmutableList.Builder builder = ImmutableList.builder(); - // Copy everything to a new list - for (Object item : (Object[]) generic) { - T result = itemConverter.getSpecific(item); - builder.add(result); - } - return builder.build(); + // Copy everything to a new list + for (Object item : (Object[]) generic) { + T result = itemConverter.getSpecific(item); + builder.add(result); } - - // Not valid - return null; + return builder.build(); } - @Override - protected Object getGenericValue(Class genericType, Iterable specific) { - List list = Lists.newArrayList(specific); - Object[] output = (Object[]) Array.newInstance(genericItemType, list.size()); - - // Convert each object - for (int i = 0; i < output.length; i++) { - Object converted = itemConverter.getGeneric(genericItemType, list.get(i)); - output[i] = converted; - } - return output; - } + // Not valid + return null; + } - @SuppressWarnings("unchecked") - @Override - public Class> getSpecificType() { - // Damn you Java - Class dummy = Iterable.class; - return (Class>) dummy; + @Override + public Object getGeneric(Iterable specific) { + List list = Lists.newArrayList(specific); + Object[] output = (Object[]) Array.newInstance(genericItemType, list.size()); + + // Convert each object + for (int i = 0; i < output.length; i++) { + Object converted = itemConverter.getGeneric(list.get(i)); + output[i] = converted; } - }; + return output; + } + + @Override + public Class> getSpecificType() { + // Damn you Java + Class dummy = Iterable.class; + return (Class>) dummy; + } + }); } /** - * Retrieve a converter for wrapped attribute snapshots. - * @return Wrapped attribute snapshot converter. + * Retrieve a converter for wrapped game profiles. + * @return Wrapped game profile converter. */ public static EquivalentConverter getWrappedGameProfileConverter() { - return new IgnoreNullConverter() { - @Override - protected Object getGenericValue(Class genericType, WrappedGameProfile specific) { - return specific.getHandle(); - } - - @Override - protected WrappedGameProfile getSpecificValue(Object generic) { - return WrappedGameProfile.fromHandle(generic); - } - - @Override - public Class getSpecificType() { - return WrappedGameProfile.class; - } - }; + return ignoreNull(handle(WrappedGameProfile::getHandle, WrappedGameProfile::fromHandle)); } /** @@ -458,22 +447,7 @@ public class BukkitConverters { * @return Wrapped chat component. */ public static EquivalentConverter getWrappedChatComponentConverter() { - return new IgnoreNullConverter() { - @Override - protected Object getGenericValue(Class genericType, WrappedChatComponent specific) { - return specific.getHandle(); - } - - @Override - protected WrappedChatComponent getSpecificValue(Object generic) { - return WrappedChatComponent.fromHandle(generic); - } - - @Override - public Class getSpecificType() { - return WrappedChatComponent.class; - } - }; + return ignoreNull(handle(WrappedChatComponent::getHandle, WrappedChatComponent::fromHandle)); } /** @@ -481,22 +455,7 @@ public class BukkitConverters { * @return Wrapped block data. */ public static EquivalentConverter getWrappedBlockDataConverter() { - return new IgnoreNullConverter() { - @Override - protected Object getGenericValue(Class genericType, WrappedBlockData specific) { - return specific.getHandle(); - } - - @Override - protected WrappedBlockData getSpecificValue(Object generic) { - return new WrappedBlockData(generic); - } - - @Override - public Class getSpecificType() { - return WrappedBlockData.class; - } - }; + return ignoreNull(handle(WrappedBlockData::getHandle, WrappedBlockData::new)); } /** @@ -504,22 +463,7 @@ public class BukkitConverters { * @return Wrapped attribute snapshot converter. */ public static EquivalentConverter getWrappedAttributeConverter() { - return new IgnoreNullConverter() { - @Override - protected Object getGenericValue(Class genericType, WrappedAttribute specific) { - return specific.getHandle(); - } - - @Override - protected WrappedAttribute getSpecificValue(Object generic) { - return WrappedAttribute.fromHandle(generic); - } - - @Override - public Class getSpecificType() { - return WrappedAttribute.class; - } - }; + return ignoreNull(handle(WrappedAttribute::getHandle, WrappedAttribute::fromHandle)); } /** @@ -527,27 +471,27 @@ public class BukkitConverters { * @return A watchable object converter. */ public static EquivalentConverter getWatchableObjectConverter() { - return new IgnoreNullConverter() { + return ignoreNull(new EquivalentConverter() { @Override - protected Object getGenericValue(Class genericType, WrappedWatchableObject specific) { + public Object getGeneric(WrappedWatchableObject specific) { return specific.getHandle(); } - + @Override - protected WrappedWatchableObject getSpecificValue(Object generic) { + public WrappedWatchableObject getSpecific(Object generic) { if (MinecraftReflection.isWatchableObject(generic)) return new WrappedWatchableObject(generic); else if (generic instanceof WrappedWatchableObject) return (WrappedWatchableObject) generic; else throw new IllegalArgumentException("Unrecognized type " + generic.getClass()); - }; - + } + @Override public Class getSpecificType() { return WrappedWatchableObject.class; } - }; + }); } /** @@ -555,14 +499,14 @@ public class BukkitConverters { * @return A DataWatcher converter. */ public static EquivalentConverter getDataWatcherConverter() { - return new IgnoreNullConverter() { + return ignoreNull(new EquivalentConverter() { @Override - protected Object getGenericValue(Class genericType, WrappedDataWatcher specific) { + public Object getGeneric(WrappedDataWatcher specific) { return specific.getHandle(); } - + @Override - protected WrappedDataWatcher getSpecificValue(Object generic) { + public WrappedDataWatcher getSpecific(Object generic) { if (MinecraftReflection.isDataWatcher(generic)) return new WrappedDataWatcher(generic); else if (generic instanceof WrappedDataWatcher) @@ -570,12 +514,12 @@ public class BukkitConverters { else throw new IllegalArgumentException("Unrecognized type " + generic.getClass()); } - + @Override public Class getSpecificType() { return WrappedDataWatcher.class; } - }; + }); } /** @@ -586,29 +530,29 @@ public class BukkitConverters { // Check that we can actually use this converter if (!hasWorldType) return null; - + final Class worldType = MinecraftReflection.getWorldTypeClass(); - - return new IgnoreNullConverter() { + + return ignoreNull(new EquivalentConverter() { @Override - protected Object getGenericValue(Class genericType, WorldType specific) { + public Object getGeneric(WorldType specific) { try { // Deduce getType method by parameters alone if (worldTypeGetType == null) { worldTypeGetType = FuzzyReflection.fromClass(worldType). - getMethodByParameters("getType", worldType, new Class[] { String.class }); + getMethodByParameters("getType", worldType, new Class[]{String.class}); } - + // Convert to the Bukkit world type return worldTypeGetType.invoke(this, specific.getName()); - + } catch (Exception e) { throw new FieldAccessException("Cannot find the WorldType.getType() method.", e); } } @Override - protected WorldType getSpecificValue(Object generic) { + public WorldType getSpecific(Object generic) { try { if (worldTypeName == null) { try { @@ -616,24 +560,24 @@ public class BukkitConverters { } catch (Exception e) { // Assume the first method is the one worldTypeName = FuzzyReflection.fromClass(worldType). - getMethodByParameters("name", String.class, new Class[] {}); + getMethodByParameters("name", String.class, new Class[]{}); } } - + // Dynamically call the namne method String name = (String) worldTypeName.invoke(generic); return WorldType.getByName(name); - + } catch (Exception e) { throw new FieldAccessException("Cannot call the name method in WorldType.", e); } } - + @Override public Class getSpecificType() { return WorldType.class; } - }; + }); } /** @@ -641,17 +585,17 @@ public class BukkitConverters { * @return An equivalent converter for NBT. */ public static EquivalentConverter> getNbtConverter() { - return new IgnoreNullConverter>() { + return ignoreNull(new EquivalentConverter>() { @Override - protected Object getGenericValue(Class genericType, NbtBase specific) { + public Object getGeneric(NbtBase specific) { return NbtFactory.fromBase(specific).getHandle(); } - + @Override - protected NbtBase getSpecificValue(Object generic) { + public NbtBase getSpecific(Object generic) { return NbtFactory.fromNMS(generic, null); } - + @Override @SuppressWarnings("unchecked") public Class> getSpecificType() { @@ -659,7 +603,7 @@ public class BukkitConverters { Class dummy = NbtBase.class; return (Class>) dummy; } - }; + }); } /** @@ -668,18 +612,17 @@ public class BukkitConverters { * @return A converter between the underlying NMS entity and Bukkit's wrapper. */ public static EquivalentConverter getEntityConverter(World world) { - final WeakReference managerRef = - new WeakReference(ProtocolLibrary.getProtocolManager()); + final WeakReference managerRef = new WeakReference<>(ProtocolLibrary.getProtocolManager()); return new WorldSpecificConverter(world) { @Override - public Object getGenericValue(Class genericType, Entity specific) { + public Object getGeneric(Entity specific) { // Simple enough return specific.getEntityId(); } @Override - public Entity getSpecificValue(Object generic) { + public Entity getSpecific(Object generic) { try { Integer id = (Integer) generic; ProtocolManager manager = managerRef.get(); @@ -715,7 +658,7 @@ public class BukkitConverters { } @Override - public Object getGeneric(Class genericType, ItemStack specific) { + public Object getGeneric(ItemStack specific) { return MinecraftReflection.getMinecraftItemStack(specific); } @@ -727,26 +670,11 @@ public class BukkitConverters { } /** - * Retrieve the converter for the ServerPing packet in {@link PacketType.Status.Server#OUT_SERVER_INFO}. + * Retrieve the converter for the ServerPing packet in {@link PacketType.Status.Server#SERVER_INFO}. * @return Server ping converter. */ public static EquivalentConverter getWrappedServerPingConverter() { - return new IgnoreNullConverter() { - @Override - protected Object getGenericValue(Class genericType, WrappedServerPing specific) { - return specific.getHandle(); - } - - @Override - protected WrappedServerPing getSpecificValue(Object generic) { - return WrappedServerPing.fromHandle(generic); - } - - @Override - public Class getSpecificType() { - return WrappedServerPing.class; - } - }; + return ignoreNull(handle(WrappedServerPing::getHandle, WrappedServerPing::fromHandle)); } /** @@ -754,22 +682,7 @@ public class BukkitConverters { * @return Statistic converter. */ public static EquivalentConverter getWrappedStatisticConverter() { - return new IgnoreNullConverter() { - @Override - protected Object getGenericValue(Class genericType, WrappedStatistic specific) { - return specific.getHandle(); - } - - @Override - protected WrappedStatistic getSpecificValue(Object generic) { - return WrappedStatistic.fromHandle(generic); - } - - @Override - public Class getSpecificType() { - return WrappedStatistic.class; - } - }; + return ignoreNull(handle(WrappedStatistic::getHandle, WrappedStatistic::fromHandle)); } /** @@ -777,22 +690,22 @@ public class BukkitConverters { * @return A converter for block instances. */ public static EquivalentConverter getBlockConverter() { - return new IgnoreNullConverter() { + return ignoreNull(new EquivalentConverter() { @Override - protected Object getGenericValue(Class genericType, Material specific) { - return getBlockIDConverter().getGeneric(genericType, specific.getId()); + public Object getGeneric(Material specific) { + return getBlockIDConverter().getGeneric(specific.getId()); } - + @Override - protected Material getSpecificValue(Object generic) { + public Material getSpecific(Object generic) { return Material.getMaterial(getBlockIDConverter().getSpecific(generic)); } - + @Override public Class getSpecificType() { return Material.class; } - }; + }); } /** @@ -804,35 +717,36 @@ public class BukkitConverters { if (GET_BLOCK == null || GET_BLOCK_ID == null) { Class block = MinecraftReflection.getBlockClass(); - FuzzyMethodContract getIdContract = FuzzyMethodContract.newBuilder(). - parameterExactArray(block). - requireModifier(Modifier.STATIC). - build(); - FuzzyMethodContract getBlockContract = FuzzyMethodContract.newBuilder(). - returnTypeExact(block). - parameterExactArray(int.class). - requireModifier(Modifier.STATIC). - build(); + FuzzyMethodContract getIdContract = FuzzyMethodContract + .newBuilder() + .parameterExactArray(block) + .requireModifier(Modifier.STATIC) + .build(); + FuzzyMethodContract getBlockContract = FuzzyMethodContract + .newBuilder().returnTypeExact(block) + .parameterExactArray(int.class) + .requireModifier(Modifier.STATIC) + .build(); GET_BLOCK = Accessors.getMethodAccessor(FuzzyReflection.fromClass(block).getMethod(getBlockContract)); GET_BLOCK_ID = Accessors.getMethodAccessor(FuzzyReflection.fromClass(block).getMethod(getIdContract)); } - - return new IgnoreNullConverter() { + + return ignoreNull(new EquivalentConverter() { @Override - protected Object getGenericValue(Class genericType, Integer specific) { + public Object getGeneric(Integer specific) { return GET_BLOCK.invoke(null, specific); } - + @Override - protected Integer getSpecificValue(Object generic) { + public Integer getSpecific(Object generic) { return (Integer) GET_BLOCK_ID.invoke(null, generic); } - + @Override public Class getSpecificType() { return Integer.class; } - }; + }); } /** @@ -840,22 +754,22 @@ public class BukkitConverters { * @return The world converter. */ public static EquivalentConverter getWorldConverter() { - return new IgnoreNullConverter() { + return ignoreNull(new EquivalentConverter() { @Override - protected Object getGenericValue(Class genericType, World specific) { + public Object getGeneric(World specific) { return BukkitUnwrapper.getInstance().unwrapItem(specific); } - + @Override - protected World getSpecificValue(Object generic) { + public World getSpecific(Object generic) { return (World) craftWorldField.get(generic); } - + @Override public Class getSpecificType() { return World.class; } - }; + }); } /** @@ -863,9 +777,9 @@ public class BukkitConverters { * @return The potion effect converter. */ public static EquivalentConverter getPotionEffectConverter() { - return new IgnoreNullConverter() { + return ignoreNull(new EquivalentConverter() { @Override - protected Object getGenericValue(Class genericType, PotionEffect specific) { + public Object getGeneric(PotionEffect specific) { // Locate the constructor if (mobEffectConstructor == null) { try { @@ -875,38 +789,38 @@ public class BukkitConverters { throw new RuntimeException("Cannot find mob effect constructor (int, int, int, boolean).", e); } } - + // Create the generic value try { return mobEffectConstructor.newInstance( - specific.getType().getId(), specific.getDuration(), - specific.getAmplifier(), specific.isAmbient()); + specific.getType().getId(), specific.getDuration(), + specific.getAmplifier(), specific.isAmbient()); } catch (Exception e) { throw new RuntimeException("Cannot construct MobEffect.", e); } } - + @Override - protected PotionEffect getSpecificValue(Object generic) { + public PotionEffect getSpecific(Object generic) { if (mobEffectModifier == null) { - mobEffectModifier = new StructureModifier(MinecraftReflection.getMobEffectClass(), false); + mobEffectModifier = new StructureModifier<>(MinecraftReflection.getMobEffectClass(), false); } StructureModifier ints = mobEffectModifier.withTarget(generic).withType(int.class); StructureModifier bools = mobEffectModifier.withTarget(generic).withType(boolean.class); - + return new PotionEffect( - PotionEffectType.getById(ints.read(0)), /* effectId */ - ints.read(1), /* duration */ - ints.read(2), /* amplification */ - bools.read(1) /* ambient */ + PotionEffectType.getById(ints.read(0)), /* effectId */ + ints.read(1), /* duration */ + ints.read(2), /* amplification */ + bools.read(1) /* ambient */ ); } - + @Override public Class getSpecificType() { return PotionEffect.class; } - }; + }); } private static Constructor vec3dConstructor; @@ -917,7 +831,7 @@ public class BukkitConverters { * @return The Vector converter. */ public static EquivalentConverter getVectorConverter() { - return new IgnoreNullConverter() { + return ignoreNull(new EquivalentConverter() { @Override public Class getSpecificType() { @@ -925,7 +839,7 @@ public class BukkitConverters { } @Override - protected Object getGenericValue(Class genericType, Vector specific) { + public Object getGeneric(Vector specific) { if (vec3dConstructor == null) { try { vec3dConstructor = MinecraftReflection.getVec3DClass().getConstructor( @@ -943,9 +857,9 @@ public class BukkitConverters { } @Override - protected Vector getSpecificValue(Object generic) { + public Vector getSpecific(Object generic) { if (vec3dModifier == null) { - vec3dModifier = new StructureModifier(MinecraftReflection.getVec3DClass(), false); + vec3dModifier = new StructureModifier<>(MinecraftReflection.getVec3DClass(), false); } StructureModifier doubles = vec3dModifier.withTarget(generic).withType(double.class); @@ -956,7 +870,7 @@ public class BukkitConverters { ); } - }; + }); } private static MethodAccessor getSound = null; @@ -969,12 +883,13 @@ public class BukkitConverters { if (getSound == null || getSoundEffect == null) { Class craftSound = MinecraftReflection.getCraftSoundClass(); FuzzyReflection fuzzy = FuzzyReflection.fromClass(craftSound, true); - getSound = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("getSound", String.class, new Class[] { Sound.class })); + getSound = Accessors.getMethodAccessor( + fuzzy.getMethodByParameters("getSound", String.class, new Class[]{Sound.class})); getSoundEffect = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("getSoundEffect", - MinecraftReflection.getSoundEffectClass(), new Class[] { String.class })); + MinecraftReflection.getSoundEffectClass(), new Class[]{String.class})); } - return new IgnoreNullConverter() { + return ignoreNull(new EquivalentConverter() { @Override public Class getSpecificType() { @@ -982,19 +897,20 @@ public class BukkitConverters { } @Override - protected Object getGenericValue(Class genericType, Sound specific) { + public Object getGeneric(Sound specific) { // Getting the SoundEffect is easy, Bukkit provides us the methods String key = (String) getSound.invoke(null, specific); return getSoundEffect.invoke(null, key); } @Override - protected Sound getSpecificValue(Object generic) { + public Sound getSpecific(Object generic) { // Getting the Sound is a bit more complicated... if (soundKey == null) { Class soundEffect = generic.getClass(); FuzzyReflection fuzzy = FuzzyReflection.fromClass(soundEffect, true); - soundKey = Accessors.getFieldAccessor(fuzzy.getFieldByType("key", MinecraftReflection.getMinecraftKeyClass())); + soundKey = Accessors.getFieldAccessor( + fuzzy.getFieldByType("key", MinecraftReflection.getMinecraftKeyClass())); } MinecraftKey minecraftKey = MinecraftKey.fromHandle(soundKey.get(generic)); @@ -1020,35 +936,34 @@ public class BukkitConverters { return soundIndex.get(key); } - }; + }); } - /** - * Wraps a given equivalent converter in NULL checks, ensuring that such values are ignored. - * @param Type - * @param delegate - the underlying equivalent converter. - * @return A equivalent converter that ignores NULL values. - */ - public static EquivalentConverter getIgnoreNull(final EquivalentConverter delegate) { - // Automatically wrap all parameters to the delegate with a NULL check - return new IgnoreNullConverter() { + public static EquivalentConverter getAdvancementConverter() { + return ignoreNull(new EquivalentConverter() { @Override - public Object getGenericValue(Class genericType, TType specific) { - return delegate.getGeneric(genericType, specific); + public Advancement getSpecific(Object generic) { + try { + return (Advancement) getCraftBukkitClass("advancement.CraftAdvancement") + .getConstructor(getMinecraftClass("Advancement")) + .newInstance(generic); + } catch (ReflectiveOperationException ex) { + throw new RuntimeException(ex); + } } - + @Override - public TType getSpecificValue(Object generic) { - return delegate.getSpecific(generic); + public Object getGeneric(Advancement specific) { + return BukkitUnwrapper.getInstance().unwrapItem(specific); } - + @Override - public Class getSpecificType() { - return delegate.getSpecificType(); + public Class getSpecificType() { + return Advancement.class; } - }; + }); } - + /** * Retrieve an equivalent unwrapper for the converter. * @param nativeType - the native NMS type the converter produces. @@ -1056,68 +971,26 @@ public class BukkitConverters { * @return The equivalent unwrapper. */ public static Unwrapper asUnwrapper(final Class nativeType, final EquivalentConverter converter) { - return new Unwrapper() { - @Override - public Object unwrapItem(Object wrappedObject) { - Class type = PacketConstructor.getClass(wrappedObject); - - // Ensure the type is correct before we test - if (converter.getSpecificType().isAssignableFrom(type)) { - if (wrappedObject instanceof Class) - return nativeType; - else - return converter.getGeneric(nativeType, wrappedObject); - } - return null; + return wrappedObject -> { + Class type = PacketConstructor.getClass(wrappedObject); + + // Ensure the type is correct before we test + if (converter.getSpecificType().isAssignableFrom(type)) { + if (wrappedObject instanceof Class) + return nativeType; + else + return converter.getGeneric(wrappedObject); } + return null; }; } - - /** - * Retrieve every converter that is associated with a specific class. - * @return Every converter with a unique specific class. - */ - @SuppressWarnings({"rawtypes", "unchecked"}) - public static Map, EquivalentConverter> getConvertersForSpecific() { - if (specificConverters == null) { - // Generics doesn't work, as usual - ImmutableMap.Builder, EquivalentConverter> builder = - ImmutableMap., EquivalentConverter>builder(). - put(WrappedDataWatcher.class, (EquivalentConverter) getDataWatcherConverter()). - put(ItemStack.class, (EquivalentConverter) getItemStackConverter()). - put(NbtBase.class, (EquivalentConverter) getNbtConverter()). - put(NbtCompound.class, (EquivalentConverter) getNbtConverter()). - put(WrappedWatchableObject.class, (EquivalentConverter) getWatchableObjectConverter()). - put(PotionEffect.class, (EquivalentConverter) getPotionEffectConverter()). - put(World.class, (EquivalentConverter) getWorldConverter()); - - // Types added in 1.7.2 - if (MinecraftReflection.isUsingNetty()) { - builder.put(Material.class, (EquivalentConverter) getBlockConverter()); - builder.put(WrappedGameProfile.class, (EquivalentConverter) getWrappedGameProfileConverter()); - builder.put(WrappedChatComponent.class, (EquivalentConverter) getWrappedChatComponentConverter()); - builder.put(WrappedServerPing.class, (EquivalentConverter) getWrappedServerPingConverter()); - builder.put(WrappedStatistic.class, (EquivalentConverter) getWrappedStatisticConverter()); - - for (Entry, EquivalentConverter> entry : EnumWrappers.getFromWrapperMap().entrySet()) { - builder.put((Class) entry.getKey(), (EquivalentConverter) entry.getValue()); - } - } - - if (hasWorldType) - builder.put(WorldType.class, (EquivalentConverter) getWorldTypeConverter()); - if (hasAttributeSnapshot) - builder.put(WrappedAttribute.class, (EquivalentConverter) getWrappedAttributeConverter()); - specificConverters = builder.build(); - } - return specificConverters; - } - + /** * Retrieve every converter that is associated with a generic class. * @return Every converter with a unique generic class. */ - @SuppressWarnings({"rawtypes", "unchecked"}) + @SuppressWarnings("rawtypes") + // TODO this list needs to be updated public static Map, EquivalentConverter> getConvertersForGeneric() { if (genericConverters == null) { // Generics doesn't work, as usual @@ -1173,7 +1046,7 @@ public class BukkitConverters { private static MethodAccessor getMobEffect = null; public static EquivalentConverter getEffectTypeConverter() { - return new IgnoreNullConverter() { + return ignoreNull(new EquivalentConverter() { @Override public Class getSpecificType() { @@ -1181,9 +1054,10 @@ public class BukkitConverters { } @Override - protected Object getGenericValue(Class genericType, PotionEffectType specific) { + public Object getGeneric(PotionEffectType specific) { + Class clazz = MinecraftReflection.getMobEffectListClass(); if (getMobEffect == null) { - getMobEffect = Accessors.getMethodAccessor(genericType, "fromId", int.class); + getMobEffect = Accessors.getMethodAccessor(clazz, "fromId", int.class); } int id = specific.getId(); @@ -1191,7 +1065,7 @@ public class BukkitConverters { } @Override - protected PotionEffectType getSpecificValue(Object generic) { + public PotionEffectType getSpecific(Object generic) { Class clazz = MinecraftReflection.getMobEffectListClass(); if (getMobEffectId == null) { getMobEffectId = Accessors.getMethodAccessor(clazz, "getId", clazz); @@ -1200,6 +1074,6 @@ public class BukkitConverters { int id = (int) getMobEffectId.invoke(null, generic); return PotionEffectType.getById(id); } - }; + }); } } diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/ChunkCoordIntPair.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/ChunkCoordIntPair.java index 0b6e3628..527fedc7 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/ChunkCoordIntPair.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/ChunkCoordIntPair.java @@ -67,7 +67,7 @@ public class ChunkCoordIntPair { public static EquivalentConverter getConverter() { return new EquivalentConverter() { @Override - public Object getGeneric(Class genericType, ChunkCoordIntPair specific) { + public Object getGeneric(ChunkCoordIntPair specific) { if (COORD_CONSTRUCTOR == null) { COORD_CONSTRUCTOR = Accessors.getConstructorAccessor(COORD_PAIR_CLASS, int.class, int.class); } diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/ChunkPosition.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/ChunkPosition.java index 022491c3..ae0dc1d5 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/ChunkPosition.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/ChunkPosition.java @@ -154,7 +154,7 @@ public class ChunkPosition { public static EquivalentConverter getConverter() { return new EquivalentConverter() { @Override - public Object getGeneric(Class genericType, ChunkPosition specific) { + public Object getGeneric(ChunkPosition specific) { if (chunkPositionConstructor == null) { try { chunkPositionConstructor = MinecraftReflection.getChunkPositionClass(). @@ -177,7 +177,7 @@ public class ChunkPosition { public ChunkPosition getSpecific(Object generic) { if (MinecraftReflection.isChunkPosition(generic)) { // Use a structure modifier - intModifier = new StructureModifier(generic.getClass(), null, false).withType(int.class); + intModifier = new StructureModifier<>(generic.getClass(), null, false).withType(int.class); // Damn it all if (intModifier.size() < 3) { diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/Converters.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/Converters.java new file mode 100644 index 00000000..064e7016 --- /dev/null +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/Converters.java @@ -0,0 +1,106 @@ +/** + * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. + * Copyright (C) 2017 Dan Mulloy + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + */ +package com.comphenix.protocol.wrappers; + +import java.util.function.Function; + +import com.comphenix.protocol.reflect.EquivalentConverter; + +/** + * Utility class for converters + * @author dmulloy2 + */ +public class Converters { + + /** + * Returns a converter that ignores null elements, so that the underlying converter doesn't have to worry about them. + * @param converter Underlying converter + * @param Element type + * @return An ignore null converter + */ + public static EquivalentConverter ignoreNull(final EquivalentConverter converter) { + return new EquivalentConverter() { + @Override + public T getSpecific(Object generic) { + return generic != null ? converter.getSpecific(generic) : null; + } + + @Override + public Object getGeneric(T specific) { + return specific != null ? converter.getGeneric(specific) : null; + } + + @Override + public Class getSpecificType() { + return converter.getSpecificType(); + } + }; + } + + /** + * Returns a converter that passes generic and specific values through without converting. + * @param clazz Element class + * @param Element type + * @return A passthrough converter + */ + public static EquivalentConverter passthrough(final Class clazz) { + return ignoreNull(new EquivalentConverter() { + @Override + public T getSpecific(Object generic) { + return (T) generic; + } + + @Override + public Object getGeneric(T specific) { + return specific; + } + + @Override + public Class getSpecificType() { + return clazz; + } + }); + } + + /** + * Creates a simple converter for wrappers with {@code getHandle()} and {@code fromHandle(...)} methods. With Java 8, + * converters can be reduced to a single line (see {@link BukkitConverters#getWrappedGameProfileConverter()}). + * @param toHandle Function from wrapper to handle (i.e. {@code getHandle()}) + * @param fromHandle Function from handle to wrapper (i.e. {@code fromHandle(Object)}) + * @param Wrapper type + * @return A handle converter + */ + public static EquivalentConverter handle(final Function toHandle, + final Function fromHandle) { + return new EquivalentConverter() { + @Override + public T getSpecific(Object generic) { + return fromHandle.apply(generic); + } + + @Override + public Object getGeneric(T specific) { + return toHandle.apply(specific); + } + + @Override + public Class getSpecificType() { + return null; + } + }; + } +} diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java index 1a128fea..11284c95 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/EnumWrappers.java @@ -3,6 +3,7 @@ package com.comphenix.protocol.wrappers; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.function.Function; import org.bukkit.GameMode; @@ -562,117 +563,119 @@ public abstract class EnumWrappers { // Get the converters public static EquivalentConverter getProtocolConverter() { - return new EnumConverter(Protocol.class); + return new EnumConverter<>(getProtocolClass(), Protocol.class); } public static EquivalentConverter getClientCommandConverter() { - return new EnumConverter(ClientCommand.class); + return new EnumConverter<>(getClientCommandClass(), ClientCommand.class); } public static EquivalentConverter getChatVisibilityConverter() { - return new EnumConverter(ChatVisibility.class); + return new EnumConverter<>(getChatVisibilityClass(), ChatVisibility.class); } public static EquivalentConverter getDifficultyConverter() { - return new EnumConverter(Difficulty.class); + return new EnumConverter<>(getDifficultyClass(), Difficulty.class); } public static EquivalentConverter getEntityUseActionConverter() { - return new EnumConverter(EntityUseAction.class); + return new EnumConverter<>(getEntityUseActionClass(), EntityUseAction.class); } public static EquivalentConverter getGameModeConverter() { - return new EnumConverter(NativeGameMode.class); + return new EnumConverter<>(getGameModeClass(), NativeGameMode.class); } public static EquivalentConverter getResourcePackStatusConverter() { - return new EnumConverter(ResourcePackStatus.class); + return new EnumConverter<>(getResourcePackStatusClass(), ResourcePackStatus.class); } public static EquivalentConverter getPlayerInfoActionConverter() { - return new EnumConverter(PlayerInfoAction.class); + return new EnumConverter<>(getPlayerInfoActionClass(), PlayerInfoAction.class); } public static EquivalentConverter getTitleActionConverter() { - return new EnumConverter(TitleAction.class); + return new EnumConverter<>(getTitleActionClass(), TitleAction.class); } public static EquivalentConverter getWorldBorderActionConverter() { - return new EnumConverter(WorldBorderAction.class); + return new EnumConverter<>(getWorldBorderActionClass(), WorldBorderAction.class); } public static EquivalentConverter getCombatEventTypeConverter() { - return new EnumConverter(CombatEventType.class); + return new EnumConverter<>(getCombatEventTypeClass(), CombatEventType.class); } public static EquivalentConverter getPlayerDiggingActionConverter() { - return new EnumConverter(PlayerDigType.class); + return new EnumConverter<>(getPlayerDigTypeClass(), PlayerDigType.class); } public static EquivalentConverter getEntityActionConverter() { - return new EnumConverter(PlayerAction.class); + return new EnumConverter<>(getPlayerActionClass(), PlayerAction.class); } public static EquivalentConverter getUpdateScoreActionConverter() { - return new EnumConverter(ScoreboardAction.class); + return new EnumConverter<>(getScoreboardActionClass(), ScoreboardAction.class); } public static EquivalentConverter getParticleConverter() { - return new EnumConverter(Particle.class); + return new EnumConverter<>(getParticleClass(), Particle.class); } public static EquivalentConverter getSoundCategoryConverter() { - return new EnumConverter(SoundCategory.class); + return new EnumConverter<>(getSoundCategoryClass(), SoundCategory.class); } public static EquivalentConverter getItemSlotConverter() { - return new EnumConverter(ItemSlot.class); + return new EnumConverter<>(getItemSlotClass(), ItemSlot.class); } public static EquivalentConverter getHandConverter() { - return new EnumConverter(Hand.class); + return new EnumConverter<>(getHandClass(), Hand.class); } public static EquivalentConverter getDirectionConverter() { - return new EnumConverter(Direction.class); + return new EnumConverter<>(getDirectionClass(), Direction.class); } public static EquivalentConverter getChatTypeConverter() { - return new EnumConverter(ChatType.class); + return new EnumConverter<>(getChatTypeClass(), ChatType.class); } /** * Retrieve a generic enum converter for use with StructureModifiers. - * @param enumClass - Enum class + * @param genericClass - Generic nms enum class + * @param specificType - Specific enum class * @return A generic enum converter */ - public static > EquivalentConverter getGenericConverter(Class enumClass) { - return new EnumConverter(enumClass); + public static > EquivalentConverter getGenericConverter(Class genericClass, Class specificType) { + return new EnumConverter<>(genericClass, specificType); } // The common enum converter @SuppressWarnings({ "rawtypes", "unchecked" }) public static class EnumConverter> implements EquivalentConverter { + private Class genericType; private Class specificType; - public EnumConverter(Class specificType) { + public EnumConverter(Class genericType, Class specificType) { + this.genericType = genericType; this.specificType = specificType; } @Override public T getSpecific(Object generic) { - // We know its an enum already! return Enum.valueOf(specificType, ((Enum) generic).name()); } @Override - public Object getGeneric(Class genericType, T specific) { + public Object getGeneric(T specific) { return Enum.valueOf((Class) genericType, specific.name()); } @Override public Class getSpecificType() { - return specificType; + return null; } } } diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/MinecraftKey.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/MinecraftKey.java index 788c75e1..8ce6a57c 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/MinecraftKey.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/MinecraftKey.java @@ -122,7 +122,7 @@ public class MinecraftKey { } @Override - public Object getGeneric(Class genericType, MinecraftKey specific) { + public Object getGeneric(MinecraftKey specific) { if (constructor == null) { try { constructor = MinecraftReflection.getMinecraftKeyClass().getConstructor(String.class, String.class); diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/MultiBlockChangeInfo.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/MultiBlockChangeInfo.java index 6eb8050c..66d36102 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/MultiBlockChangeInfo.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/MultiBlockChangeInfo.java @@ -190,7 +190,7 @@ public class MultiBlockChangeInfo { @Override public MultiBlockChangeInfo getSpecific(Object generic) { - StructureModifier modifier = new StructureModifier(generic.getClass(), null, false).withTarget(generic); + StructureModifier modifier = new StructureModifier<>(generic.getClass(), null, false).withTarget(generic); StructureModifier shorts = modifier.withType(short.class); short location = shorts.read(0); @@ -203,7 +203,7 @@ public class MultiBlockChangeInfo { } @Override - public Object getGeneric(Class genericType, MultiBlockChangeInfo specific) { + public Object getGeneric(MultiBlockChangeInfo specific) { try { if (constructor == null) { constructor = nmsClass.getConstructor( @@ -216,7 +216,7 @@ public class MultiBlockChangeInfo { return constructor.newInstance( null, specific.location, - BukkitConverters.getWrappedBlockDataConverter().getGeneric(MinecraftReflection.getIBlockDataClass(), specific.data) + BukkitConverters.getWrappedBlockDataConverter().getGeneric(specific.data) ); } catch (Throwable ex) { throw new RuntimeException("Failed to construct MultiBlockChangeInfo instance.", ex); @@ -248,12 +248,12 @@ public class MultiBlockChangeInfo { } @Override - public Object getGeneric(Class genericType, MultiBlockChangeInfo[] specific) { + public Object getGeneric(MultiBlockChangeInfo[] specific) { Object[] result = (Object[]) Array.newInstance(nmsClass, specific.length); // Wrap every item for (int i = 0; i < result.length; i++) { - result[i] = converter.getGeneric(nmsClass, specific[i]); + result[i] = converter.getGeneric(specific[i]); } return result; diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/PlayerInfoData.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/PlayerInfoData.java index 77a6e390..7b287b45 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/PlayerInfoData.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/PlayerInfoData.java @@ -91,7 +91,7 @@ public class PlayerInfoData { public static EquivalentConverter getConverter() { return new EquivalentConverter() { @Override - public Object getGeneric(Class genericType, PlayerInfoData specific) { + public Object getGeneric(PlayerInfoData specific) { if (constructor == null) { try { // public PlayerInfoData(Packet, GameProfile, int, GameMode, ChatComponent) @@ -116,7 +116,7 @@ public class PlayerInfoData { null, specific.profile.handle, specific.latency, - EnumWrappers.getGameModeConverter().getGeneric(EnumWrappers.getGameModeClass(), specific.gameMode), + EnumWrappers.getGameModeConverter().getGeneric(specific.gameMode), specific.displayName != null ? specific.displayName.handle : null ); return result; @@ -128,7 +128,7 @@ public class PlayerInfoData { @Override public PlayerInfoData getSpecific(Object generic) { if (MinecraftReflection.isPlayerInfoData(generic)) { - StructureModifier modifier = new StructureModifier(generic.getClass(), null, false) + StructureModifier modifier = new StructureModifier<>(generic.getClass(), null, false) .withTarget(generic); StructureModifier gameProfiles = modifier.withType( diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/Vector3F.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/Vector3F.java index 2f47e6a7..36b88ba0 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/Vector3F.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/Vector3F.java @@ -91,15 +91,14 @@ public class Vector3F { } public static EquivalentConverter getConverter() { - return new IgnoreNullConverter() { - + return Converters.ignoreNull(new EquivalentConverter() { @Override public Class getSpecificType() { return Vector3F.class; } @Override - protected Object getGenericValue(Class genericType, Vector3F specific) { + public Object getGeneric(Vector3F specific) { if (constructor == null) { try { constructor = clazz.getConstructor(float.class, float.class, float.class); @@ -107,7 +106,7 @@ public class Vector3F { throw new RuntimeException("Failed to find constructor for Vector3f", ex); } } - + try { return constructor.newInstance(specific.x, specific.y, specific.z); } catch (ReflectiveOperationException ex) { @@ -116,7 +115,7 @@ public class Vector3F { } @Override - protected Vector3F getSpecificValue(Object generic) { + public Vector3F getSpecific(Object generic) { StructureModifier modifier = new StructureModifier(generic.getClass()) .withTarget(generic).withType(float.class); float x = modifier.read(0); @@ -124,6 +123,6 @@ public class Vector3F { float z = modifier.read(2); return new Vector3F(x, y, z); } - }; + }); } } \ No newline at end of file diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/WrappedServerPing.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/WrappedServerPing.java index 5eef2c3a..f64da6c6 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/WrappedServerPing.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/WrappedServerPing.java @@ -280,7 +280,7 @@ public class WrappedServerPing extends AbstractWrapper { public void setPlayers(Iterable profile) { if (players == null) resetPlayers(); - PLAYERS_PROFILES.set(players, (profile != null) ? PROFILE_CONVERT.getGeneric(GAME_PROFILE_ARRAY, profile) : null); + PLAYERS_PROFILES.set(players, (profile != null) ? PROFILE_CONVERT.getGeneric(profile) : null); } /** diff --git a/modules/API/src/main/java/com/comphenix/protocol/wrappers/WrappedWatchableObject.java b/modules/API/src/main/java/com/comphenix/protocol/wrappers/WrappedWatchableObject.java index 83d52742..14051a8a 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/wrappers/WrappedWatchableObject.java +++ b/modules/API/src/main/java/com/comphenix/protocol/wrappers/WrappedWatchableObject.java @@ -273,22 +273,22 @@ public class WrappedWatchableObject extends AbstractWrapper { if (wrapped instanceof WrappedChatComponent) { return ((WrappedChatComponent) wrapped).getHandle(); } else if (wrapped instanceof ItemStack) { - return BukkitConverters.getItemStackConverter().getGeneric(MinecraftReflection.getItemStackClass(), (ItemStack) wrapped); + return BukkitConverters.getItemStackConverter().getGeneric((ItemStack) wrapped); } else if (wrapped instanceof WrappedBlockData) { - return BukkitConverters.getWrappedBlockDataConverter().getGeneric(MinecraftReflection.getIBlockDataClass(), (WrappedBlockData) wrapped); + return BukkitConverters.getWrappedBlockDataConverter().getGeneric((WrappedBlockData) wrapped); } else if (wrapped instanceof Vector3F) { - return Vector3F.getConverter().getGeneric(Vector3F.getMinecraftClass(), (Vector3F) wrapped); + return Vector3F.getConverter().getGeneric((Vector3F) wrapped); } else if (wrapped instanceof BlockPosition) { - return BlockPosition.getConverter().getGeneric(MinecraftReflection.getBlockPositionClass(), (BlockPosition) wrapped); + return BlockPosition.getConverter().getGeneric((BlockPosition) wrapped); } else if (wrapped instanceof Direction) { - return EnumWrappers.getDirectionConverter().getGeneric(EnumWrappers.getDirectionClass(), (Direction) wrapped); + return EnumWrappers.getDirectionConverter().getGeneric((Direction) wrapped); } else if (wrapped instanceof NbtCompound) { return NbtFactory.fromBase((NbtCompound) wrapped).getHandle(); } // Legacy classes if (wrapped instanceof ChunkPosition) { - return ChunkPosition.getConverter().getGeneric(MinecraftReflection.getChunkPositionClass(), (ChunkPosition) wrapped); + return ChunkPosition.getConverter().getGeneric((ChunkPosition) wrapped); } else if (wrapped instanceof WrappedChunkCoordinate) { return ((WrappedChunkCoordinate) wrapped).getHandle(); } diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java index c2457f5d..8257f6c8 100644 --- a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java @@ -38,6 +38,7 @@ public class BukkitInitialization { try { LogManager.getLogger(); } catch (Throwable ex) { + // Happens only on my Jenkins, but if it errors here it works when it matters ex.printStackTrace(); } @@ -69,6 +70,7 @@ public class BukkitInitialization { try { LogManager.getLogger(); } catch (Throwable ex) { + // Happens only on my Jenkins, but if it errors here it works when it matters ex.printStackTrace(); } diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/ChunkCoordIntPairTest.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/ChunkCoordIntPairTest.java index d7561716..e225d358 100644 --- a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/ChunkCoordIntPairTest.java +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/ChunkCoordIntPairTest.java @@ -24,7 +24,7 @@ public class ChunkCoordIntPairTest { net.minecraft.server.v1_12_R1.ChunkCoordIntPair roundtrip = (net.minecraft.server.v1_12_R1.ChunkCoordIntPair) ChunkCoordIntPair.getConverter(). - getGeneric(net.minecraft.server.v1_12_R1.ChunkCoordIntPair.class, specific); + getGeneric(specific); assertEquals(1, roundtrip.x); assertEquals(2, roundtrip.z); diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/EnumWrappersTest.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/EnumWrappersTest.java index af9e27fb..f9cf8cd2 100644 --- a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/EnumWrappersTest.java +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/EnumWrappersTest.java @@ -55,7 +55,6 @@ public class EnumWrappersTest { FieldAccessor accessor = Accessors.getFieldAccessor(target.getClass(), fieldName, true); return (T) converter.getGeneric( - accessor.getField().getType(), converter.getSpecific(accessor.get(target)) ); } diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/MultiBlockChangeTest.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/MultiBlockChangeTest.java index 5cd40c9a..8c777c94 100644 --- a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/MultiBlockChangeTest.java +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/MultiBlockChangeTest.java @@ -58,7 +58,7 @@ public class MultiBlockChangeTest { MultiBlockChangeInfo[] array = { info, info }; EquivalentConverter converter = MultiBlockChangeInfo.getArrayConverter(chunk); - Object generic = converter.getGeneric(MinecraftReflection.getMultiBlockChangeInfoArrayClass(), array); + Object generic = converter.getGeneric(array); MultiBlockChangeInfo[] back = converter.getSpecific(generic); // Make sure our conversions are correct diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/PlayerInfoDataTest.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/PlayerInfoDataTest.java index 58c80658..67a4854e 100644 --- a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/PlayerInfoDataTest.java +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/PlayerInfoDataTest.java @@ -43,7 +43,7 @@ public class PlayerInfoDataTest { WrappedChatComponent displayName = WrappedChatComponent.fromText("Name's Name"); PlayerInfoData data = new PlayerInfoData(profile, 42, NativeGameMode.CREATIVE, displayName); - Object generic = PlayerInfoData.getConverter().getGeneric(MinecraftReflection.getPlayerInfoDataClass(), data); + Object generic = PlayerInfoData.getConverter().getGeneric(data); PlayerInfoData back = PlayerInfoData.getConverter().getSpecific(generic); assertEquals(data, back); diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/WrappedBlockDataTest.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/WrappedBlockDataTest.java index a6384360..060874d2 100644 --- a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/WrappedBlockDataTest.java +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/wrappers/WrappedBlockDataTest.java @@ -47,7 +47,7 @@ public class WrappedBlockDataTest { assertEquals(wrapper.getType(), type); assertEquals(wrapper.getData(), data); - Object generic = BukkitConverters.getWrappedBlockDataConverter().getGeneric(MinecraftReflection.getIBlockDataClass(), wrapper); + Object generic = BukkitConverters.getWrappedBlockDataConverter().getGeneric(wrapper); WrappedBlockData back = BukkitConverters.getWrappedBlockDataConverter().getSpecific(generic); assertEquals(wrapper.getType(), back.getType()); diff --git a/pom.xml b/pom.xml index ddf7b5dd..aff08c10 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ UTF-8 - 4.3.1-SNAPSHOT + 4.4.0-SNAPSHOT 1.12-R0.1-SNAPSHOT @@ -45,7 +45,7 @@ - + io.netty netty-all