diff --git a/Essentials/src/com/earth2me/essentials/MobCompat.java b/Essentials/src/com/earth2me/essentials/MobCompat.java index 37387ff6c..665b28674 100644 --- a/Essentials/src/com/earth2me/essentials/MobCompat.java +++ b/Essentials/src/com/earth2me/essentials/MobCompat.java @@ -1,6 +1,7 @@ package com.earth2me.essentials; import com.earth2me.essentials.utils.EnumUtil; +import net.ess3.nms.refl.ReflUtil; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Ocelot; @@ -14,6 +15,7 @@ public class MobCompat { public static final EntityType CAT = EnumUtil.getEntityType("CAT", "OCELOT"); public enum CatType { + // These are (loosely) Mojang names for the cats SIAMESE("SIAMESE", "SIAMESE_CAT"), WHITE("WHITE", "SIAMESE_CAT"), RED("RED", "RED_CAT"), @@ -37,6 +39,7 @@ public class MobCompat { } public enum VillagerProfession { + // These are 1.14+ villager professions mapped to their respective pre-V&P profession and career NONE("FARMER", "FARMER", "NONE"), ARMORER("BLACKSMITH", "ARMORER"), BUTCHER("FARMER", "BUTCHER"), @@ -75,34 +78,17 @@ public class MobCompat { } } - public enum VillagerType { - DESERT, - JUNGLE, - PLAINS, - SAVANNA, - SNOWY, - SWAMP, - TAIGA + // Older cats are Ocelots, whereas 1.14+ cats are Cats + private static Class catClass = ReflUtil.getClassCached("org.bukkit.entity.Cat"); + private static Class catTypeClass = ReflUtil.getClassCached("org.bukkit.entity.Cat.Type"); + private static Method catSetTypeMethod = (catClass == null || catTypeClass == null) ? null : ReflUtil.getMethodCached(catClass, "setCatType", catTypeClass); + + private static boolean isNewCat() { + return (catClass != null && catTypeClass != null && catSetTypeMethod != null); } - private static Class catClass = null; - private static Class catTypeClass = null; - private static Method catSetTypeMethod = null; - private static Boolean isNewCat = null; - public static void setCatType(final Entity entity, final CatType type) { - if (isNewCat == null) { - try { - catClass = Class.forName("org.bukkit.entity.Cat"); - catTypeClass = Class.forName("org.bukkit.entity.Cat.Type"); - catSetTypeMethod = catClass.getDeclaredMethod("setCatType", catTypeClass); - isNewCat = true; - } catch (ClassNotFoundException | NoSuchMethodException e) { - isNewCat = false; - } - } - - if (isNewCat) { + if (isNewCat()) { try { catSetTypeMethod.invoke(entity, EnumUtil.valueOf(catTypeClass, type.catTypeName)); } catch (IllegalAccessException | InvocationTargetException e) { @@ -113,58 +99,114 @@ public class MobCompat { } } - private static Boolean isNewVillager = null; - private static Class villagerCareerClass = null; - private static Method villagerSetCareerMethod = null; - private static Class villagerTypeClass = null; - private static Method villagerSetTypeMethod = null; + // Older villagers have professions and careers, 1.14+ villagers only have professions + private static Class villagerCareerClass = ReflUtil.getClassCached("org.bukkit.entity.Villager.Career"); + private static Method villagerSetCareerMethod = (villagerCareerClass == null) ? null : ReflUtil.getMethodCached(Villager.class, "setCareer", villagerCareerClass); - - private static void checkVillagerEnums() { - try { - villagerCareerClass = Class.forName("org.bukkit.entity.Villager.Career"); - villagerSetCareerMethod = Villager.class.getDeclaredMethod("setCareer", villagerCareerClass); - isNewVillager = false; - } catch (ClassNotFoundException | NoSuchMethodException e) { - try { - villagerTypeClass = Class.forName("org.bukkit.entity.Villager.Type"); - villagerSetTypeMethod = Villager.class.getDeclaredMethod("setVillagerType", villagerTypeClass); - isNewVillager = true; - } catch (ClassNotFoundException | NoSuchMethodException e1) { - e1.printStackTrace(); - } - } + private static boolean isCareerVillager() { + return (villagerCareerClass != null && villagerSetCareerMethod != null); } public static void setVillagerProfession(final Entity entity, final VillagerProfession profession) { - if (isNewVillager == null) { - checkVillagerEnums(); - } - - if (isNewVillager) { + if (!isCareerVillager()) { ((Villager) entity).setProfession(profession.asEnum()); } else { ((Villager) entity).setProfession(profession.asEnum()); try { villagerSetCareerMethod.invoke(entity, EnumUtil.valueOf(villagerCareerClass, profession.oldCareer)); - } catch (IllegalAccessException | InvocationTargetException e) { + } catch (Exception e) { e.printStackTrace(); } } } - public static void setVillagerType(final Entity entity, final VillagerType type) { - if (isNewVillager == null) { - checkVillagerEnums(); - } + // Only 1.14+ villagers have biome variants + public static void setVillagerType(final Entity entity, final String type) { + Class typeEnum = ReflUtil.getClassCached("org.bukkit.entity.Villager.Type"); + if (typeEnum == null) return; - if (!isNewVillager) { - return; + Method villagerSetTypeMethod = ReflUtil.getMethodCached(Villager.class, "setVillagerType", typeEnum); + try { + villagerSetTypeMethod.invoke(entity, EnumUtil.valueOf(typeEnum, type)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Llamas only exist in 1.11+ + public static void setLlamaColor(final Entity entity, final String color) { + Class llamaClass = ReflUtil.getClassCached("org.bukkit.entity.Llama"); + if (llamaClass == null) return; + + Class colorEnum = ReflUtil.getClassCached("org.bukkit.entity.Llama.Color"); + Method setVariantMethod = ReflUtil.getMethodCached(llamaClass, "setColor"); + + try { + setVariantMethod.invoke(entity, EnumUtil.valueOf(colorEnum, color)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Parrots only exist in 1.12+ + public static void setParrotVariant(final Entity entity, final String variant) { + Class parrotClass = ReflUtil.getClassCached("org.bukkit.entity.Parrot"); + if (parrotClass == null) return; + + Class variantEnum = ReflUtil.getClassCached("org.bukkit.entity.Parrot.Variant"); + Method setVariantMethod = ReflUtil.getMethodCached(parrotClass, "setVariant"); + try { + setVariantMethod.invoke(entity, EnumUtil.valueOf(variantEnum, variant)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Tropical fish only exist in 1.13+ + public static void setTropicalFishPattern(final Entity entity, final String pattern) { + Class tropicalFishClass = ReflUtil.getClassCached("org.bukkit.entity.TropicalFish"); + if (tropicalFishClass == null) return; + + Class patternEnum = ReflUtil.getClassCached("org.bukkit.entity.TropicalFish.Pattern"); + Method setPatternMethod = ReflUtil.getMethodCached(tropicalFishClass, "setPattern"); + try { + setPatternMethod.invoke(entity, EnumUtil.valueOf(patternEnum, pattern)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Mushroom cow variant API only exists in 1.14+ + public static void setMooshroomVariant(final Entity entity, final String variant) { + Class mushroomCowClass = ReflUtil.getClassCached("org.bukkit.entity.MushroomCow"); + Class variantEnum = ReflUtil.getClassCached("org.bukkit.entity.MushroomCow.Variant"); + if (mushroomCowClass == null || variantEnum == null) return; + + Method setVariantMethod = ReflUtil.getMethodCached(mushroomCowClass, "setVariant"); + try { + setVariantMethod.invoke(entity, EnumUtil.valueOf(variantEnum, variant)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Pandas only exists in 1.14+ + public static void setPandaGene(final Entity entity, final String gene, final boolean mainGene) { + Class pandaClass = ReflUtil.getClassCached("org.bukkit.entity.Panda"); + if (pandaClass == null) return; + + Class geneEnum = ReflUtil.getClassCached("org.bukkit.entity.Panda.Gene"); + Method setGeneMethod; + + if (mainGene) { + setGeneMethod = ReflUtil.getMethodCached(pandaClass, "setMainGene"); + } else { + setGeneMethod = ReflUtil.getMethodCached(pandaClass, "setHiddenGene"); } try { - villagerSetTypeMethod.invoke(entity, EnumUtil.valueOf(villagerTypeClass, type.name())); - } catch (IllegalAccessException | InvocationTargetException e) { + setGeneMethod.invoke(entity, EnumUtil.valueOf(geneEnum, gene)); + } catch (Exception e) { e.printStackTrace(); } } diff --git a/Essentials/src/com/earth2me/essentials/MobData.java b/Essentials/src/com/earth2me/essentials/MobData.java index 58f5e4a9e..79dd7df86 100644 --- a/Essentials/src/com/earth2me/essentials/MobData.java +++ b/Essentials/src/com/earth2me/essentials/MobData.java @@ -106,44 +106,54 @@ public enum MobData { SHEPHERD_VILLAGER("shepherd", EntityType.VILLAGER, MobCompat.VillagerProfession.SHEPHERD, true), TOOLSMITH_VILLAGER("toolsmith", EntityType.VILLAGER, MobCompat.VillagerProfession.TOOLSMITH, true), WEAPONSMITH_VILLAGER("weaponsmith", EntityType.VILLAGER, MobCompat.VillagerProfession.WEAPONSMITH, true), - DESERT_VILLAGER("desert", EntityType.VILLAGER, MobCompat.VillagerType.DESERT, true), - JUNGLE_VILLAGER("jungle", EntityType.VILLAGER, MobCompat.VillagerType.JUNGLE, true), - PLAINS_VILLAGER("plains", EntityType.VILLAGER, MobCompat.VillagerType.PLAINS, true), - SAVANNA_VILLAGER("savanna", EntityType.VILLAGER, MobCompat.VillagerType.SAVANNA, true), - SNOWY_VILLAGER("snowy", EntityType.VILLAGER, MobCompat.VillagerType.SNOWY, true), - SWAMP_VILLAGER("swamp", EntityType.VILLAGER, MobCompat.VillagerType.SWAMP, true), - TAIGA_VILLAGER("taiga", EntityType.VILLAGER, MobCompat.VillagerType.TAIGA, true), + DESERT_VILLAGER("desert", EntityType.VILLAGER, "villagertype:DESERT", true), + JUNGLE_VILLAGER("jungle", EntityType.VILLAGER, "villagertype:JUNGLE", true), + PLAINS_VILLAGER("plains", EntityType.VILLAGER, "villagertype:PLAINS", true), + SAVANNA_VILLAGER("savanna", EntityType.VILLAGER, "villagertype:SAVANNA", true), + SNOWY_VILLAGER("snowy", EntityType.VILLAGER, "villagertype:SNOWY", true), + SWAMP_VILLAGER("swamp", EntityType.VILLAGER, "villagertype:SWAMP", true), + TAIGA_VILLAGER("taiga", EntityType.VILLAGER, "villagertype:TAIGA", true), SIZE_SLIME("", "<1-100>", EntityType.SLIME.getEntityClass(), Data.SIZE, true), NUM_EXPERIENCE_ORB("", "<1-2000000000>", EntityType.EXPERIENCE_ORB, Data.EXP, true), - RED_PARROT("red", EntityType.PARROT, Parrot.Variant.RED, true), - GREEN_PARROT("green", EntityType.PARROT, Parrot.Variant.GREEN, true), - BLUE_PARROT("blue", EntityType.PARROT, Parrot.Variant.BLUE, true), - CYAN_PARROT("cyan", EntityType.PARROT, Parrot.Variant.CYAN, true), - GRAY_PARROT("gray", EntityType.PARROT, Parrot.Variant.GRAY, true), - KOB_TROPICAL_FISH("kob", EntityType.TROPICAL_FISH, TropicalFish.Pattern.KOB, true), - SUNSTREAK_TROPICAL_FISH("sunstreak", EntityType.TROPICAL_FISH, TropicalFish.Pattern.SUNSTREAK, true), - SNOOPER_TROPICAL_FISH("snooper", EntityType.TROPICAL_FISH, TropicalFish.Pattern.SNOOPER, true), - DASHER_TROPICAL_FISH("dasher", EntityType.TROPICAL_FISH, TropicalFish.Pattern.DASHER, true), - BRINELY_TROPICAL_FISH("brinely", EntityType.TROPICAL_FISH, TropicalFish.Pattern.BRINELY, true), - SPOTTY_TROPICAL_FISH("spotty", EntityType.TROPICAL_FISH, TropicalFish.Pattern.SPOTTY, true), - FLOPPER_TROPICAL_FISH("flopper", EntityType.TROPICAL_FISH, TropicalFish.Pattern.FLOPPER, true), - STRIPEY_TROPICAL_FISH("stripey", EntityType.TROPICAL_FISH, TropicalFish.Pattern.STRIPEY, true), - GLITTER_TROPICAL_FISH("glitter", EntityType.TROPICAL_FISH, TropicalFish.Pattern.GLITTER, true), - BLOCKFISH_TROPICAL_FISH("blockfish", EntityType.TROPICAL_FISH, TropicalFish.Pattern.BLOCKFISH, true), - BETTY_TROPICAL_FISH("betty", EntityType.TROPICAL_FISH, TropicalFish.Pattern.BETTY, true), - CLAYFISH_TROPICAL_FISH("clayfish", EntityType.TROPICAL_FISH, TropicalFish.Pattern.CLAYFISH, true), - BROWN_MUSHROOM_COW("brown", EntityType.MUSHROOM_COW, MushroomCow.Variant.BROWN, true), - RED_MUSHROOM_COW("red", EntityType.MUSHROOM_COW, MushroomCow.Variant.RED, true), - AGGRESSIVE_PANDA("aggressive", EntityType.PANDA, Panda.Gene.AGGRESSIVE, true), - LAZY_PANDA("lazy", EntityType.PANDA, Panda.Gene.LAZY, true), - WORRIED_PANDA("worried", EntityType.PANDA, Panda.Gene.WORRIED, true), - PLAYFUL_PANDA("playful", EntityType.PANDA, Panda.Gene.PLAYFUL, true), - BROWN_PANDA("brown", EntityType.PANDA, Panda.Gene.BROWN, true), - WEAK_PANDA("weak", EntityType.PANDA, Panda.Gene.WEAK, true), - CREAMY_TRADER_LLAMA("creamy", EntityType.TRADER_LLAMA, TraderLlama.Color.CREAMY, true), - WHITE_TRADER_LLAMA("white", EntityType.TRADER_LLAMA, TraderLlama.Color.WHITE, true), - BROWN_TRADER_LLAMA("brown", EntityType.TRADER_LLAMA, TraderLlama.Color.BROWN, true), - GRAY_TRADER_LLAMA("gray", EntityType.TRADER_LLAMA, TraderLlama.Color.GRAY, true) + RED_PARROT("red", EntityType.PARROT, "parrot:RED", true), + GREEN_PARROT("green", EntityType.PARROT, "parrot:GREEN", true), + BLUE_PARROT("blue", EntityType.PARROT, "parrot:BLUE", true), + CYAN_PARROT("cyan", EntityType.PARROT, "parrot:CYAN", true), + GRAY_PARROT("gray", EntityType.PARROT, "parrot:GRAY", true), + KOB_TROPICAL_FISH("kob", EntityType.TROPICAL_FISH, "tropicalfish:KOB", true), + SUNSTREAK_TROPICAL_FISH("sunstreak", EntityType.TROPICAL_FISH, "tropicalfish:SUNSTREAK", true), + SNOOPER_TROPICAL_FISH("snooper", EntityType.TROPICAL_FISH, "tropicalfish:SNOOPER", true), + DASHER_TROPICAL_FISH("dasher", EntityType.TROPICAL_FISH, "tropicalfish:DASHER", true), + BRINELY_TROPICAL_FISH("brinely", EntityType.TROPICAL_FISH, "tropicalfish:BRINELY", true), + SPOTTY_TROPICAL_FISH("spotty", EntityType.TROPICAL_FISH, "tropicalfish:SPOTTY", true), + FLOPPER_TROPICAL_FISH("flopper", EntityType.TROPICAL_FISH, "tropicalfish:FLOPPER", true), + STRIPEY_TROPICAL_FISH("stripey", EntityType.TROPICAL_FISH, "tropicalfish:STRIPEY", true), + GLITTER_TROPICAL_FISH("glitter", EntityType.TROPICAL_FISH, "tropicalfish:GLITTER", true), + BLOCKFISH_TROPICAL_FISH("blockfish", EntityType.TROPICAL_FISH, "tropicalfish:BLOCKFISH", true), + BETTY_TROPICAL_FISH("betty", EntityType.TROPICAL_FISH, "tropicalfish:BETTY", true), + CLAYFISH_TROPICAL_FISH("clayfish", EntityType.TROPICAL_FISH, "tropicalfish:CLAYFISH", true), + BROWN_MUSHROOM_COW("brown", EntityType.MUSHROOM_COW, "mooshroom:BROWN", true), + RED_MUSHROOM_COW("red", EntityType.MUSHROOM_COW, "mooshroom:RED", true), + AGGRESSIVE_PANDA_MAIN("aggressive", EntityType.PANDA, "pandamain:AGGRESSIVE", true), + LAZY_PANDA_MAIN("lazy", EntityType.PANDA, "pandamain:LAZY", true), + WORRIED_PANDA_MAIN("worried", EntityType.PANDA, "pandamain:WORRIED", true), + PLAYFUL_PANDA_MAIN("playful", EntityType.PANDA, "pandamain:PLAYFUL", true), + BROWN_PANDA_MAIN("brown", EntityType.PANDA, "pandamain:BROWN", true), + WEAK_PANDA_MAIN("weak", EntityType.PANDA, "pandamain:WEAK", true), + AGGRESSIVE_PANDA_HIDDEN("aggressive_hidden", EntityType.PANDA, "pandahidden:AGGRESSIVE", true), + LAZY_PANDA_HIDDEN("lazy_hidden", EntityType.PANDA, "pandahidden:LAZY", true), + WORRIED_PANDA_HIDDEN("worried_hidden", EntityType.PANDA, "pandahidden:WORRIED", true), + PLAYFUL_PANDA_HIDDEN("playful_hidden", EntityType.PANDA, "pandahidden:PLAYFUL", true), + BROWN_PANDA_HIDDEN("brown_hidden", EntityType.PANDA, "pandahidden:BROWN", true), + WEAK_PANDA_HIDDEN("weak_hidden", EntityType.PANDA, "pandahidden:WEAK", true), + CREAMY_LLAMA("creamy", EntityType.LLAMA, "llama:CREAMY", true), + WHITE_LLAMA("white", EntityType.LLAMA, "llama:WHITE", true), + BROWN_LLAMA("brown", EntityType.LLAMA, "llama:BROWN", true), + GRAY_LLAMA("gray", EntityType.LLAMA, "llama:GRAY", true), + CREAMY_TRADER_LLAMA("creamy", EntityType.TRADER_LLAMA, "llama:CREAMY", true), + WHITE_TRADER_LLAMA("white", EntityType.TRADER_LLAMA, "llama:WHITE", true), + BROWN_TRADER_LLAMA("brown", EntityType.TRADER_LLAMA, "llama:BROWN", true), + GRAY_TRADER_LLAMA("gray", EntityType.TRADER_LLAMA, "llama:GRAY", true) ; @@ -292,8 +302,6 @@ public enum MobData { MobCompat.setCatType(spawned, (MobCompat.CatType) this.value); } else if (this.value instanceof MobCompat.VillagerProfession) { MobCompat.setVillagerProfession(spawned, (MobCompat.VillagerProfession) this.value); - } else if (this.value instanceof MobCompat.VillagerType) { - MobCompat.setVillagerType(spawned, (MobCompat.VillagerType) this.value); } else if (this.value instanceof Material) { if (this.type.equals(EntityType.HORSE)) { ((Horse) spawned).setTamed(true); @@ -303,16 +311,33 @@ public enum MobData { InventoryWorkaround.setItemInMainHand(invent, new ItemStack((Material) this.value, 1)); InventoryWorkaround.setItemInMainHandDropChance(invent, 0.1f); } - } else if (this.value instanceof Parrot.Variant) { // TODO: MobCompat - ((Parrot) spawned).setVariant((Parrot.Variant) this.value); - } else if (this.value instanceof TropicalFish.Pattern) { // TODO: MobCompat - ((TropicalFish) spawned).setPattern((TropicalFish.Pattern) this.value); - } else if (this.value instanceof MushroomCow.Variant) { // TODO: MobCompat - ((MushroomCow) spawned).setVariant((MushroomCow.Variant) this.value); - } else if (this.value instanceof Panda.Gene) { // TODO: MobCompat - ((Panda) spawned).setMainGene((Panda.Gene) this.value); - } else if (this.value instanceof TraderLlama.Color) { // TODO: MobCompat - ((TraderLlama) spawned).setColor((TraderLlama.Color) this.value); + } else if (this.value instanceof String) { + final String[] split = ((String) this.value).split(":"); + switch (split[0]) { + case "parrot": + MobCompat.setParrotVariant(spawned, split[1]); + break; + case "tropicalfish": + MobCompat.setTropicalFishPattern(spawned, split[1]); + break; + case "mooshroom": + MobCompat.setMooshroomVariant(spawned, split[1]); + break; + case "pandamain": + MobCompat.setPandaGene(spawned, split[1], true); + break; + case "pandahidden": + MobCompat.setPandaGene(spawned, split[1], false); + break; + case "llama": + MobCompat.setLlamaColor(spawned, split[1]); + break; + case "villagertype": + MobCompat.setVillagerType(spawned, split[1]); + break; + } + } else { + logger.warning("Unknown mob data type: " + this.toString()); } } }