Merge remote-tracking branch 'origin/2.X' into 2.X
This commit is contained in:
		
						commit
						2128243fa2
					
				
					 16 changed files with 176 additions and 49 deletions
				
			
		
							
								
								
									
										7
									
								
								api/src/main/java/lol/pyr/znpcsplus/util/LookType.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								api/src/main/java/lol/pyr/znpcsplus/util/LookType.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | package lol.pyr.znpcsplus.util; | ||||||
|  | 
 | ||||||
|  | public enum LookType { | ||||||
|  |     FIXED, | ||||||
|  |     CLOSEST_PLAYER, | ||||||
|  |     PER_PLAYER | ||||||
|  | } | ||||||
|  | @ -127,7 +127,7 @@ public class ZNpcsPlus extends JavaPlugin { | ||||||
| 
 | 
 | ||||||
|         ConfigManager configManager = new ConfigManager(getDataFolder()); |         ConfigManager configManager = new ConfigManager(getDataFolder()); | ||||||
|         MojangSkinCache skinCache = new MojangSkinCache(configManager); |         MojangSkinCache skinCache = new MojangSkinCache(configManager); | ||||||
|         EntityPropertyRegistryImpl propertyRegistry = new EntityPropertyRegistryImpl(skinCache); |         EntityPropertyRegistryImpl propertyRegistry = new EntityPropertyRegistryImpl(skinCache, configManager); | ||||||
|         PacketFactory packetFactory = setupPacketFactory(scheduler, propertyRegistry); |         PacketFactory packetFactory = setupPacketFactory(scheduler, propertyRegistry); | ||||||
|         propertyRegistry.registerTypes(packetFactory); |         propertyRegistry.registerTypes(packetFactory); | ||||||
| 
 | 
 | ||||||
|  | @ -276,6 +276,7 @@ public class ZNpcsPlus extends JavaPlugin { | ||||||
|         registerEnumParser(manager, OcelotType.class, incorrectUsageMessage); |         registerEnumParser(manager, OcelotType.class, incorrectUsageMessage); | ||||||
|         registerEnumParser(manager, PandaGene.class, incorrectUsageMessage); |         registerEnumParser(manager, PandaGene.class, incorrectUsageMessage); | ||||||
|         registerEnumParser(manager, PuffState.class, incorrectUsageMessage); |         registerEnumParser(manager, PuffState.class, incorrectUsageMessage); | ||||||
|  |         registerEnumParser(manager, LookType.class, incorrectUsageMessage); | ||||||
| 
 | 
 | ||||||
|         manager.registerCommand("npc", new MultiCommand(loadHelpMessage("root")) |         manager.registerCommand("npc", new MultiCommand(loadHelpMessage("root")) | ||||||
|                 .addSubcommand("center", new CenterCommand(npcRegistry)) |                 .addSubcommand("center", new CenterCommand(npcRegistry)) | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package lol.pyr.znpcsplus.conversion.citizens.model.traits; | ||||||
| import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; | ||||||
| import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait; | import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait; | ||||||
| import lol.pyr.znpcsplus.npc.NpcImpl; | import lol.pyr.znpcsplus.npc.NpcImpl; | ||||||
|  | import lol.pyr.znpcsplus.util.LookType; | ||||||
| import org.bukkit.configuration.ConfigurationSection; | import org.bukkit.configuration.ConfigurationSection; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
|  | @ -16,7 +17,7 @@ public class LookTrait extends SectionCitizensTrait { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) { |     public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) { | ||||||
|         if (section.getBoolean("enabled")) npc.setProperty(registry.getByName("look", Boolean.class), true); |         if (section.getBoolean("enabled")) npc.setProperty(registry.getByName("look", LookType.class), LookType.CLOSEST_PLAYER); | ||||||
|         return npc; |         return npc; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -28,13 +28,16 @@ import lol.pyr.znpcsplus.scheduling.TaskScheduler; | ||||||
| import lol.pyr.znpcsplus.skin.Skin; | import lol.pyr.znpcsplus.skin.Skin; | ||||||
| import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; | import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; | ||||||
| import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor; | import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor; | ||||||
|  | import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor; | ||||||
| import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor; | import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor; | ||||||
| import lol.pyr.znpcsplus.util.BungeeConnector; | import lol.pyr.znpcsplus.util.BungeeConnector; | ||||||
| import lol.pyr.znpcsplus.util.ItemSerializationUtil; | import lol.pyr.znpcsplus.util.ItemSerializationUtil; | ||||||
|  | import lol.pyr.znpcsplus.util.LookType; | ||||||
| import lol.pyr.znpcsplus.util.NpcLocation; | import lol.pyr.znpcsplus.util.NpcLocation; | ||||||
| import net.kyori.adventure.platform.bukkit.BukkitAudiences; | import net.kyori.adventure.platform.bukkit.BukkitAudiences; | ||||||
| import net.kyori.adventure.text.Component; | import net.kyori.adventure.text.Component; | ||||||
| import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; | ||||||
|  | import org.bukkit.DyeColor; | ||||||
| import org.bukkit.inventory.ItemStack; | import org.bukkit.inventory.ItemStack; | ||||||
| 
 | 
 | ||||||
| import java.io.BufferedReader; | import java.io.BufferedReader; | ||||||
|  | @ -129,6 +132,23 @@ public class ZNpcImporter implements DataImporter { | ||||||
|                 npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new Skin(model.getSkin(), model.getSignature()))); |                 npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new Skin(model.getSkin(), model.getSignature()))); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             Map<String, Object> toggleValues = model.getNpcToggleValues(); | ||||||
|  |             if (toggleValues != null) { | ||||||
|  |                 if (toggleValues.containsKey("look")) { | ||||||
|  |                     npc.setProperty(propertyRegistry.getByName("look", LookType.class), LookType.CLOSEST_PLAYER); | ||||||
|  |                 } | ||||||
|  |                 if (toggleValues.containsKey("mirror")) { | ||||||
|  |                     npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new MirrorDescriptor(skinCache)); | ||||||
|  |                 } | ||||||
|  |                 if (toggleValues.containsKey("glow")) { | ||||||
|  |                     try { | ||||||
|  |                         npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.valueOf((String) toggleValues.get("glow"))); | ||||||
|  |                     } catch (IllegalArgumentException e) { | ||||||
|  |                         npc.setProperty(propertyRegistry.getByName("glow", DyeColor.class), DyeColor.WHITE); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             NpcEntryImpl entry = new NpcEntryImpl(String.valueOf(model.getId()), npc); |             NpcEntryImpl entry = new NpcEntryImpl(String.valueOf(model.getId()), npc); | ||||||
|             entry.enableEverything(); |             entry.enableEverything(); | ||||||
|             entries.add(entry); |             entries.add(entry); | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ public class ZNpcsModel { | ||||||
|     private List<String> hologramLines; |     private List<String> hologramLines; | ||||||
|     private List<ZNpcsAction> clickActions; |     private List<ZNpcsAction> clickActions; | ||||||
|     private Map<String, String> npcEquip; |     private Map<String, String> npcEquip; | ||||||
|  |     private Map<String, Object> npcToggleValues; | ||||||
|     private Map<String, String[]> customizationMap; |     private Map<String, String[]> customizationMap; | ||||||
| 
 | 
 | ||||||
|     public int getId() { |     public int getId() { | ||||||
|  | @ -57,6 +58,10 @@ public class ZNpcsModel { | ||||||
|         return npcEquip; |         return npcEquip; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public Map<String, Object> getNpcToggleValues() { | ||||||
|  |         return npcToggleValues; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public Map<String, String[]> getCustomizationMap() { |     public Map<String, String[]> getCustomizationMap() { | ||||||
|         return customizationMap; |         return customizationMap; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ import com.github.retrooper.packetevents.protocol.player.EquipmentSlot; | ||||||
| import lol.pyr.znpcsplus.api.entity.EntityProperty; | import lol.pyr.znpcsplus.api.entity.EntityProperty; | ||||||
| import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; | import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry; | ||||||
| import lol.pyr.znpcsplus.api.skin.SkinDescriptor; | import lol.pyr.znpcsplus.api.skin.SkinDescriptor; | ||||||
|  | import lol.pyr.znpcsplus.config.ConfigManager; | ||||||
| import lol.pyr.znpcsplus.entity.properties.*; | import lol.pyr.znpcsplus.entity.properties.*; | ||||||
| import lol.pyr.znpcsplus.entity.properties.villager.VillagerLevelProperty; | import lol.pyr.znpcsplus.entity.properties.villager.VillagerLevelProperty; | ||||||
| import lol.pyr.znpcsplus.entity.properties.villager.VillagerProfessionProperty; | import lol.pyr.znpcsplus.entity.properties.villager.VillagerProfessionProperty; | ||||||
|  | @ -42,9 +43,9 @@ import java.util.stream.Collectors; | ||||||
| public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { | public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { | ||||||
|     private final Map<Class<?>, PropertySerializer<?>> serializerMap = new HashMap<>(); |     private final Map<Class<?>, PropertySerializer<?>> serializerMap = new HashMap<>(); | ||||||
|     private final Map<String, EntityPropertyImpl<?>> byName = new HashMap<>(); |     private final Map<String, EntityPropertyImpl<?>> byName = new HashMap<>(); | ||||||
|  |     private final ConfigManager configManager; | ||||||
| 
 | 
 | ||||||
|     public EntityPropertyRegistryImpl(MojangSkinCache skinCache) { |     public EntityPropertyRegistryImpl(MojangSkinCache skinCache, ConfigManager configManager) { | ||||||
|         registerSerializer(new BooleanPropertySerializer()); |  | ||||||
|         registerSerializer(new ComponentPropertySerializer()); |         registerSerializer(new ComponentPropertySerializer()); | ||||||
|         registerSerializer(new NamedTextColorPropertySerializer()); |         registerSerializer(new NamedTextColorPropertySerializer()); | ||||||
|         registerSerializer(new SkinDescriptorSerializer(skinCache)); |         registerSerializer(new SkinDescriptorSerializer(skinCache)); | ||||||
|  | @ -52,7 +53,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { | ||||||
|         registerSerializer(new ColorPropertySerializer()); |         registerSerializer(new ColorPropertySerializer()); | ||||||
|         registerSerializer(new Vector3fPropertySerializer()); |         registerSerializer(new Vector3fPropertySerializer()); | ||||||
|         registerSerializer(new BlockStatePropertySerializer()); |         registerSerializer(new BlockStatePropertySerializer()); | ||||||
|         registerSerializer(new IntegerPropertySerializer()); |         registerSerializer(new LookTypeSerializer()); | ||||||
| 
 | 
 | ||||||
|         registerEnumSerializer(NpcPose.class); |         registerEnumSerializer(NpcPose.class); | ||||||
|         registerEnumSerializer(DyeColor.class); |         registerEnumSerializer(DyeColor.class); | ||||||
|  | @ -76,6 +77,10 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { | ||||||
|         registerEnumSerializer(PandaGene.class); |         registerEnumSerializer(PandaGene.class); | ||||||
|         registerEnumSerializer(PuffState.class); |         registerEnumSerializer(PuffState.class); | ||||||
| 
 | 
 | ||||||
|  |         registerPrimitiveSerializers(Integer.class, Boolean.class, Double.class, Float.class, Long.class, Short.class, Byte.class, String.class); | ||||||
|  | 
 | ||||||
|  |         this.configManager = configManager; | ||||||
|  | 
 | ||||||
|         /* |         /* | ||||||
|         registerType("using_item", false); // TODO: fix it for 1.8 and add new property to use offhand item and riptide animation |         registerType("using_item", false); // TODO: fix it for 1.8 and add new property to use offhand item and riptide animation | ||||||
| 
 | 
 | ||||||
|  | @ -142,7 +147,10 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { | ||||||
|         register(new NameProperty(legacyNames, optionalComponents)); |         register(new NameProperty(legacyNames, optionalComponents)); | ||||||
|         register(new DinnerboneProperty(legacyNames, optionalComponents)); |         register(new DinnerboneProperty(legacyNames, optionalComponents)); | ||||||
| 
 | 
 | ||||||
|         register(new DummyProperty<>("look", false)); |         register(new DummyProperty<>("look", LookType.FIXED)); | ||||||
|  |         register(new DummyProperty<>("look_distance", configManager.getConfig().lookPropertyDistance())); | ||||||
|  |         register(new DummyProperty<>("view_distance", configManager.getConfig().viewDistance())); | ||||||
|  | 
 | ||||||
|         register(new GlowProperty(packetFactory)); |         register(new GlowProperty(packetFactory)); | ||||||
|         register(new BitsetProperty("fire", 0, 0x01)); |         register(new BitsetProperty("fire", 0, 0x01)); | ||||||
|         register(new BitsetProperty("invisible", 0, 0x20)); |         register(new BitsetProperty("invisible", 0, 0x20)); | ||||||
|  | @ -372,13 +380,14 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { | ||||||
|         // Player |         // Player | ||||||
|         NBTProperty.NBTDecoder<ParrotVariant> parrotVariantDecoder = (variant) -> { |         NBTProperty.NBTDecoder<ParrotVariant> parrotVariantDecoder = (variant) -> { | ||||||
|             NBTCompound compound = new NBTCompound(); |             NBTCompound compound = new NBTCompound(); | ||||||
|  |             if (variant == null) return compound; | ||||||
|             compound.setTag("id", new NBTString("minecraft:parrot")); |             compound.setTag("id", new NBTString("minecraft:parrot")); | ||||||
|             compound.setTag("Variant", new NBTInt(variant.ordinal())); |             compound.setTag("Variant", new NBTInt(variant.ordinal())); | ||||||
|             return compound; |             return compound; | ||||||
|         }; |         }; | ||||||
|         int shoulderIndex = skinLayersIndex+2; |         int shoulderIndex = skinLayersIndex+2; | ||||||
|         register(new NBTProperty<>("shoulder_entity_left", ParrotVariant.class, shoulderIndex++, parrotVariantDecoder)); |         register(new NBTProperty<>("shoulder_entity_left", ParrotVariant.class, shoulderIndex++, parrotVariantDecoder, true)); | ||||||
|         register(new NBTProperty<>("shoulder_entity_right", ParrotVariant.class, shoulderIndex, parrotVariantDecoder)); |         register(new NBTProperty<>("shoulder_entity_right", ParrotVariant.class, shoulderIndex, parrotVariantDecoder, true)); | ||||||
| 
 | 
 | ||||||
|         if (!ver.isNewerThanOrEquals(ServerVersion.V_1_13)) return; |         if (!ver.isNewerThanOrEquals(ServerVersion.V_1_13)) return; | ||||||
|         // Pufferfish |         // Pufferfish | ||||||
|  | @ -515,6 +524,16 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry { | ||||||
|         serializerMap.put(clazz, new EnumPropertySerializer<>(clazz)); |         serializerMap.put(clazz, new EnumPropertySerializer<>(clazz)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private void registerPrimitiveSerializers(Class<?>... classes) { | ||||||
|  |         for (Class<?> clazz : classes) { | ||||||
|  |             registerPrimitiveSerializer(clazz); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private <T> void registerPrimitiveSerializer(Class<T> clazz) { | ||||||
|  |         serializerMap.put(clazz, new PrimitivePropertySerializer<>(clazz)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private <T> void register(EntityPropertyImpl<?> property) { |     private <T> void register(EntityPropertyImpl<?> property) { | ||||||
|         if (byName.containsKey(property.getName())) |         if (byName.containsKey(property.getName())) | ||||||
|             throw new IllegalArgumentException("Duplicate property name: " + property.getName()); |             throw new IllegalArgumentException("Duplicate property name: " + property.getName()); | ||||||
|  |  | ||||||
|  | @ -60,6 +60,10 @@ public class PacketEntity implements PropertyHolder { | ||||||
|         else packetFactory.spawnEntity(player, this, properties); |         else packetFactory.spawnEntity(player, this, properties); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void setHeadRotation(Player player, float yaw, float pitch) { | ||||||
|  |         packetFactory.sendHeadRotation(player, this, yaw, pitch); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public void despawn(Player player) { |     public void despawn(Player player) { | ||||||
|         packetFactory.destroyEntity(player, this, properties); |         packetFactory.destroyEntity(player, this, properties); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | package lol.pyr.znpcsplus.entity; | ||||||
|  | 
 | ||||||
|  | import java.lang.reflect.InvocationTargetException; | ||||||
|  | 
 | ||||||
|  | public class PrimitivePropertySerializer<T> implements PropertySerializer<T> { | ||||||
|  |     private final Class<T> clazz; | ||||||
|  | 
 | ||||||
|  |     public PrimitivePropertySerializer(Class<T> clazz) { | ||||||
|  |         this.clazz = clazz; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public String serialize(T property) { | ||||||
|  |         return String.valueOf(property); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public T deserialize(String property) { | ||||||
|  |         try { | ||||||
|  |             return clazz.getConstructor(String.class).newInstance(property); | ||||||
|  |         } catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) { | ||||||
|  |             throw new NullPointerException("Failed to deserialize property " + property + " of type " + clazz.getName() + "!"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Class<T> getTypeClass() { | ||||||
|  |         return clazz; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -14,32 +14,43 @@ public class NBTProperty<T> extends EntityPropertyImpl<T> { | ||||||
|     private final EntityDataType<NBTCompound> type; |     private final EntityDataType<NBTCompound> type; | ||||||
|     private final NBTDecoder<T> decoder; |     private final NBTDecoder<T> decoder; | ||||||
|     private final int index; |     private final int index; | ||||||
|  |     private final boolean allowNull; // This means that the decoder can have null input, not that the property can be null | ||||||
| 
 | 
 | ||||||
|     public NBTProperty(String name, T defaultValue, Class<T> clazz, int index, NBTDecoder<T> decoder, EntityDataType<NBTCompound> type) { |     public NBTProperty(String name, T defaultValue, Class<T> clazz, int index, NBTDecoder<T> decoder, boolean allowNull, EntityDataType<NBTCompound> type) { | ||||||
|         super(name, defaultValue, clazz); |         super(name, defaultValue, clazz); | ||||||
|         this.decoder = decoder; |         this.decoder = decoder; | ||||||
|         this.index = index; |         this.index = index; | ||||||
|  |         this.allowNull = allowNull; | ||||||
|         this.type = type; |         this.type = type; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @SuppressWarnings("unchecked") |     @SuppressWarnings("unchecked") | ||||||
|     public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder) { |     public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder, boolean allowNull) { | ||||||
|         this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, EntityDataTypes.NBT); |         this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, allowNull, EntityDataTypes.NBT); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @SuppressWarnings("unchecked") |     @SuppressWarnings("unchecked") | ||||||
|     public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder, EntityDataType<NBTCompound> type) { |     public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder) { | ||||||
|         this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, type); |         this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, false, EntityDataTypes.NBT); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @SuppressWarnings("unchecked") | ||||||
|  |     public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder, boolean allowNull, EntityDataType<NBTCompound> type) { | ||||||
|  |         this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, allowNull, type); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public NBTProperty(String name, Class<T> clazz, int index, NBTDecoder<T> decoder, boolean allowNull) { | ||||||
|  |         this(name, null, clazz, index, decoder, allowNull, EntityDataTypes.NBT); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public NBTProperty(String name, Class<T> clazz, int index, NBTDecoder<T> decoder) { |     public NBTProperty(String name, Class<T> clazz, int index, NBTDecoder<T> decoder) { | ||||||
|         this(name, null, clazz, index, decoder, EntityDataTypes.NBT); |         this(name, null, clazz, index, decoder, false, EntityDataTypes.NBT); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) { |     public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) { | ||||||
|         T value = entity.getProperty(this); |         T value = entity.getProperty(this); | ||||||
|         if (value == null) return; |         if (value == null && !allowNull) return; | ||||||
|         properties.put(index, newEntityData(index, type, decoder.decode(value))); |         properties.put(index, newEntityData(index, type, decoder.decode(value))); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,25 +0,0 @@ | ||||||
| package lol.pyr.znpcsplus.entity.serializers; |  | ||||||
| 
 |  | ||||||
| import lol.pyr.znpcsplus.entity.PropertySerializer; |  | ||||||
| 
 |  | ||||||
| public class IntegerPropertySerializer implements PropertySerializer<Integer> { |  | ||||||
|     @Override |  | ||||||
|     public String serialize(Integer property) { |  | ||||||
|         return String.valueOf(property); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public Integer deserialize(String property) { |  | ||||||
|         try { |  | ||||||
|             return Integer.parseInt(property); |  | ||||||
|         } catch (NumberFormatException e) { |  | ||||||
|             e.printStackTrace(); |  | ||||||
|         } |  | ||||||
|         return null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     @Override |  | ||||||
|     public Class<Integer> getTypeClass() { |  | ||||||
|         return Integer.class; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | package lol.pyr.znpcsplus.entity.serializers; | ||||||
|  | 
 | ||||||
|  | import lol.pyr.znpcsplus.entity.PropertySerializer; | ||||||
|  | import lol.pyr.znpcsplus.util.LookType; | ||||||
|  | 
 | ||||||
|  | public class LookTypeSerializer implements PropertySerializer<LookType> { | ||||||
|  |     @Override | ||||||
|  |     public String serialize(LookType property) { | ||||||
|  |         return property.name(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public LookType deserialize(String property) { | ||||||
|  |         if (property.equals("true")) return LookType.CLOSEST_PLAYER; | ||||||
|  |         try { | ||||||
|  |              return LookType.valueOf(property); | ||||||
|  |         } catch (IllegalArgumentException ignored) { | ||||||
|  |             return LookType.FIXED; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public Class<LookType> getTypeClass() { | ||||||
|  |         return LookType.class; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -83,6 +83,16 @@ public class NpcImpl extends Viewable implements Npc { | ||||||
|         hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); |         hologram.setLocation(location.withY(location.getY() + type.getHologramOffset())); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void setHeadRotation(Player player, float yaw, float pitch) { | ||||||
|  |         entity.setHeadRotation(player, yaw, pitch); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setHeadRotation(float yaw, float pitch) { | ||||||
|  |         for (Player player : getViewers()) { | ||||||
|  |             entity.setHeadRotation(player, yaw, pitch); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public HologramImpl getHologram() { |     public HologramImpl getHologram() { | ||||||
|         return hologram; |         return hologram; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -110,8 +110,9 @@ public class NpcTypeImpl implements NpcType { | ||||||
| 
 | 
 | ||||||
|         public NpcTypeImpl build() { |         public NpcTypeImpl build() { | ||||||
|             ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion(); |             ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion(); | ||||||
|             addProperties("fire", "invisible", "silent", "look", |             addProperties("fire", "invisible", "silent", "look", "look_distance", "view_distance", | ||||||
|                     "potion_color", "potion_ambient", "dinnerbone"); |                     "potion_color", "potion_ambient"); | ||||||
|  |             if (!type.equals(EntityTypes.PLAYER)) addProperties("dinnerbone"); | ||||||
|             // TODO: make this look nicer after completing the rest of the properties |             // TODO: make this look nicer after completing the rest of the properties | ||||||
|             if (version.isNewerThanOrEquals(ServerVersion.V_1_9)) addProperties("glow"); |             if (version.isNewerThanOrEquals(ServerVersion.V_1_9)) addProperties("glow"); | ||||||
|             if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) { |             if (version.isNewerThanOrEquals(ServerVersion.V_1_14)) { | ||||||
|  |  | ||||||
|  | @ -22,4 +22,5 @@ public interface PacketFactory { | ||||||
|     void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties); |     void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties); | ||||||
|     void sendEquipment(Player player, PacketEntity entity, Equipment equipment); |     void sendEquipment(Player player, PacketEntity entity, Equipment equipment); | ||||||
|     void sendMetadata(Player player, PacketEntity entity, List<EntityData> data); |     void sendMetadata(Player player, PacketEntity entity, List<EntityData> data); | ||||||
|  |     void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -137,6 +137,12 @@ public class V1_8PacketFactory implements PacketFactory { | ||||||
|         sendPacket(player, new WrapperPlayServerEntityMetadata(entity.getEntityId(), data)); |         sendPacket(player, new WrapperPlayServerEntityMetadata(entity.getEntityId(), data)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     public void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch) { | ||||||
|  |         sendPacket(player, new WrapperPlayServerEntityHeadLook(entity.getEntityId(),yaw)); | ||||||
|  |         sendPacket(player, new WrapperPlayServerEntityRotation(entity.getEntityId(), yaw, pitch, true)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void sendEquipment(Player player, PacketEntity entity, Equipment equipment) { |     public void sendEquipment(Player player, PacketEntity entity, Equipment equipment) { | ||||||
|         sendPacket(player, new WrapperPlayServerEntityEquipment(entity.getEntityId(), Collections.singletonList(equipment))); |         sendPacket(player, new WrapperPlayServerEntityEquipment(entity.getEntityId(), Collections.singletonList(equipment))); | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; | ||||||
| import lol.pyr.znpcsplus.npc.NpcEntryImpl; | import lol.pyr.znpcsplus.npc.NpcEntryImpl; | ||||||
| import lol.pyr.znpcsplus.npc.NpcImpl; | import lol.pyr.znpcsplus.npc.NpcImpl; | ||||||
| import lol.pyr.znpcsplus.npc.NpcRegistryImpl; | import lol.pyr.znpcsplus.npc.NpcRegistryImpl; | ||||||
|  | import lol.pyr.znpcsplus.util.LookType; | ||||||
| import lol.pyr.znpcsplus.util.NpcLocation; | import lol.pyr.znpcsplus.util.NpcLocation; | ||||||
| import org.bukkit.Bukkit; | import org.bukkit.Bukkit; | ||||||
| import org.bukkit.entity.Player; | import org.bukkit.entity.Player; | ||||||
|  | @ -26,15 +27,18 @@ public class NpcProcessorTask extends BukkitRunnable { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void run() { |     public void run() { | ||||||
|         double distSq = NumberConversions.square(configManager.getConfig().viewDistance()); |         EntityPropertyImpl<Integer> viewDistanceProperty = propertyRegistry.getByName("view_distance", Integer.class); // Not sure why this is an Integer, but it is | ||||||
|         double lookPropertyDistSq = NumberConversions.square(configManager.getConfig().lookPropertyDistance()); |         EntityPropertyImpl<LookType> lookProperty = propertyRegistry.getByName("look", LookType.class); | ||||||
|         EntityPropertyImpl<Boolean> lookProperty = propertyRegistry.getByName("look", Boolean.class); |         EntityPropertyImpl<Double> lookDistanceProperty = propertyRegistry.getByName("look_distance", Double.class); | ||||||
|  |         double lookDistance; | ||||||
|         for (NpcEntryImpl entry : npcRegistry.getProcessable()) { |         for (NpcEntryImpl entry : npcRegistry.getProcessable()) { | ||||||
|             NpcImpl npc = entry.getNpc(); |             NpcImpl npc = entry.getNpc(); | ||||||
|             if (!npc.isEnabled()) continue; |             if (!npc.isEnabled()) continue; | ||||||
| 
 | 
 | ||||||
|             double closestDist = Double.MAX_VALUE; |             double closestDist = Double.MAX_VALUE; | ||||||
|             Player closest = null; |             Player closest = null; | ||||||
|  |             LookType lookType = npc.getProperty(lookProperty); | ||||||
|  |             lookDistance =  NumberConversions.square(npc.getProperty(lookDistanceProperty)); | ||||||
|             for (Player player : Bukkit.getOnlinePlayers()) { |             for (Player player : Bukkit.getOnlinePlayers()) { | ||||||
|                 if (!player.getWorld().equals(npc.getWorld())) { |                 if (!player.getWorld().equals(npc.getWorld())) { | ||||||
|                     if (npc.isVisibleTo(player)) npc.hide(player); |                     if (npc.isVisibleTo(player)) npc.hide(player); | ||||||
|  | @ -43,7 +47,7 @@ public class NpcProcessorTask extends BukkitRunnable { | ||||||
|                 double distance = player.getLocation().distanceSquared(npc.getBukkitLocation()); |                 double distance = player.getLocation().distanceSquared(npc.getBukkitLocation()); | ||||||
| 
 | 
 | ||||||
|                 // visibility |                 // visibility | ||||||
|                 boolean inRange = distance <= distSq; |                 boolean inRange = distance <= NumberConversions.square(npc.getProperty(viewDistanceProperty)); | ||||||
|                 if (!inRange && npc.isVisibleTo(player)) { |                 if (!inRange && npc.isVisibleTo(player)) { | ||||||
|                     NpcDespawnEvent event = new NpcDespawnEvent(player, entry); |                     NpcDespawnEvent event = new NpcDespawnEvent(player, entry); | ||||||
|                     Bukkit.getPluginManager().callEvent(event); |                     Bukkit.getPluginManager().callEvent(event); | ||||||
|  | @ -60,12 +64,18 @@ public class NpcProcessorTask extends BukkitRunnable { | ||||||
|                         closestDist = distance; |                         closestDist = distance; | ||||||
|                         closest = player; |                         closest = player; | ||||||
|                     } |                     } | ||||||
|  |                     if (lookType.equals(LookType.PER_PLAYER) && lookDistance >= distance) { | ||||||
|  |                         NpcLocation expected = npc.getLocation().lookingAt(player.getLocation().add(0, -npc.getType().getHologramOffset(), 0)); | ||||||
|  |                         if (!expected.equals(npc.getLocation())) npc.setHeadRotation(player, expected.getYaw(), expected.getPitch()); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             // look property |             // look property | ||||||
|             if (closest != null && npc.getProperty(lookProperty) && lookPropertyDistSq >= closestDist) { |             if (lookType.equals(LookType.CLOSEST_PLAYER)) { | ||||||
|                 NpcLocation expected = npc.getLocation().lookingAt(closest.getLocation().add(0, -npc.getType().getHologramOffset(), 0)); |                 if (closest != null && lookDistance >= closestDist) { | ||||||
|                 if (!expected.equals(npc.getLocation())) npc.setLocation(expected); |                     NpcLocation expected = npc.getLocation().lookingAt(closest.getLocation().add(0, -npc.getType().getHologramOffset(), 0)); | ||||||
|  |                     if (!expected.equals(npc.getLocation())) npc.setHeadRotation(expected.getYaw(), expected.getPitch()); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue