diff --git a/api/src/main/java/lol/pyr/znpcsplus/util/AxolotlVariant.java b/api/src/main/java/lol/pyr/znpcsplus/util/AxolotlVariant.java new file mode 100644 index 0000000..b38b907 --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/util/AxolotlVariant.java @@ -0,0 +1,9 @@ +package lol.pyr.znpcsplus.util; + +public enum AxolotlVariant { + LUCY, + WILD, + GOLD, + CYAN, + BLUE +} diff --git a/api/src/main/java/lol/pyr/znpcsplus/util/HorseArmor.java b/api/src/main/java/lol/pyr/znpcsplus/util/HorseArmor.java new file mode 100644 index 0000000..80fa2f2 --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/util/HorseArmor.java @@ -0,0 +1,8 @@ +package lol.pyr.znpcsplus.util; + +public enum HorseArmor { + NONE, + IRON, + GOLD, + DIAMOND +} diff --git a/api/src/main/java/lol/pyr/znpcsplus/util/HorseColor.java b/api/src/main/java/lol/pyr/znpcsplus/util/HorseColor.java new file mode 100644 index 0000000..ae6327a --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/util/HorseColor.java @@ -0,0 +1,11 @@ +package lol.pyr.znpcsplus.util; + +public enum HorseColor { + WHITE, + CREAMY, + CHESTNUT, + BROWN, + BLACK, + GRAY, + DARK_BROWN +} diff --git a/api/src/main/java/lol/pyr/znpcsplus/util/HorseStyle.java b/api/src/main/java/lol/pyr/znpcsplus/util/HorseStyle.java new file mode 100644 index 0000000..b5544c4 --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/util/HorseStyle.java @@ -0,0 +1,9 @@ +package lol.pyr.znpcsplus.util; + +public enum HorseStyle { + NONE, + WHITE, + WHITEFIELD, + WHITE_DOTS, + BLACK_DOTS +} diff --git a/api/src/main/java/lol/pyr/znpcsplus/util/HorseType.java b/api/src/main/java/lol/pyr/znpcsplus/util/HorseType.java new file mode 100644 index 0000000..9526d67 --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/util/HorseType.java @@ -0,0 +1,9 @@ +package lol.pyr.znpcsplus.util; + +public enum HorseType { + HORSE, + DONKEY, + MULE, + ZOMBIE, + SKELETON +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index 9e0f44b..d414ead 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -253,6 +253,7 @@ public class ZNpcsPlus extends JavaPlugin { manager.registerParser(Color.class, new ColorParser(incorrectUsageMessage)); manager.registerParser(Vector3f.class, new Vector3fParser(incorrectUsageMessage)); + // TODO: Need to find a better way to do this registerEnumParser(manager, NpcPose.class, incorrectUsageMessage); registerEnumParser(manager, DyeColor.class, incorrectUsageMessage); registerEnumParser(manager, CatVariant.class, incorrectUsageMessage); @@ -264,6 +265,11 @@ public class ZNpcsPlus extends JavaPlugin { registerEnumParser(manager, VillagerType.class, incorrectUsageMessage); registerEnumParser(manager, VillagerProfession.class, incorrectUsageMessage); registerEnumParser(manager, VillagerLevel.class, incorrectUsageMessage); + registerEnumParser(manager, AxolotlVariant.class, incorrectUsageMessage); + registerEnumParser(manager, HorseType.class, incorrectUsageMessage); + registerEnumParser(manager, HorseStyle.class, incorrectUsageMessage); + registerEnumParser(manager, HorseColor.class, incorrectUsageMessage); + registerEnumParser(manager, HorseArmor.class, incorrectUsageMessage); manager.registerCommand("npc", new MultiCommand(loadHelpMessage("root")) .addSubcommand("create", new CreateCommand(npcRegistry, typeRegistry)) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java index 335cc16..752f8cb 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/property/PropertySetCommand.java @@ -16,7 +16,6 @@ import lol.pyr.znpcsplus.util.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Color; -import org.bukkit.DyeColor; import com.github.retrooper.packetevents.protocol.item.ItemStack; import java.util.Collections; @@ -118,19 +117,13 @@ public class PropertySetCommand implements CommandHandler { if (context.argSize() == 3) { if (type == Boolean.class) return context.suggestLiteral("true", "false"); if (type == NamedTextColor.class) return context.suggestCollection(NamedTextColor.NAMES.keys()); - if (type == NpcPose.class) return context.suggestEnum(NpcPose.values()); if (type == Color.class) return context.suggestLiteral("0x0F00FF", "#FFFFFF"); - if (type == DyeColor.class) return context.suggestEnum(DyeColor.values()); - if (type == CatVariant.class) return context.suggestEnum(CatVariant.values()); - if (type == CreeperState.class) return context.suggestEnum(CreeperState.values()); - if (type == ParrotVariant.class) return context.suggestEnum(ParrotVariant.values()); if (type == BlockState.class) return context.suggestLiteral("hand", "looking_at", "block"); - if (type == SpellType.class) return context.suggestEnum(SpellType.values()); - if (type == FoxVariant.class) return context.suggestEnum(FoxVariant.values()); - if (type == FrogVariant.class) return context.suggestEnum(FrogVariant.values()); - if (type == VillagerType.class) return context.suggestEnum(VillagerType.values()); - if (type == VillagerProfession.class) return context.suggestEnum(VillagerProfession.values()); - if (type == VillagerLevel.class) return context.suggestEnum(VillagerLevel.values()); + + // Suggest enum values directly + if (type.isEnum()) { + return context.suggestEnum((Enum[]) type.getEnumConstants()); + } } else if (context.argSize() == 4) { if (type == BlockState.class) { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java index f41eb42..56d8788 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/EntityPropertyRegistryImpl.java @@ -58,12 +58,15 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { registerEnumSerializer(VillagerType.class); registerEnumSerializer(VillagerProfession.class); registerEnumSerializer(VillagerLevel.class); + registerEnumSerializer(AxolotlVariant.class); + registerEnumSerializer(HorseType.class); + registerEnumSerializer(HorseColor.class); + registerEnumSerializer(HorseStyle.class); + registerEnumSerializer(HorseArmor.class); + /* registerType("using_item", false); // TODO: fix it for 1.8 and add new property to use offhand item and riptide animation - registerType("baby", false); // TODO - registerType("pose", NpcPose.STANDING); - // Player registerType("shoulder_entity_left", ParrotVariant.NONE); registerType("shoulder_entity_right", ParrotVariant.NONE); @@ -72,13 +75,6 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { registerType("beam_target", null); // TODO: Make a block pos class for this registerType("show_base", true); // TODO - // Axolotl - registerType("axolotl_variant", 0); - registerType("playing_dead", false); // TODO fix disabling - - // Blaze - registerType("blaze_on_fire", false); - // Creeper registerType("creeper_state", CreeperState.IDLE); registerType("creeper_charged", false); @@ -106,11 +102,6 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { // Sniffer registerType("sniffer_state", null); // TODO: Nothing on wiki.vg, look in mc source - // Horse - registerType("horse_style", 0); // TODO: Figure this out - registerType("horse_chest", false); // TODO - registerType("horse_saddle", false); // TODO - // LLama registerType("carpet_color", DyeColor.class); // TODO registerType("llama_variant", 0); // TODO @@ -217,6 +208,15 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { register(new EncodedIntegerProperty<>("potion_color", Color.class, potionIndex++, Color::asRGB)); register(new BooleanProperty("potion_ambient", potionIndex, false, legacyBooleans)); + int babyIndex; + if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) babyIndex = 16; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) babyIndex = 15; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) babyIndex = 14; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) babyIndex = 12; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) babyIndex = 11; + else babyIndex = 12; + register(new BooleanProperty("baby", babyIndex, false, legacyBooleans)); + // Player register(new DummyProperty<>("skin", SkinDescriptor.class, false)); final int skinLayersIndex; @@ -273,7 +273,80 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { else batIndex = 16; register(new BooleanProperty("hanging", batIndex, false, true /* This isnt a mistake */)); + // Blaze + final int blazeIndex; + if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) blazeIndex = 16; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) blazeIndex = 15; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) blazeIndex = 14; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) blazeIndex = 12; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) blazeIndex = 11; + else blazeIndex = 16; + register(new BitsetProperty("blaze_on_fire", blazeIndex, 0x01)); + + // Creeper + int creeperIndex; + if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) creeperIndex = 16; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) creeperIndex = 15; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) creeperIndex = 14; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) creeperIndex = 12; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) creeperIndex = 11; + else creeperIndex= 16; + register(new EncodedIntegerProperty<>("creeper_state", CreeperState.IDLE, creeperIndex++, CreeperState::getState)); + register(new BooleanProperty("creeper_charged", creeperIndex, false, legacyBooleans)); + + // Abstract Horse + int horseIndex; + if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) horseIndex = 17; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) horseIndex = 16; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) horseIndex = 15; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) horseIndex = 13; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) horseIndex = 12; + else horseIndex = 16; + int horseEating = ver.isNewerThanOrEquals(ServerVersion.V_1_12) ? 0x10 : 0x20; + boolean v1_8 = ver.isOlderThan(ServerVersion.V_1_9); + register(new BitsetProperty("is_tame", horseIndex, 0x02, false, v1_8)); + register(new BitsetProperty("is_saddled", horseIndex, 0x04, false, v1_8)); + register(new BitsetProperty("is_eating", horseIndex, horseEating, false, v1_8)); + register(new BitsetProperty("is_rearing", horseIndex, horseEating << 1, false, v1_8)); + register(new BitsetProperty("has_mouth_open", horseIndex, horseEating << 2, false, v1_8)); + + // Horse + if (ver.isNewerThanOrEquals(ServerVersion.V_1_8) && ver.isOlderThan(ServerVersion.V_1_9)) { + register(new EncodedByteProperty<>("horse_type", HorseType.HORSE, 19, obj -> (byte) obj.ordinal())); + } else if (ver.isOlderThan(ServerVersion.V_1_11)) { + int horseTypeIndex = 14; + if (ver.isOlderThan(ServerVersion.V_1_10)) horseTypeIndex = 13; + register(new EncodedIntegerProperty<>("horse_type", HorseType.HORSE, horseTypeIndex, Enum::ordinal)); + } + int horseVariantIndex; + if (ver.isNewerThanOrEquals(ServerVersion.V_1_18)) horseVariantIndex = 18; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) horseVariantIndex = 19; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) horseVariantIndex = 18; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) horseVariantIndex = 17; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) horseVariantIndex = 15; + else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) horseVariantIndex = 14; + else horseVariantIndex = 20; + register(new HorseStyleProperty(horseVariantIndex)); + register(new HorseColorProperty(horseVariantIndex)); + linkProperties("horse_style", "horse_color"); + + // Use chesteplate property for 1.14 and above + if (ver.isOlderThan(ServerVersion.V_1_14)) { + register(new EncodedIntegerProperty<>("horse_armor", HorseArmor.NONE, horseVariantIndex + 2, Enum::ordinal)); + } + + // Chested Horse + if (ver.isOlderThan(ServerVersion.V_1_11)) { + register(new BitsetProperty("has_chest", horseIndex, 0x08, false, v1_8)); + linkProperties("is_saddled", "has_chest", "is_eating", "is_rearing", "has_mouth_open"); + } else { + register(new BooleanProperty("has_chest", horseVariantIndex, false, legacyBooleans)); + linkProperties("is_saddled", "is_eating", "is_rearing", "has_mouth_open"); + } + if (!ver.isNewerThanOrEquals(ServerVersion.V_1_14)) return; + // Pose + register(new NpcPoseProperty()); // Cat int catIndex; @@ -301,6 +374,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { register(new BitsetProperty("fox_faceplanted", foxIndex, 0x40)); linkProperties("fox_sitting", "fox_crouching", "fox_sleeping", "fox_faceplanted"); + // Bee int beeIndex; if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) beeIndex = 17; else beeIndex = 18; @@ -315,12 +389,20 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { register(new BooleanProperty("immune_to_zombification", zombificationIndex, false, legacyBooleans)); if (!ver.isNewerThanOrEquals(ServerVersion.V_1_17)) return; + // Axolotl + register(new EncodedIntegerProperty<>("axolotl_variant", AxolotlVariant.LUCY, 17, Enum::ordinal)); + register(new BooleanProperty("playing_dead", 18, false, legacyBooleans)); // Goat register(new BooleanProperty("has_left_horn", 18, true, legacyBooleans)); register(new BooleanProperty("has_right_horn", 19, true, legacyBooleans)); register(new EncodedIntegerProperty<>("shaking", false,7, enabled -> enabled ? 140 : 0)); + + if (!ver.isNewerThanOrEquals(ServerVersion.V_1_20)) return; + + // Camel + register(new BooleanProperty("bashing", 18, false, legacyBooleans)); } private void registerSerializer(PropertySerializer serializer) { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BitsetProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BitsetProperty.java index 579074e..1a1e5f2 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BitsetProperty.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/BitsetProperty.java @@ -12,6 +12,12 @@ public class BitsetProperty extends EntityPropertyImpl { private final int index; private final int bitmask; private final boolean inverted; + private boolean integer = false; + + public BitsetProperty(String name, int index, int bitmask, boolean inverted, boolean integer) { + this(name, index, bitmask, inverted); + this.integer = integer; + } public BitsetProperty(String name, int index, int bitmask, boolean inverted) { super(name, inverted, Boolean.class); @@ -27,9 +33,11 @@ public class BitsetProperty extends EntityPropertyImpl { @Override public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { EntityData oldData = properties.get(index); - byte oldValue = oldData == null ? 0 : (byte) oldData.getValue(); boolean enabled = entity.getProperty(this); if (inverted) enabled = !enabled; - properties.put(index, newEntityData(index, EntityDataTypes.BYTE, (byte) (oldValue | (enabled ? bitmask : 0)))); + properties.put(index, + integer ? newEntityData(index, EntityDataTypes.INT, (oldData == null ? 0 : (int) oldData.getValue()) | (enabled ? bitmask : 0)) : + newEntityData(index, EntityDataTypes.BYTE, (byte) ((oldData == null ? 0 : (byte) oldData.getValue()) | (enabled ? bitmask : 0)))); + } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedByteProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedByteProperty.java new file mode 100644 index 0000000..af64b11 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/EncodedByteProperty.java @@ -0,0 +1,48 @@ +package lol.pyr.znpcsplus.entity.properties; + +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType; +import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.PacketEntity; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class EncodedByteProperty extends EntityPropertyImpl { + private final EntityDataType type; + private final ByteDecoder decoder; + private final int index; + + protected EncodedByteProperty(String name, T defaultValue, Class clazz, int index, ByteDecoder decoder, EntityDataType type) { + super(name, defaultValue, clazz); + this.decoder = decoder; + this.index = index; + this.type = type; + } + + @SuppressWarnings("unchecked") + public EncodedByteProperty(String name, T defaultValue, int index, ByteDecoder decoder) { + this(name, defaultValue, (Class) defaultValue.getClass(), index, decoder, EntityDataTypes.BYTE); + } + + @SuppressWarnings("unchecked") + public EncodedByteProperty(String name, T defaultValue, int index, ByteDecoder decoder, EntityDataType type) { + this(name, defaultValue, (Class) defaultValue.getClass(), index, decoder, type); + } + + public EncodedByteProperty(String name, Class clazz, int index, ByteDecoder decoder) { + this(name, null, clazz, index, decoder, EntityDataTypes.BYTE); + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + T value = entity.getProperty(this); + if (value == null) return; + properties.put(index, newEntityData(index, type, decoder.decode(value))); + } + + public interface ByteDecoder { + byte decode(T obj); + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HorseColorProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HorseColorProperty.java new file mode 100644 index 0000000..b7b12ed --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HorseColorProperty.java @@ -0,0 +1,26 @@ +package lol.pyr.znpcsplus.entity.properties; + +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.util.HorseColor; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class HorseColorProperty extends EntityPropertyImpl { + private final int index; + + public HorseColorProperty(int index) { + super("horse_color", HorseColor.WHITE, HorseColor.class); + this.index = index; + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + EntityData oldData = properties.get(index); + HorseColor value = entity.getProperty(this); + properties.put(index, newEntityData(index, EntityDataTypes.INT, value.ordinal() | (oldData == null ? 0 : ((int) oldData.getValue() & 0xFF00)))); + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HorseStyleProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HorseStyleProperty.java new file mode 100644 index 0000000..ebb1b53 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/HorseStyleProperty.java @@ -0,0 +1,26 @@ +package lol.pyr.znpcsplus.entity.properties; + +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.util.HorseStyle; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class HorseStyleProperty extends EntityPropertyImpl { + private final int index; + + public HorseStyleProperty(int index) { + super("horse_style", HorseStyle.NONE, HorseStyle.class); + this.index = index; + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + EntityData oldData = properties.get(index); + HorseStyle value = entity.getProperty(this); + properties.put(index, newEntityData(index, EntityDataTypes.INT, (oldData == null ? 0 : ((int) oldData.getValue() & 0x00FF)) | (value.ordinal() << 8))); + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/NpcPoseProperty.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/NpcPoseProperty.java new file mode 100644 index 0000000..3599f64 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/properties/NpcPoseProperty.java @@ -0,0 +1,23 @@ +package lol.pyr.znpcsplus.entity.properties; + +import com.github.retrooper.packetevents.protocol.entity.data.EntityData; +import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; +import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.PacketEntity; +import lol.pyr.znpcsplus.util.NpcPose; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class NpcPoseProperty extends EntityPropertyImpl { + + public NpcPoseProperty() { + super("pose", NpcPose.STANDING, NpcPose.class); + } + + @Override + public void apply(Player player, PacketEntity entity, boolean isSpawned, Map properties) { + properties.put(6, newEntityData(6, EntityDataTypes.ENTITY_POSE, EntityPose.valueOf(entity.getProperty(this).name()))); + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ItemStackPropertySerializer.java b/plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ItemStackPropertySerializer.java index d9f59d2..c6f1cb5 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ItemStackPropertySerializer.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/entity/serializers/ItemStackPropertySerializer.java @@ -1,18 +1,19 @@ package lol.pyr.znpcsplus.entity.serializers; +import com.github.retrooper.packetevents.protocol.item.ItemStack; +import io.github.retrooper.packetevents.util.SpigotConversionUtil; import lol.pyr.znpcsplus.entity.PropertySerializer; import lol.pyr.znpcsplus.util.ItemSerializationUtil; -import org.bukkit.inventory.ItemStack; public class ItemStackPropertySerializer implements PropertySerializer { @Override public String serialize(ItemStack property) { - return ItemSerializationUtil.itemToB64(property); + return ItemSerializationUtil.itemToB64(SpigotConversionUtil.toBukkitItemStack(property)); } @Override public ItemStack deserialize(String property) { - return ItemSerializationUtil.itemFromB64(property); + return SpigotConversionUtil.fromBukkitItemStack(ItemSerializationUtil.itemFromB64(property)); } @Override diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java index 4d406c0..5a9131e 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeImpl.java @@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.npc; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import lol.pyr.znpcsplus.api.entity.EntityProperty; import lol.pyr.znpcsplus.api.npc.NpcType; import lol.pyr.znpcsplus.entity.EntityPropertyImpl; @@ -90,8 +91,24 @@ public class NpcTypeImpl implements NpcType { addProperties("fire", "invisible", "silent", "look", "using_item", "potion_color", "potion_ambient", "dinnerbone"); if (version.isNewerThanOrEquals(ServerVersion.V_1_9)) addProperties("glow"); - if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) addProperties("pose"); + if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) { + addProperties("pose"); + if (EntityTypes.isTypeInstanceOf(type, EntityTypes.HORSE)) { + addProperties("chestplate"); + } + } if (version.isNewerThanOrEquals(ServerVersion.V_1_17)) addProperties("shaking"); + if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_AGEABLE)) { + addProperties("baby"); + } + if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_HORSE)) { + addProperties("is_saddled", "is_eating", "is_rearing", "has_mouth_open"); + } + if (EntityTypes.isTypeInstanceOf(type, EntityTypes.CHESTED_HORSE)) { + addProperties("has_chest"); + } else if (version.isOlderThan(ServerVersion.V_1_11) && type.equals(EntityTypes.HORSE)) { + addProperties("has_chest"); + } return new NpcTypeImpl(name, type, hologramOffset, new HashSet<>(allowedProperties)); } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java index 9e66516..6835ead 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcTypeRegistryImpl.java @@ -88,7 +88,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { .setHologramOffset(-1.125)); register(builder(p, "horse", EntityTypes.HORSE) - .setHologramOffset(-0.375)); + .setHologramOffset(-0.375) + .addProperties("horse_type", "horse_style", "horse_color", "horse_armor")); register(builder(p, "iron_golem", EntityTypes.IRON_GOLEM) .setHologramOffset(0.725)); @@ -335,7 +336,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry { .setHologramOffset(0.125)); register(builder(p, "camel", EntityTypes.CAMEL) - .setHologramOffset(0.25)); + .setHologramOffset(0.25) + .addProperties("bashing")); } public Collection getAll() { diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java index 9f0ef66..336deab 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java @@ -65,7 +65,12 @@ public class YamlStorage implements NpcStorage { Bukkit.getLogger().log(Level.WARNING, "Unknown property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); continue; } - npc.UNSAFE_setProperty(property, propertyRegistry.getSerializer(property.getType()).deserialize(properties.getString(key))); + PropertySerializer serializer = propertyRegistry.getSerializer(property.getType()); + if (serializer == null) { + Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); + continue; + } + npc.UNSAFE_setProperty(property, serializer.deserialize(properties.getString(key))); } } HologramImpl hologram = npc.getHologram();