diff --git a/TODOLIST b/TODOLIST index 97fa7421c..dd14be8a3 100644 --- a/TODOLIST +++ b/TODOLIST @@ -1,4 +1,3 @@ -Migrate EntityUtil to be cool Fix 1.9to1.8 Migrate listeners in BaseProtocol Register Listeners Properly diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java index c43dffd12..947bb8536 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetaIndex.java @@ -1,146 +1,159 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata; +import com.google.common.base.Optional; import lombok.Getter; -import org.bukkit.entity.*; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.util.EntityUtil; + +import java.util.HashMap; + +import static us.myles.ViaVersion.util.EntityUtil.EntityType.*; @Getter public enum MetaIndex { // entity - ENTITY_STATUS(org.bukkit.entity.Entity.class, 0, Type.Byte, NewType.Byte), - ENTITY_AIR(org.bukkit.entity.Entity.class, 1, Type.Short, NewType.VarInt), - ENTITY_SILENT(org.bukkit.entity.Entity.class, 4, Type.Byte, NewType.Boolean), + ENTITY_STATUS(ENTITY, 0, Type.Byte, NewType.Byte), + ENTITY_AIR(ENTITY, 1, Type.Short, NewType.VarInt), + ENTITY_SILENT(ENTITY, 4, Type.Byte, NewType.Boolean), // living entity - LIVINGENTITY_NAMETAG(LivingEntity.class, 2, Type.String, NewType.String), - LIVINGENTITY_ALWAYS_SHOW_NAMETAG(LivingEntity.class, 3, Type.Byte, NewType.Boolean), - LIVINGENTITY_HEALTH(LivingEntity.class, 6, Type.Float, NewType.Float), - LIVINGENTITY_POTION_EFFECT_COLOR(LivingEntity.class, 7, Type.Int, NewType.VarInt), - LIVINGENTITY_IS_POTION_AMBIENT(LivingEntity.class, 8, Type.Byte, NewType.Boolean), - LIVINGENTITY_NUMBER_OF_ARROWS_IN(LivingEntity.class, 9, Type.Byte, NewType.VarInt), - LIVINGENTITY_NO_AI(LivingEntity.class, 15, Type.Byte, 10, NewType.Byte), // in 1.9 this is combined with Left handed, oh. + LIVINGENTITY_NAMETAG(ENTITY_LIVING, 2, Type.String, NewType.String), + LIVINGENTITY_ALWAYS_SHOW_NAMETAG(ENTITY_LIVING, 3, Type.Byte, NewType.Boolean), + LIVINGENTITY_HEALTH(ENTITY_LIVING, 6, Type.Float, NewType.Float), + LIVINGENTITY_POTION_EFFECT_COLOR(ENTITY_LIVING, 7, Type.Int, NewType.VarInt), + LIVINGENTITY_IS_POTION_AMBIENT(ENTITY_LIVING, 8, Type.Byte, NewType.Boolean), + LIVINGENTITY_NUMBER_OF_ARROWS_IN(ENTITY_LIVING, 9, Type.Byte, NewType.VarInt), + LIVINGENTITY_NO_AI(ENTITY_LIVING, 15, Type.Byte, 10, NewType.Byte), // in 1.9 this is combined with Left handed, oh. // ageable - AGEABLE_AGE(Ageable.class, 12, Type.Byte, 11, NewType.Boolean), + AGEABLE_AGE(ENTITY_AGEABLE, 12, Type.Byte, 11, NewType.Boolean), // armour stand - STAND_INFO(ArmorStand.class, 10, Type.Byte, NewType.Byte), - STAND_HEAD_POS(ArmorStand.class, 11, Type.Rotation, NewType.Vector3F), - STAND_BODY_POS(ArmorStand.class, 12, Type.Rotation, NewType.Vector3F), - STAND_LA_POS(ArmorStand.class, 13, Type.Rotation, NewType.Vector3F), - STAND_RA_POS(ArmorStand.class, 14, Type.Rotation, NewType.Vector3F), - STAND_LL_POS(ArmorStand.class, 15, Type.Rotation, NewType.Vector3F), - STAND_RL_POS(ArmorStand.class, 16, Type.Rotation, NewType.Vector3F), + STAND_INFO(ARMOR_STAND, 10, Type.Byte, NewType.Byte), + STAND_HEAD_POS(ARMOR_STAND, 11, Type.Rotation, NewType.Vector3F), + STAND_BODY_POS(ARMOR_STAND, 12, Type.Rotation, NewType.Vector3F), + STAND_LA_POS(ARMOR_STAND, 13, Type.Rotation, NewType.Vector3F), + STAND_RA_POS(ARMOR_STAND, 14, Type.Rotation, NewType.Vector3F), + STAND_LL_POS(ARMOR_STAND, 15, Type.Rotation, NewType.Vector3F), + STAND_RL_POS(ARMOR_STAND, 16, Type.Rotation, NewType.Vector3F), // human, discountined? - PLAYER_SKIN_FLAGS(HumanEntity.class, 10, Type.Byte, 12, NewType.Byte), // unsigned on 1.8 - PLAYER_HUMAN_BYTE(HumanEntity.class, 16, Type.Byte, NewType.Discontinued), // unused on 1.8 - PLAYER_ADDITIONAL_HEARTS(HumanEntity.class, 17, Type.Float, 10, NewType.Float), - PLAYER_SCORE(HumanEntity.class, 18, Type.Int, 11, NewType.VarInt), - PLAYER_HAND(HumanEntity.class, -1, Type.NonExistent, 5, NewType.Byte), // new in 1.9 - SOMETHING_ANTICHEAT_PLUGINS_FOR_SOME_REASON_USE(HumanEntity.class, 11, Type.Byte, NewType.Discontinued), //For what we know, This doesn't exists. If you think it exists and knows what it does. Please tell us. + PLAYER_SKIN_FLAGS(ENTITY_HUMAN, 10, Type.Byte, 12, NewType.Byte), // unsigned on 1.8 + PLAYER_HUMAN_BYTE(ENTITY_HUMAN, 16, Type.Byte, NewType.Discontinued), // unused on 1.8 + PLAYER_ADDITIONAL_HEARTS(ENTITY_HUMAN, 17, Type.Float, 10, NewType.Float), + PLAYER_SCORE(ENTITY_HUMAN, 18, Type.Int, 11, NewType.VarInt), + PLAYER_HAND(ENTITY_HUMAN, -1, Type.NonExistent, 5, NewType.Byte), // new in 1.9 + SOMETHING_ANTICHEAT_PLUGINS_FOR_SOME_REASON_USE(ENTITY_HUMAN, 11, Type.Byte, NewType.Discontinued), //For what we know, This doesn't exists. If you think it exists and knows what it does. Please tell us. // horse - HORSE_INFO(Horse.class, 16, Type.Int, 12, NewType.Byte), - HORSE_TYPE(Horse.class, 19, Type.Byte, 13, NewType.VarInt), - HORSE_SUBTYPE(Horse.class, 20, Type.Int, 14, NewType.VarInt), - HORSE_OWNER(Horse.class, 21, Type.String, 15, NewType.OptUUID), - HORSE_ARMOR(Horse.class, 22, Type.Int, 16, NewType.VarInt), + HORSE_INFO(HORSE, 16, Type.Int, 12, NewType.Byte), + HORSE_TYPE(HORSE, 19, Type.Byte, 13, NewType.VarInt), + HORSE_SUBTYPE(HORSE, 20, Type.Int, 14, NewType.VarInt), + HORSE_OWNER(HORSE, 21, Type.String, 15, NewType.OptUUID), + HORSE_ARMOR(HORSE, 22, Type.Int, 16, NewType.VarInt), // bat - BAT_ISHANGING(Bat.class, 16, Type.Byte, 11, NewType.Byte), + BAT_ISHANGING(BAT, 16, Type.Byte, 11, NewType.Byte), // tameable - TAMING_INFO(Tameable.class, 16, Type.Byte, 12, NewType.Byte), - TAMING_OWNER(Tameable.class, 17, Type.String, 13, NewType.OptUUID), + TAMING_INFO(ENTITY_TAMEABLE_ANIMAL, 16, Type.Byte, 12, NewType.Byte), + TAMING_OWNER(ENTITY_TAMEABLE_ANIMAL, 17, Type.String, 13, NewType.OptUUID), // ocelot - OCELOT_TYPE(Ocelot.class, 18, Type.Byte, 14, NewType.VarInt), + OCELOT_TYPE(OCELOT, 18, Type.Byte, 14, NewType.VarInt), // wolf - WOLF_HEALTH(Wolf.class, 18, Type.Float, 14, NewType.Float), - WOLF_BEGGING(Wolf.class, 19, Type.Byte, 15, NewType.Boolean), - WOLF_COLLAR(Wolf.class, 20, Type.Byte, 16, NewType.VarInt), + WOLF_HEALTH(WOLF, 18, Type.Float, 14, NewType.Float), + WOLF_BEGGING(WOLF, 19, Type.Byte, 15, NewType.Boolean), + WOLF_COLLAR(WOLF, 20, Type.Byte, 16, NewType.VarInt), // pig - PIG_SADDLE(Pig.class, 16, Type.Byte, 12, NewType.Boolean), + PIG_SADDLE(PIG, 16, Type.Byte, 12, NewType.Boolean), // rabbit - RABBIT_TYPE(Rabbit.class, 18, Type.Byte, 12, NewType.VarInt), + RABBIT_TYPE(RABBIT, 18, Type.Byte, 12, NewType.VarInt), // sheep - SHEEP_COLOR(Sheep.class, 16, Type.Byte, 12, NewType.Byte), + SHEEP_COLOR(SHEEP, 16, Type.Byte, 12, NewType.Byte), // villager - VILLAGER_PROFESSION(Villager.class, 16, Type.Int, 12, NewType.VarInt), + VILLAGER_PROFESSION(VILLAGER, 16, Type.Int, 12, NewType.VarInt), // enderman - ENDERMAN_BLOCK(Enderman.class, 16, Type.Short, 11, NewType.BlockID), // special case - ENDERMAN_BLOCKDATA(Enderman.class, 17, Type.Byte, 11, NewType.BlockID), // special case - ENDERMAN_ISSCREAMING(Enderman.class, 18, Type.Byte, 12, NewType.Boolean), + ENDERMAN_BLOCK(ENDERMAN, 16, Type.Short, 11, NewType.BlockID), // special case + ENDERMAN_BLOCKDATA(ENDERMAN, 17, Type.Byte, 11, NewType.BlockID), // special case + ENDERMAN_ISSCREAMING(ENDERMAN, 18, Type.Byte, 12, NewType.Boolean), // zombie - ZOMBIE_ISCHILD(Zombie.class, 12, Type.Byte, 11, NewType.Boolean), - ZOMBIE_ISVILLAGER(Zombie.class, 13, Type.Byte, 12, NewType.VarInt), - ZOMBIE_ISCONVERTING(Zombie.class, 14, Type.Byte, 13, NewType.Boolean), + ZOMBIE_ISCHILD(ZOMBIE, 12, Type.Byte, 11, NewType.Boolean), + ZOMBIE_ISVILLAGER(ZOMBIE, 13, Type.Byte, 12, NewType.VarInt), + ZOMBIE_ISCONVERTING(ZOMBIE, 14, Type.Byte, 13, NewType.Boolean), // ZOMBIE_RISINGHANDS added in 1.9 // blaze - BLAZE_ONFIRE(Blaze.class, 16, Type.Byte, 11, NewType.Byte), + BLAZE_ONFIRE(BLAZE, 16, Type.Byte, 11, NewType.Byte), // spider - SPIDER_CIMBING(Spider.class, 16, Type.Byte, 11, NewType.Byte), + SPIDER_CIMBING(SPIDER, 16, Type.Byte, 11, NewType.Byte), // creeper - CREEPER_FUSE(Creeper.class, 16, Type.Byte, 11, NewType.VarInt), // -1 idle, 1 is fuse - CREEPER_ISPOWERED(Creeper.class, 17, Type.Byte, 12, NewType.Boolean), - CREEPER_ISIGNITED(Creeper.class, 18, Type.Byte, 13, NewType.Boolean), + CREEPER_FUSE(CREEPER, 16, Type.Byte, 11, NewType.VarInt), // -1 idle, 1 is fuse + CREEPER_ISPOWERED(CREEPER, 17, Type.Byte, 12, NewType.Boolean), + CREEPER_ISIGNITED(CREEPER, 18, Type.Byte, 13, NewType.Boolean), // ghast - GHAST_ISATTACKING(Ghast.class, 16, Type.Byte, 11, NewType.Boolean), + GHAST_ISATTACKING(GHAST, 16, Type.Byte, 11, NewType.Boolean), // slime - SLIME_SIZE(Slime.class, 16, Type.Byte, 11, NewType.VarInt), + SLIME_SIZE(SLIME, 16, Type.Byte, 11, NewType.VarInt), // skeleton - SKELETON_TYPE(Skeleton.class, 13, Type.Byte, 11, NewType.VarInt), + SKELETON_TYPE(SKELETON, 13, Type.Byte, 11, NewType.VarInt), // witch - WITCH_AGGRO(Witch.class, 21, Type.Byte, 11, NewType.Boolean), + WITCH_AGGRO(WITCH, 21, Type.Byte, 11, NewType.Boolean), // iron golem - IRON_PLAYERMADE(IronGolem.class, 16, Type.Byte, 11, NewType.Byte), + IRON_PLAYERMADE(IRON_GOLEM, 16, Type.Byte, 11, NewType.Byte), // wither - WITHER_TARGET1(Wither.class, 17, Type.Int, 11, NewType.VarInt), - WITHER_TARGET2(Wither.class, 18, Type.Int, 12, NewType.VarInt), - WITHER_TARGET3(Wither.class, 19, Type.Int, 13, NewType.VarInt), - WITHER_INVULN_TIME(Wither.class, 20, Type.Int, 14, NewType.VarInt), - WITHER_PROPERTIES(Wither.class, 10, Type.Byte, NewType.Byte), - WITHER_UNKNOWN(Wither.class, 11, Type.Byte, NewType.Discontinued), + WITHER_TARGET1(WITHER, 17, Type.Int, 11, NewType.VarInt), + WITHER_TARGET2(WITHER, 18, Type.Int, 12, NewType.VarInt), + WITHER_TARGET3(WITHER, 19, Type.Int, 13, NewType.VarInt), + WITHER_INVULN_TIME(WITHER, 20, Type.Int, 14, NewType.VarInt), + WITHER_PROPERTIES(WITHER, 10, Type.Byte, NewType.Byte), + WITHER_UNKNOWN(WITHER, 11, Type.Byte, NewType.Discontinued), // wither skull - WITHERSKULL_INVULN(WitherSkull.class, 10, Type.Byte, 5, NewType.Boolean), + WITHERSKULL_INVULN(WITHER_SKULL, 10, Type.Byte, 5, NewType.Boolean), // guardian - GUARDIAN_INFO(Guardian.class, 16, Type.Int, 11, NewType.Byte), - GUARDIAN_TARGET(Guardian.class, 17, Type.Int, 12, NewType.VarInt), + GUARDIAN_INFO(GUARDIAN, 16, Type.Int, 11, NewType.Byte), + GUARDIAN_TARGET(GUARDIAN, 17, Type.Int, 12, NewType.VarInt), // boat - BOAT_SINCEHIT(Boat.class, 17, Type.Int, 5, NewType.VarInt), - BOAT_FORWARDDIR(Boat.class, 18, Type.Int, 6, NewType.VarInt), - BOAT_DMGTAKEN(Boat.class, 19, Type.Float, 7, NewType.Float), + BOAT_SINCEHIT(BOAT, 17, Type.Int, 5, NewType.VarInt), + BOAT_FORWARDDIR(BOAT, 18, Type.Int, 6, NewType.VarInt), + BOAT_DMGTAKEN(BOAT, 19, Type.Float, 7, NewType.Float), // BOAT_TYPE in 1.9 // minecart - MINECART_SHAKINGPOWER(Minecart.class, 17, Type.Int, 5, NewType.VarInt), - MINECART_SHAKINGDIRECTION(Minecart.class, 18, Type.Int, 6, NewType.VarInt), - MINECART_DAMAGETAKEN(Minecart.class, 19, Type.Float, 7, NewType.Float), // also shaking modifier :P - MINECART_BLOCK(Minecart.class, 20, Type.Int, 8, NewType.VarInt), - MINECART_BLOCK_Y(Minecart.class, 21, Type.Int, 9, NewType.VarInt), - MINECART_SHOWBLOCK(Minecart.class, 22, Type.Byte, 10, NewType.Boolean), + MINECART_SHAKINGPOWER(MINECART_ABSTRACT, 17, Type.Int, 5, NewType.VarInt), + MINECART_SHAKINGDIRECTION(MINECART_ABSTRACT, 18, Type.Int, 6, NewType.VarInt), + MINECART_DAMAGETAKEN(MINECART_ABSTRACT, 19, Type.Float, 7, NewType.Float), // also shaking modifier :P + MINECART_BLOCK(MINECART_ABSTRACT, 20, Type.Int, 8, NewType.VarInt), + MINECART_BLOCK_Y(MINECART_ABSTRACT, 21, Type.Int, 9, NewType.VarInt), + MINECART_SHOWBLOCK(MINECART_ABSTRACT, 22, Type.Byte, 10, NewType.Boolean), // Command minecart (they are still broken) - MINECART_COMMANDBLOCK_COMMAND(Minecart.class, 23, Type.String, 11, NewType.String), - MINECART_COMMANDBLOCK_OUTPUT(Minecart.class, 24, Type.String, 12, NewType.Chat), + MINECART_COMMANDBLOCK_COMMAND(MINECART_ABSTRACT, 23, Type.String, 11, NewType.String), + MINECART_COMMANDBLOCK_OUTPUT(MINECART_ABSTRACT, 24, Type.String, 12, NewType.Chat), // furnace cart - FURNACECART_ISPOWERED(Minecart.class, 16, Type.Byte, 11, NewType.Boolean), + FURNACECART_ISPOWERED(MINECART_ABSTRACT, 16, Type.Byte, 11, NewType.Boolean), // item drop - ITEM_ITEM(Item.class, 10, Type.Slot, 5, NewType.Slot), + ITEM_ITEM(DROPPED_ITEM, 10, Type.Slot, 5, NewType.Slot), // arrow - ARROW_ISCRIT(Arrow.class, 16, Type.Byte, 5, NewType.Byte), + ARROW_ISCRIT(ARROW, 16, Type.Byte, 5, NewType.Byte), // firework - FIREWORK_INFO(Firework.class, 8, Type.Slot, 5, NewType.Slot), + FIREWORK_INFO(FIREWORK, 8, Type.Slot, 5, NewType.Slot), // item frame - ITEMFRAME_ITEM(ItemFrame.class, 8, Type.Slot, 5, NewType.Slot), - ITEMFRAME_ROTATION(ItemFrame.class, 9, Type.Byte, 6, NewType.VarInt), + ITEMFRAME_ITEM(ITEM_FRAME, 8, Type.Slot, 5, NewType.Slot), + ITEMFRAME_ROTATION(ITEM_FRAME, 9, Type.Byte, 6, NewType.VarInt), // ender crystal - ENDERCRYSTAL_HEALTH(EnderCrystal.class, 8, Type.Int, NewType.Discontinued), + ENDERCRYSTAL_HEALTH(ENDER_CRYSTAL, 8, Type.Int, NewType.Discontinued), // Ender dragon boss bar issues - ENDERDRAGON_UNKNOWN(EnderDragon.class, 5, Type.Byte, NewType.Discontinued), - ENDERDRAGON_NAME(EnderDragon.class, 10, Type.String, NewType.Discontinued), + ENDERDRAGON_UNKNOWN(ENDER_DRAGON, 5, Type.Byte, NewType.Discontinued), + ENDERDRAGON_NAME(ENDER_DRAGON, 10, Type.String, NewType.Discontinued), // Normal Ender dragon - ENDERDRAGON_FLAG(EnderDragon.class, 15, Type.Byte, NewType.Discontinued), - ENDERDRAGON_PHASE(EnderDragon.class, 11, Type.Byte, NewType.VarInt); + ENDERDRAGON_FLAG(ENDER_DRAGON, 15, Type.Byte, NewType.Discontinued), + ENDERDRAGON_PHASE(ENDER_DRAGON, 11, Type.Byte, NewType.VarInt); - private Class clazz; + private static final HashMap, MetaIndex> metadataRewrites = new HashMap<>(); + + static { + for (MetaIndex index : MetaIndex.values()) + metadataRewrites.put(new Pair<>(index.getClazz(), index.getIndex()), index); + } + + private EntityUtil.EntityType clazz; private int newIndex; private NewType newType; private Type oldType; private int index; - MetaIndex(Class type, int index, Type oldType, NewType newType) { + MetaIndex(EntityUtil.EntityType type, int index, Type oldType, NewType newType) { this.clazz = type; this.index = index; this.newIndex = index; @@ -148,7 +161,7 @@ public enum MetaIndex { this.newType = newType; } - MetaIndex(Class type, int index, Type oldType, int newIndex, NewType newType) { + MetaIndex(EntityUtil.EntityType type, int index, Type oldType, int newIndex, NewType newType) { this.clazz = type; this.index = index; this.oldType = oldType; @@ -156,37 +169,29 @@ public enum MetaIndex { this.newType = newType; } - public static MetaIndex getIndex(EntityType type, int index) { - Class entityClass = type == null ? LivingEntity.class : type.getEntityClass(); - if (entityClass == null) { - System.out.println("Could not get entity class for " + type); - return null; + private static Optional getIndex(EntityUtil.EntityType type, int index) { + Pair pair = new Pair<>(type, index); + if (metadataRewrites.containsKey(pair)) { + return Optional.of(metadataRewrites.get(pair)); } - for (MetaIndex mi : MetaIndex.values()) { - if (mi.getIndex() == index) { - // To fix issue with armour stands colliding with new values - if (mi.getApplicableClass().equals(LivingEntity.class)) continue; - if ((mi.getApplicableClass().isAssignableFrom(entityClass) || - mi.getApplicableClass().equals(entityClass))) { - return mi; - } + return Optional.absent(); + } + + public static MetaIndex searchIndex(EntityUtil.EntityType type, int index) { + EntityUtil.EntityType currentType = type; + do { + Optional optMeta = getIndex(currentType, index); + + if (optMeta.isPresent()){ + return optMeta.get(); } - } - // fall back to living entity - for (MetaIndex mi : MetaIndex.values()) { - if (mi.getIndex() == index) { - if (mi.getApplicableClass().isAssignableFrom(LivingEntity.class) || - mi.getApplicableClass().equals(LivingEntity.class)) { - return mi; - } - } - } + + currentType = currentType.getParent(); + } while (currentType != null); + return null; } - public Class getApplicableClass() { - return this.clazz; - } } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java index 713a9fdaf..6a3ce503d 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/metadata/MetadataRewriter.java @@ -1,6 +1,5 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata; -import org.bukkit.entity.EntityType; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.minecraft.EulerAngle; import us.myles.ViaVersion.api.minecraft.Vector; @@ -8,17 +7,18 @@ import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; import us.myles.ViaVersion.protocols.protocol1_9to1_8.ItemRewriter; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.util.EntityUtil; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class MetadataRewriter { - public static void transform(EntityType type, List list) { + public static void transform(EntityUtil.EntityType type, List list) { short id = -1; int data = -1; for (Metadata entry : new ArrayList<>(list)) { - MetaIndex metaIndex = MetaIndex.getIndex(type, entry.getId()); + MetaIndex metaIndex = MetaIndex.searchIndex(type, entry.getId()); try { if (metaIndex != null) { if (metaIndex.getNewType() != NewType.Discontinued) { @@ -38,7 +38,7 @@ public class MetadataRewriter { entry.setValue(((Integer) value).byteValue()); } // After writing the last one - if (metaIndex == MetaIndex.ENTITY_STATUS && type == EntityType.PLAYER) { + if (metaIndex == MetaIndex.ENTITY_STATUS && type == EntityUtil.EntityType.PLAYER) { Byte val = 0; if ((((Byte) value) & 0x10) == 0x10) { // Player eating/aiming/drinking val = 1; diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java index f190257bf..7b3455f4c 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/PlayerPackets.java @@ -2,7 +2,6 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.packets; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import org.bukkit.entity.EntityType; import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.minecraft.item.Item; @@ -20,6 +19,7 @@ import us.myles.ViaVersion.protocols.protocol1_9to1_8.chat.ChatRewriter; import us.myles.ViaVersion.protocols.protocol1_9to1_8.chat.GameMode; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; +import us.myles.ViaVersion.util.EntityUtil; public class PlayerPackets { public static void register(Protocol protocol) { @@ -165,7 +165,7 @@ public class PlayerPackets { public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.PLAYER); + tracker.getClientEntityTypes().put(entityID, EntityUtil.EntityType.PLAYER); tracker.setEntityID(entityID); } }); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java index a60e6a9de..d286f2067 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/SpawnPackets.java @@ -1,6 +1,5 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.packets; -import org.bukkit.entity.EntityType; import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.minecraft.item.Item; import us.myles.ViaVersion.api.minecraft.metadata.Metadata; @@ -96,7 +95,7 @@ public class SpawnPackets { final int data = wrapper.get(Type.INT, 0); // Data int typeID = wrapper.get(Type.BYTE, 0); - if (EntityUtil.getTypeFromID(typeID, true) == EntityType.SPLASH_POTION) { + if (EntityUtil.getTypeFromID(typeID, true) == EntityUtil.EntityType.SPLASH_POTION) { // Convert this to meta data, woo! PacketWrapper metaPacket = wrapper.create(0x39, new ValueCreator() { @Override @@ -130,7 +129,7 @@ public class SpawnPackets { public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.EXPERIENCE_ORB); + tracker.getClientEntityTypes().put(entityID, EntityUtil.EntityType.EXPERIENCE_ORB); tracker.sendMetadataBuffer(entityID); } }); @@ -156,7 +155,7 @@ public class SpawnPackets { // Currently only lightning uses this int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.LIGHTNING); + tracker.getClientEntityTypes().put(entityID, EntityUtil.EntityType.LIGHTNING); tracker.sendMetadataBuffer(entityID); } }); @@ -247,7 +246,7 @@ public class SpawnPackets { public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.PAINTING); + tracker.getClientEntityTypes().put(entityID, EntityUtil.EntityType.PAINTING); tracker.sendMetadataBuffer(entityID); } }); @@ -281,7 +280,7 @@ public class SpawnPackets { public void handle(PacketWrapper wrapper) throws Exception { int entityID = wrapper.get(Type.VAR_INT, 0); EntityTracker tracker = wrapper.user().get(EntityTracker.class); - tracker.getClientEntityTypes().put(entityID, EntityType.PLAYER); + tracker.getClientEntityTypes().put(entityID, EntityUtil.EntityType.PLAYER); tracker.sendMetadataBuffer(entityID); } }); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java index 5b9541fbb..6e5cefa07 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/EntityTracker.java @@ -6,7 +6,6 @@ import com.google.common.collect.Sets; import io.netty.buffer.ByteBuf; import lombok.Getter; import lombok.Setter; -import org.bukkit.entity.EntityType; import us.myles.ViaVersion.api.PacketWrapper; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.boss.BossBar; @@ -24,6 +23,7 @@ import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; import us.myles.ViaVersion.protocols.protocol1_9to1_8.chat.GameMode; import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.MetadataRewriter; import us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata.NewType; +import us.myles.ViaVersion.util.EntityUtil; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -32,7 +32,7 @@ import java.util.concurrent.TimeUnit; @Getter public class EntityTracker extends StoredObject { private final Map uuidMap = new ConcurrentHashMap<>(); - private final Map clientEntityTypes = new ConcurrentHashMap<>(); + private final Map clientEntityTypes = new ConcurrentHashMap<>(); private final Map> metadataBuffer = new ConcurrentHashMap<>(); private final Map vehicleMap = new ConcurrentHashMap<>(); private final Map bossBarMap = new ConcurrentHashMap<>(); @@ -118,37 +118,37 @@ public class EntityTracker extends StoredObject { return; } - EntityType type = clientEntityTypes.get(entityID); + EntityUtil.EntityType type = clientEntityTypes.get(entityID); for (Metadata metadata : new ArrayList<>(metadataList)) { // Fix: wither (crash fix) - if (type == EntityType.WITHER) { + if (type == EntityUtil.EntityType.WITHER) { if (metadata.getId() == 10) { metadataList.remove(metadata); //metadataList.add(new Metadata(10, NewType.Byte.getTypeID(), Type.BYTE, 0)); } } // Fix: enderdragon (crash fix) - if (type == EntityType.ENDER_DRAGON) { + if (type == EntityUtil.EntityType.ENDER_DRAGON) { if (metadata.getId() == 11) { metadataList.remove(metadata); // metadataList.add(new Metadata(11, NewType.Byte.getTypeID(), Type.VAR_INT, 0)); } } - if (type == EntityType.SKELETON) { + if (type == EntityUtil.EntityType.SKELETON) { if ((getMetaByIndex(metadataList, 12)) == null) { metadataList.add(new Metadata(12, NewType.Boolean.getTypeID(), Type.BOOLEAN, true)); } } //ECHOPET Patch - if (type == EntityType.HORSE) { + if (type == EntityUtil.EntityType.HORSE) { // Wrong metadata value from EchoPet, patch since it's discontinued. (https://github.com/DSH105/EchoPet/blob/06947a8b08ce40be9a518c2982af494b3b99d140/modules/API/src/main/java/com/dsh105/echopet/compat/api/entity/HorseArmour.java#L22) if (metadata.getId() == 16 && (int) metadata.getValue() == Integer.MIN_VALUE) metadata.setValue(0); } - if (type == EntityType.PLAYER) { + if (type == EntityUtil.EntityType.PLAYER) { if (metadata.getId() == 0) { // Byte byte data = (byte) metadata.getValue(); @@ -164,7 +164,7 @@ public class EntityTracker extends StoredObject { } } } - if (type == EntityType.ARMOR_STAND && ViaVersion.getConfig().isHologramPatch()) { + if (type == EntityUtil.EntityType.ARMOR_STAND && Via.getConfig().isHologramPatch()) { if (metadata.getId() == 0 && getMetaByIndex(metadataList, 10) != null) { Metadata meta = getMetaByIndex(metadataList, 10); //Only happens if the armorstand is small byte data = (byte) metadata.getValue(); @@ -192,11 +192,11 @@ public class EntityTracker extends StoredObject { UUID uuid = getUser().get(ProtocolInfo.class).getUuid(); // Boss bar if (Via.getConfig().isBossbarPatch()) { - if (type == EntityType.ENDER_DRAGON || type == EntityType.WITHER) { + if (type == EntityUtil.EntityType.ENDER_DRAGON || type == EntityUtil.EntityType.WITHER) { if (metadata.getId() == 2) { BossBar bar = bossBarMap.get(entityID); String title = (String) metadata.getValue(); - title = title.isEmpty() ? (type == EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither") : title; + title = title.isEmpty() ? (type == EntityUtil.EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither") : title; if (bar == null) { bar = Via.getAPI().createBossBar(title, BossColor.PINK, BossStyle.SOLID); bossBarMap.put(entityID, bar); @@ -208,10 +208,10 @@ public class EntityTracker extends StoredObject { } else if (metadata.getId() == 6 && !Via.getConfig().isBossbarAntiflicker()) { // If anti flicker is enabled, don't update health BossBar bar = bossBarMap.get(entityID); // Make health range between 0 and 1 - float maxHealth = type == EntityType.ENDER_DRAGON ? 200.0f : 300.0f; + float maxHealth = type == EntityUtil.EntityType.ENDER_DRAGON ? 200.0f : 300.0f; float health = Math.max(0.0f, Math.min(((float) metadata.getValue()) / maxHealth, 1.0f)); if (bar == null) { - String title = type == EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither"; + String title = type == EntityUtil.EntityType.ENDER_DRAGON ? "Ender Dragon" : "Wither"; bar = Via.getAPI().createBossBar(title, health, BossColor.PINK, BossStyle.SOLID); bossBarMap.put(entityID, bar); bar.addPlayer(uuid); diff --git a/common/src/main/java/us/myles/ViaVersion/util/EntityUtil.java b/common/src/main/java/us/myles/ViaVersion/util/EntityUtil.java index 696f8a576..d1a3075dd 100644 --- a/common/src/main/java/us/myles/ViaVersion/util/EntityUtil.java +++ b/common/src/main/java/us/myles/ViaVersion/util/EntityUtil.java @@ -1,92 +1,186 @@ package us.myles.ViaVersion.util; -import org.bukkit.entity.EntityType; +import com.google.common.base.Optional; +import lombok.AllArgsConstructor; +import lombok.Getter; +import us.myles.ViaVersion.api.Via; public class EntityUtil { public static EntityType getTypeFromID(int typeID, boolean isObject) { - if (isObject) { - return getObjectFromID(typeID); - } else { - return EntityType.fromId(typeID); + Optional type; + + if (isObject) + type = PCObjectTypes.getPCEntity(typeID); + else + type = EntityType.findById(typeID); + + if (!type.isPresent()) { + Via.getPlatform().getLogger().severe("Could not find type id " + typeID + " isObject=" + isObject); + return EntityType.ENTITY; // Fall back to the basic ENTITY + } + + return type.get(); + } + + @AllArgsConstructor + @Getter + public enum EntityType { + ENTITY(-1), + DROPPED_ITEM(1, EntityType.ENTITY), + EXPERIENCE_ORB(2, EntityType.ENTITY), + LEASH_HITCH(8, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata + PAINTING(9, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata + ARROW(10, EntityType.ENTITY), + SNOWBALL(11, EntityType.ENTITY), // Actually EntityProjectile + FIREBALL(12, EntityType.ENTITY), + SMALL_FIREBALL(13, EntityType.ENTITY), + ENDER_PEARL(14, EntityType.ENTITY), // Actually EntityProjectile + ENDER_SIGNAL(15, EntityType.ENTITY), + THROWN_EXP_BOTTLE(17, EntityType.ENTITY), + ITEM_FRAME(18, EntityType.ENTITY), // Actually EntityHanging + WITHER_SKULL(19, EntityType.ENTITY), + PRIMED_TNT(20, EntityType.ENTITY), + FALLING_BLOCK(21, EntityType.ENTITY), + FIREWORK(22, EntityType.ENTITY), + TIPPED_ARROW(23, EntityType.ARROW), + SPECTRAL_ARROW(24, EntityType.ARROW), + SHULKER_BULLET(25, EntityType.ENTITY), + DRAGON_FIREBALL(26, EntityType.FIREBALL), + + ENTITY_LIVING(-1, ENTITY), + ENTITY_INSENTIENT(-1, ENTITY_LIVING), + ENTITY_AGEABLE(-1, ENTITY_INSENTIENT), + ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE), + ENTITY_HUMAN(-1, ENTITY_LIVING), + + ARMOR_STAND(30, EntityType.ENTITY_LIVING), + + // Vehicles + MINECART_ABSTRACT(-1, ENTITY), + MINECART_COMMAND(40, MINECART_ABSTRACT), + BOAT(41, ENTITY), + MINECART_RIDEABLE(42, MINECART_ABSTRACT), + MINECART_CHEST(43, MINECART_ABSTRACT), + MINECART_FURNACE(44, MINECART_ABSTRACT), + MINECART_TNT(45, MINECART_ABSTRACT), + MINECART_HOPPER(46, MINECART_ABSTRACT), + MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT), + + CREEPER(50, ENTITY_INSENTIENT), + SKELETON(51, ENTITY_INSENTIENT), + SPIDER(52, ENTITY_INSENTIENT), + GIANT(53, ENTITY_INSENTIENT), + ZOMBIE(54, ENTITY_INSENTIENT), + SLIME(55, ENTITY_INSENTIENT), + GHAST(56, ENTITY_INSENTIENT), + PIG_ZOMBIE(57, ZOMBIE), + ENDERMAN(58, ENTITY_INSENTIENT), + CAVE_SPIDER(59, SPIDER), + SILVERFISH(60, ENTITY_INSENTIENT), + BLAZE(61, ENTITY_INSENTIENT), + MAGMA_CUBE(62, SLIME), + ENDER_DRAGON(63, ENTITY_INSENTIENT), + WITHER(64, ENTITY_INSENTIENT), + BAT(65, ENTITY_INSENTIENT), + WITCH(66, ENTITY_INSENTIENT), + ENDERMITE(67, ENTITY_INSENTIENT), + GUARDIAN(68, ENTITY_INSENTIENT), + IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references + SHULKER(69, EntityType.IRON_GOLEM), + PIG(90, ENTITY_AGEABLE), + SHEEP(91, ENTITY_AGEABLE), + COW(92, ENTITY_AGEABLE), + CHICKEN(93, ENTITY_AGEABLE), + SQUID(94, ENTITY_INSENTIENT), + WOLF(95, ENTITY_TAMEABLE_ANIMAL), + MUSHROOM_COW(96, COW), + SNOWMAN(97, EntityType.IRON_GOLEM), + OCELOT(98, ENTITY_TAMEABLE_ANIMAL), + HORSE(100, ENTITY_AGEABLE), + RABBIT(101, ENTITY_AGEABLE), + POLAR_BEAR(102, ENTITY_AGEABLE), + VILLAGER(120, ENTITY_AGEABLE), + ENDER_CRYSTAL(200, ENTITY), + SPLASH_POTION(-1, ENTITY), + LINGERING_POTION(-1, SPLASH_POTION), + AREA_EFFECT_CLOUD(-1, ENTITY), + EGG(-1, ENTITY), + FISHING_HOOK(-1, ENTITY), + LIGHTNING(-1, ENTITY), + WEATHER(-1, ENTITY), + PLAYER(-1, ENTITY_HUMAN), + COMPLEX_PART(-1, ENTITY); + + private final int id; + private final EntityType parent; + + EntityType(int id) { + this.id = id; + this.parent = null; + } + + public static Optional findById(int id) { + if (id == -1) // Check if this is called + return Optional.absent(); + + for (EntityType ent : EntityType.values()) + if (ent.getId() == id) + return Optional.of(ent); + + return Optional.absent(); } } - // based on http://wiki.vg/index.php?title=Entities - public static EntityType getObjectFromID(int objectID) { - EntityType type; - switch (objectID) { - case 2: - type = EntityType.DROPPED_ITEM; - break; - case 77: - type = EntityType.LEASH_HITCH; - break; - case 60: - type = EntityType.ARROW; - break; - case 61: - type = EntityType.SNOWBALL; - break; - case 63: - type = EntityType.FIREBALL; - break; - case 64: - type = EntityType.SMALL_FIREBALL; - break; - case 65: - type = EntityType.ENDER_PEARL; - break; - case 72: - type = EntityType.ENDER_SIGNAL; - break; - case 75: - type = EntityType.THROWN_EXP_BOTTLE; - break; - case 71: - type = EntityType.ITEM_FRAME; - break; - case 66: - type = EntityType.WITHER_SKULL; - break; - case 50: - type = EntityType.PRIMED_TNT; - break; - case 70: - type = EntityType.FALLING_BLOCK; - break; - case 76: - type = EntityType.FIREWORK; - break; - case 78: - type = EntityType.ARMOR_STAND; - break; - case 1: - type = EntityType.BOAT; - break; - case 10: - type = EntityType.MINECART; - break; - case 51: - type = EntityType.ENDER_CRYSTAL; - break; - case 73: - type = EntityType.SPLASH_POTION; - break; - case 62: - type = EntityType.EGG; - break; - case 90: - type = EntityType.FISHING_HOOK; - break; - default: - type = EntityType.fromId(objectID); - if (type == null) { - System.out.println("Unable to find entity type for " + objectID); - type = EntityType.UNKNOWN; - } - break; + @AllArgsConstructor + @Getter + public enum PCObjectTypes { + BOAT(1, EntityType.BOAT), + ITEM(2, EntityType.DROPPED_ITEM), + AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD), + MINECART(10, EntityType.MINECART_ABSTRACT), + TNT_PRIMED(50, EntityType.PRIMED_TNT), + ENDER_CRYSTAL(51, EntityType.ENDER_CRYSTAL), + TIPPED_ARROW(60, EntityType.TIPPED_ARROW), + SNOWBALL(61, EntityType.SNOWBALL), + EGG(62, EntityType.EGG), + FIREBALL(63, EntityType.FIREBALL), + SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL), + ENDER_PEARL(65, EntityType.ENDER_PEARL), + WITHER_SKULL(66, EntityType.WITHER_SKULL), + SHULKER_BULLET(67, EntityType.SHULKER_BULLET), + FALLING_BLOCK(70, EntityType.FALLING_BLOCK), + ITEM_FRAME(71, EntityType.ITEM_FRAME), + ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL), + POTION(73, EntityType.SPLASH_POTION), + THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE), + FIREWORK(76, EntityType.FIREWORK), + LEASH(77, EntityType.LEASH_HITCH), + ARMOR_STAND(78, EntityType.ARMOR_STAND), + FISHIHNG_HOOK(90, EntityType.FISHING_HOOK), + SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW), + DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL); + + private final int id; + private final EntityType type; + + public static Optional findById(int id) { + if (id == -1) + return Optional.absent(); + + for (PCObjectTypes ent : PCObjectTypes.values()) + if (ent.getId() == id) + return Optional.of(ent); + + return Optional.absent(); + } + + public static Optional getPCEntity(int id) { + Optional output = findById(id); + + if (!output.isPresent()) + return Optional.absent(); + return Optional.of(output.get().getType()); } - return type; } }