diff --git a/src/main/java/com/comphenix/protocol/events/PacketContainer.java b/src/main/java/com/comphenix/protocol/events/PacketContainer.java index e7edf8a5..ed16eec7 100644 --- a/src/main/java/com/comphenix/protocol/events/PacketContainer.java +++ b/src/main/java/com/comphenix/protocol/events/PacketContainer.java @@ -58,6 +58,7 @@ import org.bukkit.Sound; import org.bukkit.World; import org.bukkit.WorldType; import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; @@ -436,6 +437,16 @@ public class PacketContainer implements Serializable { Preconditions.checkNotNull(event, "event cannot be NULL."); return getEntityModifier(event.getPlayer().getWorld()); } + + /** + * Retrieves a read/write structure for entity types + * @return A modifier for an EntityType. + */ + public StructureModifier getEntityTypeModifier() { + return structureModifier.withType( + MinecraftReflection.getMinecraftClass("EntityTypes"), + BukkitConverters.getEntityTypeConverter()); + } /** * Retrieves a read/write structure for chunk positions. diff --git a/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java b/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java index 65fd421c..1891d6cc 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java +++ b/src/main/java/com/comphenix/protocol/wrappers/BukkitConverters.java @@ -49,12 +49,15 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; +import net.minecraft.server.v1_14_R1.EntityTypes; + 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.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -655,6 +658,54 @@ public class BukkitConverters { } }; } + + private static MethodAccessor getEntityTypeName; + private static MethodAccessor entityTypeFromName; + + public static EquivalentConverter getEntityTypeConverter() { + return ignoreNull(new EquivalentConverter() { + @Override + public Object getGeneric(EntityType specific) { + if (entityTypeFromName == null) { + Class entityTypesClass = MinecraftReflection.getMinecraftClass("EntityTypes"); + entityTypeFromName = Accessors.getMethodAccessor( + FuzzyReflection + .fromClass(entityTypesClass, false) + .getMethod(FuzzyMethodContract + .newBuilder() + .returnDerivedOf(Optional.class) + .parameterExactArray(new Class[]{ String.class }) + .build())); + } + + Optional opt = (Optional) entityTypeFromName.invoke(null, specific.getName()); + return opt.orElse(null); + } + + @Override + public EntityType getSpecific(Object generic) { + if (getEntityTypeName == null) { + Class entityTypesClass = MinecraftReflection.getMinecraftClass("EntityTypes"); + getEntityTypeName = Accessors.getMethodAccessor( + FuzzyReflection + .fromClass(entityTypesClass, false) + .getMethod(FuzzyMethodContract + .newBuilder() + .returnTypeExact(MinecraftReflection.getMinecraftKeyClass()) + .parameterExactArray(new Class[]{ entityTypesClass }) + .build())); + } + + MinecraftKey key = MinecraftKey.fromHandle(getEntityTypeName.invoke(null, generic)); + return EntityType.fromName(key.getKey()); + } + + @Override + public Class getSpecificType() { + return EntityType.class; + } + }); + } /** * Retrieve the converter used to convert NMS ItemStacks to Bukkit's ItemStack. diff --git a/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java b/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java index 4b39a9d1..58f3c084 100644 --- a/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java +++ b/src/test/java/com/comphenix/protocol/events/PacketContainerTest.java @@ -46,6 +46,7 @@ import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.WorldType; +import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.potion.PotionEffect; @@ -289,6 +290,14 @@ public class PacketContainerTest { // @Test // public void testGetPositionModifier() { } + @Test + public void testEntityTypeModifier() { + PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY); + + packet.getEntityTypeModifier().write(0, EntityType.ARROW); + assertEquals(packet.getEntityTypeModifier().read(0), EntityType.ARROW); + } + @Test public void testGetPositionCollectionModifier() { PacketContainer explosionPacket = new PacketContainer(PacketType.Play.Server.EXPLOSION);