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());
|
||||
MojangSkinCache skinCache = new MojangSkinCache(configManager);
|
||||
EntityPropertyRegistryImpl propertyRegistry = new EntityPropertyRegistryImpl(skinCache);
|
||||
EntityPropertyRegistryImpl propertyRegistry = new EntityPropertyRegistryImpl(skinCache, configManager);
|
||||
PacketFactory packetFactory = setupPacketFactory(scheduler, propertyRegistry);
|
||||
propertyRegistry.registerTypes(packetFactory);
|
||||
|
||||
|
@ -276,6 +276,7 @@ public class ZNpcsPlus extends JavaPlugin {
|
|||
registerEnumParser(manager, OcelotType.class, incorrectUsageMessage);
|
||||
registerEnumParser(manager, PandaGene.class, incorrectUsageMessage);
|
||||
registerEnumParser(manager, PuffState.class, incorrectUsageMessage);
|
||||
registerEnumParser(manager, LookType.class, incorrectUsageMessage);
|
||||
|
||||
manager.registerCommand("npc", new MultiCommand(loadHelpMessage("root"))
|
||||
.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.conversion.citizens.model.SectionCitizensTrait;
|
||||
import lol.pyr.znpcsplus.npc.NpcImpl;
|
||||
import lol.pyr.znpcsplus.util.LookType;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
@ -16,7 +17,7 @@ public class LookTrait extends SectionCitizensTrait {
|
|||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,13 +28,16 @@ import lol.pyr.znpcsplus.scheduling.TaskScheduler;
|
|||
import lol.pyr.znpcsplus.skin.Skin;
|
||||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||
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.util.BungeeConnector;
|
||||
import lol.pyr.znpcsplus.util.ItemSerializationUtil;
|
||||
import lol.pyr.znpcsplus.util.LookType;
|
||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
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())));
|
||||
}
|
||||
|
||||
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);
|
||||
entry.enableEverything();
|
||||
entries.add(entry);
|
||||
|
|
|
@ -19,6 +19,7 @@ public class ZNpcsModel {
|
|||
private List<String> hologramLines;
|
||||
private List<ZNpcsAction> clickActions;
|
||||
private Map<String, String> npcEquip;
|
||||
private Map<String, Object> npcToggleValues;
|
||||
private Map<String, String[]> customizationMap;
|
||||
|
||||
public int getId() {
|
||||
|
@ -57,6 +58,10 @@ public class ZNpcsModel {
|
|||
return npcEquip;
|
||||
}
|
||||
|
||||
public Map<String, Object> getNpcToggleValues() {
|
||||
return npcToggleValues;
|
||||
}
|
||||
|
||||
public Map<String, String[]> getCustomizationMap() {
|
||||
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.EntityPropertyRegistry;
|
||||
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.villager.VillagerLevelProperty;
|
||||
import lol.pyr.znpcsplus.entity.properties.villager.VillagerProfessionProperty;
|
||||
|
@ -42,9 +43,9 @@ import java.util.stream.Collectors;
|
|||
public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
||||
private final Map<Class<?>, PropertySerializer<?>> serializerMap = new HashMap<>();
|
||||
private final Map<String, EntityPropertyImpl<?>> byName = new HashMap<>();
|
||||
private final ConfigManager configManager;
|
||||
|
||||
public EntityPropertyRegistryImpl(MojangSkinCache skinCache) {
|
||||
registerSerializer(new BooleanPropertySerializer());
|
||||
public EntityPropertyRegistryImpl(MojangSkinCache skinCache, ConfigManager configManager) {
|
||||
registerSerializer(new ComponentPropertySerializer());
|
||||
registerSerializer(new NamedTextColorPropertySerializer());
|
||||
registerSerializer(new SkinDescriptorSerializer(skinCache));
|
||||
|
@ -52,7 +53,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
|||
registerSerializer(new ColorPropertySerializer());
|
||||
registerSerializer(new Vector3fPropertySerializer());
|
||||
registerSerializer(new BlockStatePropertySerializer());
|
||||
registerSerializer(new IntegerPropertySerializer());
|
||||
registerSerializer(new LookTypeSerializer());
|
||||
|
||||
registerEnumSerializer(NpcPose.class);
|
||||
registerEnumSerializer(DyeColor.class);
|
||||
|
@ -76,6 +77,10 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
|||
registerEnumSerializer(PandaGene.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
|
||||
|
||||
|
@ -142,7 +147,10 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
|||
register(new NameProperty(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 BitsetProperty("fire", 0, 0x01));
|
||||
register(new BitsetProperty("invisible", 0, 0x20));
|
||||
|
@ -372,13 +380,14 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
|||
// Player
|
||||
NBTProperty.NBTDecoder<ParrotVariant> parrotVariantDecoder = (variant) -> {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
if (variant == null) return compound;
|
||||
compound.setTag("id", new NBTString("minecraft:parrot"));
|
||||
compound.setTag("Variant", new NBTInt(variant.ordinal()));
|
||||
return compound;
|
||||
};
|
||||
int shoulderIndex = skinLayersIndex+2;
|
||||
register(new NBTProperty<>("shoulder_entity_left", ParrotVariant.class, shoulderIndex++, parrotVariantDecoder));
|
||||
register(new NBTProperty<>("shoulder_entity_right", 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, true));
|
||||
|
||||
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_13)) return;
|
||||
// Pufferfish
|
||||
|
@ -515,6 +524,16 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
|||
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) {
|
||||
if (byName.containsKey(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);
|
||||
}
|
||||
|
||||
public void setHeadRotation(Player player, float yaw, float pitch) {
|
||||
packetFactory.sendHeadRotation(player, this, yaw, pitch);
|
||||
}
|
||||
|
||||
public void despawn(Player player) {
|
||||
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 NBTDecoder<T> decoder;
|
||||
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);
|
||||
this.decoder = decoder;
|
||||
this.index = index;
|
||||
this.allowNull = allowNull;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder) {
|
||||
this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, EntityDataTypes.NBT);
|
||||
public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder, boolean allowNull) {
|
||||
this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, allowNull, EntityDataTypes.NBT);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder, EntityDataType<NBTCompound> type) {
|
||||
this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder, type);
|
||||
public NBTProperty(String name, T defaultValue, int index, NBTDecoder<T> decoder) {
|
||||
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) {
|
||||
this(name, null, clazz, index, decoder, EntityDataTypes.NBT);
|
||||
this(name, null, clazz, index, decoder, false, EntityDataTypes.NBT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
|
||||
T value = entity.getProperty(this);
|
||||
if (value == null) return;
|
||||
if (value == null && !allowNull) return;
|
||||
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()));
|
||||
}
|
||||
|
||||
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() {
|
||||
return hologram;
|
||||
}
|
||||
|
|
|
@ -110,8 +110,9 @@ public class NpcTypeImpl implements NpcType {
|
|||
|
||||
public NpcTypeImpl build() {
|
||||
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||
addProperties("fire", "invisible", "silent", "look",
|
||||
"potion_color", "potion_ambient", "dinnerbone");
|
||||
addProperties("fire", "invisible", "silent", "look", "look_distance", "view_distance",
|
||||
"potion_color", "potion_ambient");
|
||||
if (!type.equals(EntityTypes.PLAYER)) addProperties("dinnerbone");
|
||||
// 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_14)) {
|
||||
|
|
|
@ -22,4 +22,5 @@ public interface PacketFactory {
|
|||
void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties);
|
||||
void sendEquipment(Player player, PacketEntity entity, Equipment equipment);
|
||||
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));
|
||||
}
|
||||
|
||||
@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
|
||||
public void sendEquipment(Player player, PacketEntity entity, Equipment 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.NpcImpl;
|
||||
import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
|
||||
import lol.pyr.znpcsplus.util.LookType;
|
||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -26,15 +27,18 @@ public class NpcProcessorTask extends BukkitRunnable {
|
|||
}
|
||||
|
||||
public void run() {
|
||||
double distSq = NumberConversions.square(configManager.getConfig().viewDistance());
|
||||
double lookPropertyDistSq = NumberConversions.square(configManager.getConfig().lookPropertyDistance());
|
||||
EntityPropertyImpl<Boolean> lookProperty = propertyRegistry.getByName("look", Boolean.class);
|
||||
EntityPropertyImpl<Integer> viewDistanceProperty = propertyRegistry.getByName("view_distance", Integer.class); // Not sure why this is an Integer, but it is
|
||||
EntityPropertyImpl<LookType> lookProperty = propertyRegistry.getByName("look", LookType.class);
|
||||
EntityPropertyImpl<Double> lookDistanceProperty = propertyRegistry.getByName("look_distance", Double.class);
|
||||
double lookDistance;
|
||||
for (NpcEntryImpl entry : npcRegistry.getProcessable()) {
|
||||
NpcImpl npc = entry.getNpc();
|
||||
if (!npc.isEnabled()) continue;
|
||||
|
||||
double closestDist = Double.MAX_VALUE;
|
||||
Player closest = null;
|
||||
LookType lookType = npc.getProperty(lookProperty);
|
||||
lookDistance = NumberConversions.square(npc.getProperty(lookDistanceProperty));
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (!player.getWorld().equals(npc.getWorld())) {
|
||||
if (npc.isVisibleTo(player)) npc.hide(player);
|
||||
|
@ -43,7 +47,7 @@ public class NpcProcessorTask extends BukkitRunnable {
|
|||
double distance = player.getLocation().distanceSquared(npc.getBukkitLocation());
|
||||
|
||||
// visibility
|
||||
boolean inRange = distance <= distSq;
|
||||
boolean inRange = distance <= NumberConversions.square(npc.getProperty(viewDistanceProperty));
|
||||
if (!inRange && npc.isVisibleTo(player)) {
|
||||
NpcDespawnEvent event = new NpcDespawnEvent(player, entry);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
|
@ -60,12 +64,18 @@ public class NpcProcessorTask extends BukkitRunnable {
|
|||
closestDist = distance;
|
||||
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
|
||||
if (closest != null && npc.getProperty(lookProperty) && lookPropertyDistSq >= closestDist) {
|
||||
NpcLocation expected = npc.getLocation().lookingAt(closest.getLocation().add(0, -npc.getType().getHologramOffset(), 0));
|
||||
if (!expected.equals(npc.getLocation())) npc.setLocation(expected);
|
||||
if (lookType.equals(LookType.CLOSEST_PLAYER)) {
|
||||
if (closest != null && lookDistance >= closestDist) {
|
||||
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