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