move to a more modular property/metadata system

This commit is contained in:
Pyrbu 2023-07-10 01:01:12 +02:00
parent 80683f81bc
commit acd953e460
39 changed files with 357 additions and 365 deletions

@ -1,7 +1,10 @@
package lol.pyr.znpcsplus.api.entity;
import java.util.Set;
public interface PropertyHolder {
<T> T getProperty(EntityProperty<T> key);
boolean hasProperty(EntityProperty<?> key);
<T> void setProperty(EntityProperty<T> key, T value);
Set<EntityProperty<?>> getAppliedProperties();
}

@ -31,9 +31,11 @@ import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
import lol.pyr.znpcsplus.interaction.InteractionPacketListener;
import lol.pyr.znpcsplus.metadata.*;
import lol.pyr.znpcsplus.npc.*;
import lol.pyr.znpcsplus.packets.*;
import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.packets.V1_17PacketFactory;
import lol.pyr.znpcsplus.packets.V1_19PacketFactory;
import lol.pyr.znpcsplus.packets.V1_8PacketFactory;
import lol.pyr.znpcsplus.parsers.*;
import lol.pyr.znpcsplus.scheduling.FoliaScheduler;
import lol.pyr.znpcsplus.scheduling.SpigotScheduler;
@ -128,8 +130,8 @@ public class ZNpcsPlus extends JavaPlugin {
ConfigManager configManager = new ConfigManager(getDataFolder());
MojangSkinCache skinCache = new MojangSkinCache(configManager);
EntityPropertyRegistryImpl propertyRegistry = new EntityPropertyRegistryImpl(skinCache);
MetadataFactory metadataFactory = setupMetadataFactory();
PacketFactory packetFactory = setupPacketFactory(scheduler, metadataFactory, propertyRegistry);
PacketFactory packetFactory = setupPacketFactory(scheduler, propertyRegistry);
propertyRegistry.registerTypes(packetFactory);
BungeeConnector bungeeConnector = new BungeeConnector(this);
ActionRegistry actionRegistry = new ActionRegistry();
@ -203,7 +205,6 @@ public class ZNpcsPlus extends JavaPlugin {
npc.getHologram().addLineComponent(Component.text("Hello, World!", TextColor.color(255, 0, 0)));
npc.getHologram().addLineComponent(Component.text("Hello, World!", TextColor.color(0, 255, 0)));
npc.getHologram().addLineComponent(Component.text("Hello, World!", TextColor.color(0, 0, 255)));
npc.setProperty(propertyRegistry.getByName("look", Boolean.class), true);
i++;
}
}
@ -216,15 +217,11 @@ public class ZNpcsPlus extends JavaPlugin {
PacketEvents.getAPI().terminate();
}
private PacketFactory setupPacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, EntityPropertyRegistryImpl propertyRegistry) {
private PacketFactory setupPacketFactory(TaskScheduler scheduler, EntityPropertyRegistryImpl propertyRegistry) {
HashMap<ServerVersion, LazyLoader<? extends PacketFactory>> versions = new HashMap<>();
versions.put(ServerVersion.V_1_8, LazyLoader.of(() -> new V1_8PacketFactory(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_9, LazyLoader.of(() -> new V1_9PacketFactory(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_10, LazyLoader.of(() -> new V1_10PacketFactory(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_14, LazyLoader.of(() -> new V1_14PacketFactory(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_16, LazyLoader.of(() -> new V1_16PacketFactory(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_17, LazyLoader.of(() -> new V1_17PacketFactory(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_19, LazyLoader.of(() -> new V1_19PacketFactory(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_8, LazyLoader.of(() -> new V1_8PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_17, LazyLoader.of(() -> new V1_17PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer)));
versions.put(ServerVersion.V_1_19, LazyLoader.of(() -> new V1_19PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer)));
ServerVersion version = packetEvents.getServerManager().getVersion();
if (versions.containsKey(version)) return versions.get(version).get();
@ -236,31 +233,6 @@ public class ZNpcsPlus extends JavaPlugin {
throw new RuntimeException("Unsupported version!");
}
private MetadataFactory setupMetadataFactory() {
HashMap<ServerVersion, LazyLoader<? extends MetadataFactory>> versions = new HashMap<>();
versions.put(ServerVersion.V_1_8, LazyLoader.of(V1_8MetadataFactory::new));
versions.put(ServerVersion.V_1_9, LazyLoader.of(V1_9MetadataFactory::new));
versions.put(ServerVersion.V_1_10, LazyLoader.of(V1_10MetadataFactory::new));
versions.put(ServerVersion.V_1_11, LazyLoader.of(V1_11MetadataFactory::new));
versions.put(ServerVersion.V_1_12, LazyLoader.of(V1_12MetadataFactory::new));
versions.put(ServerVersion.V_1_13, LazyLoader.of(V1_13MetadataFactory::new));
versions.put(ServerVersion.V_1_14, LazyLoader.of(V1_14MetadataFactory::new));
versions.put(ServerVersion.V_1_15, LazyLoader.of(V1_15MetadataFactory::new));
versions.put(ServerVersion.V_1_16, LazyLoader.of(V1_16MetadataFactory::new));
versions.put(ServerVersion.V_1_17, LazyLoader.of(V1_17MetadataFactory::new));
versions.put(ServerVersion.V_1_19, LazyLoader.of(V1_19MetadataFactory::new));
ServerVersion version = packetEvents.getServerManager().getVersion();
if (versions.containsKey(version)) return versions.get(version).get();
for (ServerVersion v : ServerVersion.reversedValues()) {
if (v.isNewerThan(version)) continue;
if (!versions.containsKey(v)) continue;
return versions.get(v).get();
}
throw new RuntimeException("Unsupported version!");
}
private void registerCommands(NpcRegistryImpl npcRegistry, MojangSkinCache skinCache, BukkitAudiences adventure,
ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry,
EntityPropertyRegistryImpl propertyRegistry, DataImporterRegistry importerRegistry,

@ -28,7 +28,7 @@ public class PropertyRemoveCommand implements CommandHandler {
NpcImpl npc = entry.getNpc();
EntityPropertyImpl<?> property = context.parse(EntityPropertyImpl.class);
if (!npc.hasProperty(property)) context.halt(Component.text("This npc doesn't have the " + property.getName() + " property set", NamedTextColor.RED));
npc.removeProperty(property);
npc.setProperty(property, null);
context.send(Component.text("Removed property " + property.getName() + " from NPC " + entry.getId(), NamedTextColor.GREEN));
}

@ -100,7 +100,7 @@ public class ZNpcImporter implements DataImporter {
ZNpcsLocation oldLoc = model.getLocation();
NpcLocation location = new NpcLocation(oldLoc.getX(), oldLoc.getY(), oldLoc.getZ(), oldLoc.getYaw(), oldLoc.getPitch());
UUID uuid = model.getUuid() == null ? UUID.randomUUID() : model.getUuid();
NpcImpl npc = new NpcImpl(uuid, configManager, packetFactory, textSerializer, oldLoc.getWorld(), typeRegistry.getByName(type), location);
NpcImpl npc = new NpcImpl(uuid, propertyRegistry, configManager, packetFactory, textSerializer, oldLoc.getWorld(), typeRegistry.getByName(type), location);
HologramImpl hologram = npc.getHologram();
hologram.setOffset(model.getHologramHeight());

@ -1,19 +1,24 @@
package lol.pyr.znpcsplus.entity;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import org.bukkit.entity.Player;
public class EntityPropertyImpl<T> implements EntityProperty<T> {
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class EntityPropertyImpl<T> implements EntityProperty<T> {
private final String name;
private final T defaultValue;
private final Class<T> clazz;
private final PropertySerializer<T> serializer;
protected EntityPropertyImpl(String name, T defaultValue, Class<T> clazz, PropertySerializer<T> serializer) {
protected EntityPropertyImpl(String name, T defaultValue, Class<T> clazz) {
this.name = name.toLowerCase();
this.defaultValue = defaultValue;
this.clazz = clazz;
this.serializer = serializer;
}
@Override
@ -21,18 +26,6 @@ public class EntityPropertyImpl<T> implements EntityProperty<T> {
return name;
}
public String serialize(PropertyHolder holder) {
return serialize(holder.getProperty(this));
}
public String serialize(T value) {
return serializer.serialize(value);
}
public T deserialize(String str) {
return serializer.deserialize(str);
}
@Override
public T getDefaultValue() {
return defaultValue;
@ -41,4 +34,21 @@ public class EntityPropertyImpl<T> implements EntityProperty<T> {
public Class<T> getType() {
return clazz;
}
protected static <V> EntityData newEntityData(int index, EntityDataType<V> type, V value) {
return new EntityData(index, type, value);
}
public List<EntityData> makeStandaloneData(T value, Player player, PacketEntity packetEntity, boolean isSpawned) {
Map<Integer, EntityData> map = new HashMap<>();
apply(value, player, packetEntity, isSpawned, map);
return new ArrayList<>(map.values());
}
abstract public void apply(T value, Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties);
@SuppressWarnings("unchecked")
public void UNSAFE_update(Object value, Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
apply((T) value, player, entity, isSpawned, properties);
}
}

@ -1,15 +1,13 @@
package lol.pyr.znpcsplus.entity;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
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.entity.properties.*;
import lol.pyr.znpcsplus.entity.serializers.*;
import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
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 java.util.Collection;
@ -18,6 +16,20 @@ import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 1.8 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=7415">...</a>
* 1.9 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=7968">...</a>
* 1.10 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=8241">...</a>
* 1.11 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=8534">...</a>
* 1.12 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=14048">...</a>
* 1.13 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=14800">...</a>
* 1.14 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=15240">...</a>
* 1.15 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=15991">...</a>
* 1.16 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=16539">...</a>
* 1.17 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=17521">...</a>
* 1.18-1.19 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=18191">...</a>
* 1.20 <a href="https://wiki.vg/index.php?title=Entity_metadata">...</a>
*/
@SuppressWarnings("unchecked")
public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
private final Map<Class<?>, PropertySerializer<?>> serializerMap = new HashMap<>();
@ -44,7 +56,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
registerEnumSerializer(VillagerType.class);
registerEnumSerializer(VillagerProfession.class);
registerEnumSerializer(VillagerLevel.class);
/*
registerType("glow", NamedTextColor.class);
registerType("fire", false);
registerType("invisible", false);
@ -226,6 +238,22 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
// Slime
registerType("slime_size", 0); // TODO
*/
}
public void registerTypes(PacketFactory packetFactory) {
register(new EquipmentProperty(packetFactory, "helmet", EquipmentSlot.HELMET));
register(new EquipmentProperty(packetFactory, "chestplate", EquipmentSlot.CHEST_PLATE));
register(new EquipmentProperty(packetFactory, "leggings", EquipmentSlot.LEGGINGS));
register(new EquipmentProperty(packetFactory, "boots", EquipmentSlot.BOOTS));
register(new EquipmentProperty(packetFactory, "hand", EquipmentSlot.MAIN_HAND));
register(new EquipmentProperty(packetFactory, "offhand", EquipmentSlot.OFF_HAND));
register(new NameProperty());
register(new DummyBooleanProperty("look", false));
register(new GlowProperty(packetFactory));
register(new EffectsProperty("fire", 0x01));
register(new EffectsProperty("invisible", 0x20));
}
private void registerSerializer(PropertySerializer<?> serializer) {
@ -236,18 +264,12 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
serializerMap.put(clazz, new EnumPropertySerializer<>(clazz));
}
private <T> void registerType(String name, Class<T> type) {
registerType(name, null, type);
private <T> void register(EntityPropertyImpl<?> property) {
byName.put(property.getName(), property);
}
private <T> void registerType(String name, T defaultValue) {
registerType(name, defaultValue, (Class<T>) defaultValue.getClass());
}
private <T> void registerType(String name, T defaultValue, Class<T> clazz) {
if (clazz == null) return;
EntityPropertyImpl<T> property = new EntityPropertyImpl<>(name, defaultValue, clazz, (PropertySerializer<T>) serializerMap.get(clazz));
byName.put(name.toLowerCase(), property);
public <V> PropertySerializer<V> getSerializer(Class<V> type) {
return (PropertySerializer<V>) serializerMap.get(type);
}
@Override

@ -66,11 +66,6 @@ public class PacketEntity {
packetFactory.sendAllMetadata(player, this, properties);
}
public void remakeTeam(Player player) {
packetFactory.removeTeam(player, this);
packetFactory.createTeam(player, this, properties);
}
private static int reserveEntityID() {
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14)) {
return Reflections.ATOMIC_ENTITY_ID_FIELD.get().incrementAndGet();

@ -4,4 +4,9 @@ public interface PropertySerializer<T> {
String serialize(T property);
T deserialize(String property);
Class<T> getTypeClass();
@SuppressWarnings("unchecked")
default String UNSAFE_serialize(Object property) {
return serialize((T) property);
}
}

@ -0,0 +1,18 @@
package lol.pyr.znpcsplus.entity.properties;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import org.bukkit.entity.Player;
import java.util.Map;
public class DummyBooleanProperty extends EntityPropertyImpl<Boolean> {
public DummyBooleanProperty(String name, boolean def) {
super(name, def, Boolean.class);
}
@Override
public void apply(Boolean value, Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
}
}

@ -0,0 +1,25 @@
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 org.bukkit.entity.Player;
import java.util.Map;
public class EffectsProperty extends EntityPropertyImpl<Boolean> {
private final int bitmask;
public EffectsProperty(String name, int bitmask) {
super(name, false, Boolean.class);
this.bitmask = bitmask;
}
@Override
public void apply(Boolean enabled, Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
EntityData oldData = properties.get(0);
byte oldValue = oldData == null ? 0 : (byte) oldData.getValue();
properties.put(0, newEntityData(0, EntityDataTypes.BYTE, (byte) (oldValue | (enabled ? bitmask : 0))));
}
}

@ -0,0 +1,28 @@
package lol.pyr.znpcsplus.entity.properties;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.protocol.player.Equipment;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.packets.PacketFactory;
import org.bukkit.entity.Player;
import java.util.Map;
public class EquipmentProperty extends EntityPropertyImpl<ItemStack> {
private final PacketFactory packetFactory;
private final EquipmentSlot slot;
public EquipmentProperty(PacketFactory packetFactory, String name, EquipmentSlot slot) {
super(name, null, ItemStack.class);
this.packetFactory = packetFactory;
this.slot = slot;
}
@Override
public void apply(ItemStack value, Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
packetFactory.sendEquipment(player, entity, new Equipment(slot, value));
}
}

@ -0,0 +1,29 @@
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.packets.PacketFactory;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player;
import java.util.Map;
public class GlowProperty extends EntityPropertyImpl<NamedTextColor> {
private final PacketFactory packetFactory;
public GlowProperty(PacketFactory packetFactory) {
super("glow", null, NamedTextColor.class);
this.packetFactory = packetFactory;
}
@Override
public void apply(NamedTextColor value, Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
EntityData oldData = properties.get(0);
byte oldValue = oldData == null ? 0 : (byte) oldData.getValue();
properties.put(0, newEntityData(0, EntityDataTypes.BYTE, (byte) (oldValue | (value == null ? 0 : 0x40))));
if (isSpawned) packetFactory.removeTeam(player, entity);
packetFactory.createTeam(player, entity, value);
}
}

@ -0,0 +1,41 @@
package lol.pyr.znpcsplus.entity.properties;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import java.util.Map;
import java.util.Optional;
public class NameProperty extends EntityPropertyImpl<Component> {
private final boolean legacy;
private final boolean optionalComponent;
public NameProperty() {
super("name", null, Component.class);
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
legacy = version.isOlderThan(ServerVersion.V_1_9);
optionalComponent = version.isNewerThanOrEquals(ServerVersion.V_1_13);
}
@Override
public void apply(Component value, Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
if (value != null) {
String serialized = legacy ?
AdventureSerializer.getLegacyGsonSerializer().serialize(value) :
AdventureSerializer.getGsonSerializer().serialize(value);
if (optionalComponent) properties.put(2, newEntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, Optional.of(serialized)));
else properties.put(2, newEntityData(2, EntityDataTypes.STRING, serialized));
}
if (legacy) properties.put(3, newEntityData(3, EntityDataTypes.BYTE, (byte) (value != null ? 1 : 0)));
else properties.put(3, newEntityData(3, EntityDataTypes.BOOLEAN, value != null));
}
}

@ -2,6 +2,7 @@ package lol.pyr.znpcsplus.hologram;
import lol.pyr.znpcsplus.api.hologram.Hologram;
import lol.pyr.znpcsplus.config.ConfigManager;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.util.Viewable;
import lol.pyr.znpcsplus.util.NpcLocation;
@ -17,6 +18,7 @@ public class HologramImpl extends Viewable implements Hologram {
private final ConfigManager configManager;
private final PacketFactory packetFactory;
private final LegacyComponentSerializer textSerializer;
private final EntityPropertyRegistryImpl propertyRegistry;
private double offset = 0.0;
private long refreshDelay = -1;
@ -24,7 +26,8 @@ public class HologramImpl extends Viewable implements Hologram {
private NpcLocation location;
private final List<HologramLine> lines = new ArrayList<>();
public HologramImpl(ConfigManager configManager, PacketFactory packetFactory, LegacyComponentSerializer textSerializer, NpcLocation location) {
public HologramImpl(EntityPropertyRegistryImpl propertyRegistry, ConfigManager configManager, PacketFactory packetFactory, LegacyComponentSerializer textSerializer, NpcLocation location) {
this.propertyRegistry = propertyRegistry;
this.configManager = configManager;
this.packetFactory = packetFactory;
this.textSerializer = textSerializer;
@ -32,7 +35,7 @@ public class HologramImpl extends Viewable implements Hologram {
}
public void addLineComponent(Component line) {
HologramLine newLine = new HologramLine(packetFactory, null, line);
HologramLine newLine = new HologramLine(propertyRegistry, packetFactory, null, line);
lines.add(newLine);
relocateLines(newLine);
for (Player viewer : getViewers()) newLine.show(viewer.getPlayer());
@ -66,7 +69,7 @@ public class HologramImpl extends Viewable implements Hologram {
}
public void insertLineComponent(int index, Component line) {
HologramLine newLine = new HologramLine(packetFactory, null, line);
HologramLine newLine = new HologramLine(propertyRegistry, packetFactory, null, line);
lines.add(index, newLine);
relocateLines(newLine);
for (Player viewer : getViewers()) newLine.show(viewer.getPlayer());

@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.hologram;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.util.NpcLocation;
@ -10,13 +11,19 @@ import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class HologramLine implements PropertyHolder {
private Component text;
private final PacketEntity armorStand;
private final Set<EntityProperty<?>> properties;
public HologramLine(PacketFactory packetFactory, NpcLocation location, Component text) {
public HologramLine(EntityPropertyRegistryImpl propertyRegistry, PacketFactory packetFactory, NpcLocation location, Component text) {
this.text = text;
this.properties = new HashSet<>();
this.properties.add(propertyRegistry.getByName("name"));
this.properties.add(propertyRegistry.getByName("invisible"));
armorStand = new PacketEntity(packetFactory, this, EntityTypes.ARMOR_STAND, location);
}
@ -61,4 +68,9 @@ public class HologramLine implements PropertyHolder {
public <T> void setProperty(EntityProperty<T> key, T value) {
throw new UnsupportedOperationException("Can't set properties on a hologram");
}
@Override
public Set<EntityProperty<?>> getAppliedProperties() {
return properties;
}
}

@ -20,6 +20,7 @@ import org.bukkit.DyeColor;
* 1.18-1.19 <a href="https://wiki.vg/index.php?title=Entity_metadata&oldid=18191">...</a>
* 1.20 <a href="https://wiki.vg/index.php?title=Entity_metadata">...</a>
*/
@Deprecated
public interface MetadataFactory {
EntityData effects(boolean onFire, boolean glowing, boolean invisible, boolean usingElytra, boolean usingItemLegacy);
EntityData silent(boolean enabled);

@ -5,6 +5,7 @@ import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import lol.pyr.znpcsplus.util.CreeperState;
import lol.pyr.znpcsplus.util.Vector3f;
@Deprecated
public class V1_10MetadataFactory extends V1_9MetadataFactory {
@Override
public EntityData skinLayers(boolean cape, boolean jacket, boolean leftSleeve, boolean rightSleeve, boolean leftLeg, boolean rightLeg, boolean hat) {

@ -3,12 +3,8 @@ package lol.pyr.znpcsplus.metadata;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
@Deprecated
public class V1_11MetadataFactory extends V1_10MetadataFactory {
@Override
public EntityData effects(boolean onFire, boolean glowing, boolean invisible, boolean usingElytra, boolean usingItemLegacy) {
return super.effects(onFire, glowing, invisible, usingElytra, false);
}
@Override
public EntityData usingItem(boolean usingItem, boolean offHand, boolean riptide) {
return newEntityData(6, EntityDataTypes.BYTE, (byte) ((usingItem ? 0x01 : 0) | (offHand ? 0x02 : 0)));

@ -6,6 +6,7 @@ import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
import lol.pyr.znpcsplus.entity.ParrotNBTCompound;
import lol.pyr.znpcsplus.util.ParrotVariant;
@Deprecated
public class V1_12MetadataFactory extends V1_11MetadataFactory {
@Override
public EntityData shoulderEntityLeft(ParrotVariant variant) {

@ -7,6 +7,7 @@ import net.kyori.adventure.text.Component;
import java.util.Optional;
@Deprecated
public class V1_13MetadataFactory extends V1_12MetadataFactory {
@Override
public EntityData name(Component name) {

@ -10,6 +10,7 @@ import lol.pyr.znpcsplus.util.ParrotVariant;
import lol.pyr.znpcsplus.util.Vector3f;
import org.bukkit.DyeColor;
@Deprecated
public class V1_14MetadataFactory extends V1_13MetadataFactory {
@Override
public EntityData skinLayers(boolean cape, boolean jacket, boolean leftSleeve, boolean rightSleeve, boolean leftLeg, boolean rightLeg, boolean hat) {

@ -9,6 +9,7 @@ import lol.pyr.znpcsplus.util.ParrotVariant;
import lol.pyr.znpcsplus.util.Vector3f;
import org.bukkit.DyeColor;
@Deprecated
public class V1_15MetadataFactory extends V1_14MetadataFactory {
@Override
public EntityData shoulderEntityLeft(ParrotVariant variant) {

@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.metadata;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
@Deprecated
public class V1_16MetadataFactory extends V1_15MetadataFactory {
@Override
public EntityData skinLayers(boolean cape, boolean jacket, boolean leftSleeve, boolean rightSleeve, boolean leftLeg, boolean rightLeg, boolean hat) {

@ -9,6 +9,7 @@ import lol.pyr.znpcsplus.util.ParrotVariant;
import lol.pyr.znpcsplus.util.Vector3f;
import org.bukkit.DyeColor;
@Deprecated
public class V1_17MetadataFactory extends V1_16MetadataFactory {
@Override
public EntityData skinLayers(boolean cape, boolean jacket, boolean leftSleeve, boolean rightSleeve, boolean leftLeg, boolean rightLeg, boolean hat) {

@ -2,8 +2,8 @@ package lol.pyr.znpcsplus.metadata;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import lol.pyr.znpcsplus.util.FrogVariant;
@Deprecated
public class V1_19MetadataFactory extends V1_17MetadataFactory {
@Override
public EntityData frogVariant(int variant) {

@ -9,6 +9,7 @@ import lol.pyr.znpcsplus.util.*;
import net.kyori.adventure.text.Component;
import org.bukkit.DyeColor;
@Deprecated
public class V1_8MetadataFactory implements MetadataFactory {
@Override
public EntityData skinLayers(boolean cape, boolean jacket, boolean leftSleeve, boolean rightSleeve, boolean leftLeg, boolean rightLeg, boolean hat) {

@ -6,6 +6,7 @@ import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
import lol.pyr.znpcsplus.util.CreeperState;
import net.kyori.adventure.text.Component;
@Deprecated
public class V1_9MetadataFactory extends V1_8MetadataFactory {
@Override
public EntityData skinLayers(boolean cape, boolean jacket, boolean leftSleeve, boolean rightSleeve, boolean leftLeg, boolean rightLeg, boolean hat) {

@ -1,9 +1,11 @@
package lol.pyr.znpcsplus.npc;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.npc.Npc;
import lol.pyr.znpcsplus.config.ConfigManager;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.hologram.HologramImpl;
import lol.pyr.znpcsplus.interaction.InteractionAction;
@ -31,18 +33,18 @@ public class NpcImpl extends Viewable implements Npc {
private final Map<EntityPropertyImpl<?>, Object> propertyMap = new HashMap<>();
private final List<InteractionAction> actions = new ArrayList<>();
protected NpcImpl(UUID uuid, ConfigManager configManager, LegacyComponentSerializer textSerializer, World world, NpcTypeImpl type, NpcLocation location, PacketFactory packetFactory) {
this(uuid, configManager, packetFactory, textSerializer, world.getName(), type, location);
protected NpcImpl(UUID uuid, EntityPropertyRegistryImpl propertyRegistry, ConfigManager configManager, LegacyComponentSerializer textSerializer, World world, NpcTypeImpl type, NpcLocation location, PacketFactory packetFactory) {
this(uuid, propertyRegistry, configManager, packetFactory, textSerializer, world.getName(), type, location);
}
public NpcImpl(UUID uuid, ConfigManager configManager, PacketFactory packetFactory, LegacyComponentSerializer textSerializer, String world, NpcTypeImpl type, NpcLocation location) {
public NpcImpl(UUID uuid, EntityPropertyRegistryImpl propertyRegistry, ConfigManager configManager, PacketFactory packetFactory, LegacyComponentSerializer textSerializer, String world, NpcTypeImpl type, NpcLocation location) {
this.packetFactory = packetFactory;
this.worldName = world;
this.type = type;
this.location = location;
this.uuid = uuid;
entity = new PacketEntity(packetFactory, this, type.getType(), location);
hologram = new HologramImpl(configManager, packetFactory, textSerializer, location.withY(location.getY() + type.getHologramOffset()));
hologram = new HologramImpl(propertyRegistry, configManager, packetFactory, textSerializer, location.withY(location.getY() + type.getHologramOffset()));
}
@ -112,12 +114,11 @@ public class NpcImpl extends Viewable implements Npc {
hologram.hide(player);
}
private void UNSAFE_refreshMeta() {
for (Player viewer : getViewers()) entity.refreshMeta(viewer);
private <T> void UNSAFE_refreshProperty(EntityPropertyImpl<T> property) {
for (Player viewer : getViewers()) {
List<EntityData> data = property.makeStandaloneData(property.getDefaultValue(), viewer, entity, true);
if (data.size() > 0) packetFactory.sendMetadata(viewer, entity, data);
}
private void UNSAFE_remakeTeam() {
for (Player viewer : getViewers()) entity.remakeTeam(viewer);
}
@SuppressWarnings("unchecked")
@ -135,10 +136,9 @@ public class NpcImpl extends Viewable implements Npc {
}
public <T> void setProperty(EntityPropertyImpl<T> key, T value) {
if (value == null || value.equals(key.getDefaultValue())) removeProperty(key);
if (value == null || value.equals(key.getDefaultValue())) propertyMap.remove(key);
else propertyMap.put(key, value);
UNSAFE_refreshMeta();
if (key.getName().equalsIgnoreCase("glow")) UNSAFE_remakeTeam();
UNSAFE_refreshProperty(key);
}
@SuppressWarnings("unchecked")
@ -146,14 +146,8 @@ public class NpcImpl extends Viewable implements Npc {
setProperty((EntityPropertyImpl<T>) property, (T) value);
}
public void removeProperty(EntityPropertyImpl<?> key) {
propertyMap.remove(key);
UNSAFE_refreshMeta();
if (key.getName().equalsIgnoreCase("glow")) UNSAFE_remakeTeam();
else if (key.getName().equalsIgnoreCase("dinnerbone")) respawn();
}
public Set<EntityPropertyImpl<?>> getAppliedProperties() {
@Override
public Set<EntityProperty<?>> getAppliedProperties() {
return Collections.unmodifiableSet(propertyMap.keySet());
}

@ -22,6 +22,7 @@ public class NpcRegistryImpl implements NpcRegistry {
private final PacketFactory packetFactory;
private final ConfigManager configManager;
private final LegacyComponentSerializer textSerializer;
private final EntityPropertyRegistryImpl propertyRegistry;
private final List<NpcEntryImpl> npcList = new ArrayList<>();
private final Map<String, NpcEntryImpl> npcIdLookupMap = new HashMap<>();
@ -29,6 +30,7 @@ public class NpcRegistryImpl implements NpcRegistry {
public NpcRegistryImpl(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistry actionRegistry, TaskScheduler scheduler, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
this.textSerializer = textSerializer;
this.propertyRegistry = propertyRegistry;
storage = configManager.getConfig().storageType().create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer);
this.packetFactory = packetFactory;
this.configManager = configManager;
@ -134,7 +136,7 @@ public class NpcRegistryImpl implements NpcRegistry {
public NpcEntryImpl create(String id, World world, NpcTypeImpl type, NpcLocation location) {
id = id.toLowerCase();
if (npcIdLookupMap.containsKey(id)) throw new IllegalArgumentException("An npc with the id " + id + " already exists!");
NpcImpl npc = new NpcImpl(UUID.randomUUID(), configManager, textSerializer, world, type, location, packetFactory);
NpcImpl npc = new NpcImpl(UUID.randomUUID(), propertyRegistry, configManager, textSerializer, world, type, location, packetFactory);
NpcEntryImpl entry = new NpcEntryImpl(id, npc);
register(entry);
return entry;

@ -1,12 +1,13 @@
package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.player.Equipment;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.PacketEntity;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
public interface PacketFactory {
@ -16,10 +17,9 @@ public interface PacketFactory {
void teleportEntity(Player player, PacketEntity entity);
CompletableFuture<Void> addTabPlayer(Player player, PacketEntity entity, PropertyHolder properties);
void removeTabPlayer(Player player, PacketEntity entity);
void createTeam(Player player, PacketEntity entity, PropertyHolder properties);
void createTeam(Player player, PacketEntity entity, NamedTextColor glowColor);
void removeTeam(Player player, PacketEntity entity);
Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties);
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 sendEquipment(Player player, PacketEntity entity, PropertyHolder properties);
}

@ -1,27 +0,0 @@
package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.metadata.MetadataFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.Map;
public class V1_10PacketFactory extends V1_9PacketFactory {
public V1_10PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
super(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer);
}
@Override
public Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
Map<Integer, EntityData> data = super.generateMetadata(player, entity, properties);
add(data, metadataFactory.noGravity());
return data;
}
}

@ -1,27 +0,0 @@
package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.metadata.MetadataFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.Map;
public class V1_11PacketFactory extends V1_10PacketFactory {
public V1_11PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
super(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer);
}
@Override
public Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
Map<Integer, EntityData> data = super.generateMetadata(player, entity, properties);
add(data, metadataFactory.usingItem(properties.getProperty(propertyRegistry.getByName("using_item", Boolean.class)), false, false));
return data;
}
}

@ -1,33 +0,0 @@
package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.metadata.MetadataFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import lol.pyr.znpcsplus.util.NpcPose;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.Map;
public class V1_14PacketFactory extends V1_11PacketFactory {
public V1_14PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
super(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer);
}
@Override
public Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
Map<Integer, EntityData> data = super.generateMetadata(player, entity, properties);
add(data, metadataFactory.pose(adaptNpcPose(properties.getProperty(propertyRegistry.getByName("pose", NpcPose.class)))));
return data;
}
protected EntityPose adaptNpcPose(NpcPose pose) {
return EntityPose.valueOf(pose.name());
}
}

@ -1,27 +0,0 @@
package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.protocol.player.Equipment;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEquipment;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.metadata.MetadataFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.List;
public class V1_16PacketFactory extends V1_14PacketFactory {
public V1_16PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
super(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer);
}
@Override
public void sendEquipment(Player player, PacketEntity entity, PropertyHolder properties) {
List<Equipment> equipments = generateEquipments(properties);
if (equipments.size() > 0) sendPacket(player, new WrapperPlayServerEntityEquipment(entity.getEntityId(), equipments));
}
}

@ -1,25 +1,23 @@
package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.metadata.MetadataFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import lol.pyr.znpcsplus.util.NpcLocation;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.Map;
import java.util.Optional;
public class V1_17PacketFactory extends V1_16PacketFactory {
public V1_17PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
super(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer);
public class V1_17PacketFactory extends V1_8PacketFactory {
public V1_17PacketFactory(TaskScheduler scheduler, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
super(scheduler, packetEvents, propertyRegistry, textSerializer);
}
@Override
@ -28,13 +26,6 @@ public class V1_17PacketFactory extends V1_16PacketFactory {
sendPacket(player, new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(),
npcLocationToVector(location), location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.of(new Vector3d())));
sendAllMetadata(player, entity, properties);
createTeam(player, entity, properties);
}
@Override
public Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
Map<Integer, EntityData> data = super.generateMetadata(player, entity, properties);
add(data, metadataFactory.shaking(properties.getProperty(propertyRegistry.getByName("shaking", Boolean.class))));
return data;
createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedTextColor.class)));
}
}

@ -7,10 +7,9 @@ import com.github.retrooper.packetevents.protocol.player.GameMode;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoRemove;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.metadata.MetadataFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
@ -22,8 +21,8 @@ import java.util.concurrent.CompletableFuture;
public class V1_19PacketFactory extends V1_17PacketFactory {
private final boolean oldTabPackets;
public V1_19PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
super(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer);
public V1_19PacketFactory(TaskScheduler scheduler, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
super(scheduler, packetEvents, propertyRegistry, textSerializer);
oldTabPackets = packetEvents.getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_19_2);
}

@ -1,29 +1,28 @@
package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.protocol.player.*;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.Equipment;
import com.github.retrooper.packetevents.protocol.player.GameMode;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.server.*;
import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.metadata.MetadataFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
import lol.pyr.znpcsplus.util.*;
import lol.pyr.znpcsplus.util.NpcLocation;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
@ -32,14 +31,12 @@ import java.util.concurrent.CompletableFuture;
public class V1_8PacketFactory implements PacketFactory {
protected final TaskScheduler scheduler;
protected final MetadataFactory metadataFactory;
protected final PacketEventsAPI<Plugin> packetEvents;
protected final EntityPropertyRegistryImpl propertyRegistry;
protected final LegacyComponentSerializer textSerializer;
public V1_8PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
public V1_8PacketFactory(TaskScheduler scheduler, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
this.scheduler = scheduler;
this.metadataFactory = metadataFactory;
this.packetEvents = packetEvents;
this.propertyRegistry = propertyRegistry;
this.textSerializer = textSerializer;
@ -48,7 +45,7 @@ public class V1_8PacketFactory implements PacketFactory {
@Override
public void spawnPlayer(Player player, PacketEntity entity, PropertyHolder properties) {
addTabPlayer(player, entity, properties).thenAccept(ignored -> {
createTeam(player, entity, properties);
createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedTextColor.class)));
NpcLocation location = entity.getLocation();
sendPacket(player, new WrapperPlayServerSpawnPlayer(entity.getEntityId(),
entity.getUuid(), npcLocationToVector(location), location.getYaw(), location.getPitch(), Collections.emptyList()));
@ -69,7 +66,7 @@ public class V1_8PacketFactory implements PacketFactory {
new WrapperPlayServerSpawnEntity(entity.getEntityId(), Optional.of(entity.getUuid()), entity.getType(), npcLocationToVector(location),
location.getPitch(), location.getYaw(), location.getYaw(), 0, Optional.empty()));
sendAllMetadata(player, entity, properties);
createTeam(player, entity, properties);
createTeam(player, entity, properties.getProperty(propertyRegistry.getByName("glow", NamedTextColor.class)));
}
protected Vector3d npcLocationToVector(NpcLocation location) {
@ -111,12 +108,12 @@ public class V1_8PacketFactory implements PacketFactory {
}
@Override
public void createTeam(Player player, PacketEntity entity, PropertyHolder properties) {
public void createTeam(Player player, PacketEntity entity, NamedTextColor glowColor) {
sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo(
Component.empty(), Component.empty(), Component.empty(),
WrapperPlayServerTeams.NameTagVisibility.NEVER,
WrapperPlayServerTeams.CollisionRule.NEVER,
properties.hasProperty(propertyRegistry.getByName("glow")) ? properties.getProperty(propertyRegistry.getByName("glow", NamedTextColor.class)) : NamedTextColor.WHITE,
glowColor == null ? NamedTextColor.WHITE : glowColor,
WrapperPlayServerTeams.OptionData.NONE
)));
sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.ADD_ENTITIES, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null,
@ -128,21 +125,20 @@ public class V1_8PacketFactory implements PacketFactory {
sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.REMOVE, (WrapperPlayServerTeams.ScoreBoardTeamInfo) null));
}
@Override
public Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
HashMap<Integer, EntityData> data = new HashMap<>();
add(data, metadataFactory.effects(
/*
List<EntityData> data = new ArrayList<>();
data.add(metadataFactory.effects(
properties.getProperty(propertyRegistry.getByName("fire", Boolean.class)),
false,
properties.getProperty(propertyRegistry.getByName("invisible", Boolean.class)),
false,
properties.getProperty(propertyRegistry.getByName("using_item", Boolean.class))
));
add(data, metadataFactory.silent(properties.getProperty(propertyRegistry.getByName("silent", Boolean.class))));
add(data, metadataFactory.potionColor(properties.getProperty(propertyRegistry.getByName("potion_color", Color.class)).asRGB()));
add(data, metadataFactory.potionAmbient(properties.getProperty(propertyRegistry.getByName("potion_ambient", Boolean.class))));
data.add(metadataFactory.silent(properties.getProperty(propertyRegistry.getByName("silent", Boolean.class))));
data.add(metadataFactory.potionColor(properties.getProperty(propertyRegistry.getByName("potion_color", Color.class)).asRGB()));
data.add(metadataFactory.potionAmbient(properties.getProperty(propertyRegistry.getByName("potion_ambient", Boolean.class))));
if (entity.getType().equals(EntityTypes.PLAYER)) {
add(data, metadataFactory.skinLayers(
data.add(metadataFactory.skinLayers(
properties.getProperty(propertyRegistry.getByName("skin_cape", Boolean.class)),
properties.getProperty(propertyRegistry.getByName("skin_jacket", Boolean.class)),
properties.getProperty(propertyRegistry.getByName("skin_left_sleeve", Boolean.class)),
@ -151,60 +147,60 @@ public class V1_8PacketFactory implements PacketFactory {
properties.getProperty(propertyRegistry.getByName("skin_right_leg", Boolean.class)),
properties.getProperty(propertyRegistry.getByName("skin_hat", Boolean.class))
));
add(data, metadataFactory.shoulderEntityLeft(properties.getProperty(propertyRegistry.getByName("shoulder_entity_left", ParrotVariant.class))));
add(data, metadataFactory.shoulderEntityRight(properties.getProperty(propertyRegistry.getByName("shoulder_entity_right", ParrotVariant.class))));
data.add(metadataFactory.shoulderEntityLeft(properties.getProperty(propertyRegistry.getByName("shoulder_entity_left", ParrotVariant.class))));
data.add(metadataFactory.shoulderEntityRight(properties.getProperty(propertyRegistry.getByName("shoulder_entity_right", ParrotVariant.class))));
}
else if (entity.getType().equals(EntityTypes.ARMOR_STAND)) {
add(data, metadataFactory.armorStandProperties(
data.add(metadataFactory.armorStandProperties(
properties.getProperty(propertyRegistry.getByName("small", Boolean.class)),
properties.getProperty(propertyRegistry.getByName("arms", Boolean.class)),
!properties.getProperty(propertyRegistry.getByName("base_plate", Boolean.class))
));
add(data, metadataFactory.armorStandHeadRotation(properties.getProperty(propertyRegistry.getByName("head_rotation", Vector3f.class))));
add(data, metadataFactory.armorStandBodyRotation(properties.getProperty(propertyRegistry.getByName("body_rotation", Vector3f.class))));
add(data, metadataFactory.armorStandLeftArmRotation(properties.getProperty(propertyRegistry.getByName("left_arm_rotation", Vector3f.class))));
add(data, metadataFactory.armorStandRightArmRotation(properties.getProperty(propertyRegistry.getByName("right_arm_rotation", Vector3f.class))));
add(data, metadataFactory.armorStandLeftLegRotation(properties.getProperty(propertyRegistry.getByName("left_leg_rotation", Vector3f.class))));
add(data, metadataFactory.armorStandRightLegRotation(properties.getProperty(propertyRegistry.getByName("right_leg_rotation", Vector3f.class))));
data.add(metadataFactory.armorStandHeadRotation(properties.getProperty(propertyRegistry.getByName("head_rotation", Vector3f.class))));
data.add(metadataFactory.armorStandBodyRotation(properties.getProperty(propertyRegistry.getByName("body_rotation", Vector3f.class))));
data.add(metadataFactory.armorStandLeftArmRotation(properties.getProperty(propertyRegistry.getByName("left_arm_rotation", Vector3f.class))));
data.add(metadataFactory.armorStandRightArmRotation(properties.getProperty(propertyRegistry.getByName("right_arm_rotation", Vector3f.class))));
data.add(metadataFactory.armorStandLeftLegRotation(properties.getProperty(propertyRegistry.getByName("left_leg_rotation", Vector3f.class))));
data.add(metadataFactory.armorStandRightLegRotation(properties.getProperty(propertyRegistry.getByName("right_leg_rotation", Vector3f.class))));
}
else if (entity.getType().equals(EntityTypes.AXOLOTL)) {
add(data, metadataFactory.axolotlVariant(properties.getProperty(propertyRegistry.getByName("axolotl_variant", Integer.class))));
add(data, metadataFactory.playingDead(properties.getProperty(propertyRegistry.getByName("playing_dead", Boolean.class))));
data.add(metadataFactory.axolotlVariant(properties.getProperty(propertyRegistry.getByName("axolotl_variant", Integer.class))));
data.add(metadataFactory.playingDead(properties.getProperty(propertyRegistry.getByName("playing_dead", Boolean.class))));
}
else if (entity.getType().equals(EntityTypes.BAT)) {
add(data, metadataFactory.batHanging(properties.getProperty(propertyRegistry.getByName("hanging", Boolean.class))));
data.add(metadataFactory.batHanging(properties.getProperty(propertyRegistry.getByName("hanging", Boolean.class))));
}
else if (entity.getType().equals(EntityTypes.BEE)) {
add(data, metadataFactory.beeAngry(properties.getProperty(propertyRegistry.getByName("angry", Boolean.class))));
add(data, metadataFactory.beeHasNectar(properties.getProperty(propertyRegistry.getByName("has_nectar", Boolean.class))));
data.add(metadataFactory.beeAngry(properties.getProperty(propertyRegistry.getByName("angry", Boolean.class))));
data.add(metadataFactory.beeHasNectar(properties.getProperty(propertyRegistry.getByName("has_nectar", Boolean.class))));
}
else if (entity.getType().equals(EntityTypes.BLAZE)) {
add(data, metadataFactory.blazeOnFire(properties.getProperty(propertyRegistry.getByName("blaze_on_fire", Boolean.class))));
data.add(metadataFactory.blazeOnFire(properties.getProperty(propertyRegistry.getByName("blaze_on_fire", Boolean.class))));
}
else if (entity.getType().equals(EntityTypes.CAT)) {
add(data, metadataFactory.catVariant(properties.getProperty(propertyRegistry.getByName("cat_variant", CatVariant.class))));
add(data, metadataFactory.catLying(properties.getProperty(propertyRegistry.getByName("cat_lying", Boolean.class))));
add(data, metadataFactory.catCollarColor(properties.getProperty(propertyRegistry.getByName("cat_collar_color", DyeColor.class))));
add(data, metadataFactory.catTamed(properties.hasProperty(propertyRegistry.getByName("cat_collar_color", DyeColor.class))));
data.add(metadataFactory.catVariant(properties.getProperty(propertyRegistry.getByName("cat_variant", CatVariant.class))));
data.add(metadataFactory.catLying(properties.getProperty(propertyRegistry.getByName("cat_lying", Boolean.class))));
data.add(metadataFactory.catCollarColor(properties.getProperty(propertyRegistry.getByName("cat_collar_color", DyeColor.class))));
data.add(metadataFactory.catTamed(properties.hasProperty(propertyRegistry.getByName("cat_collar_color", DyeColor.class))));
}
else if (entity.getType().equals(EntityTypes.CREEPER)) {
add(data, metadataFactory.creeperState(properties.getProperty(propertyRegistry.getByName("creeper_state", CreeperState.class))));
add(data, metadataFactory.creeperCharged(properties.getProperty(propertyRegistry.getByName("creeper_charged", Boolean.class))));
data.add(metadataFactory.creeperState(properties.getProperty(propertyRegistry.getByName("creeper_state", CreeperState.class))));
data.add(metadataFactory.creeperCharged(properties.getProperty(propertyRegistry.getByName("creeper_charged", Boolean.class))));
}
else if (entity.getType().equals(EntityTypes.ENDERMAN)) {
add(data, metadataFactory.endermanHeldBlock(
data.add(metadataFactory.endermanHeldBlock(
properties.getProperty(propertyRegistry.getByName("enderman_held_block", BlockState.class)).getGlobalId())
);
add(data, metadataFactory.endermanScreaming(properties.getProperty(propertyRegistry.getByName("enderman_screaming", Boolean.class))));
add(data, metadataFactory.endermanStaring(properties.getProperty(propertyRegistry.getByName("enderman_staring", Boolean.class))));
data.add(metadataFactory.endermanScreaming(properties.getProperty(propertyRegistry.getByName("enderman_screaming", Boolean.class))));
data.add(metadataFactory.endermanStaring(properties.getProperty(propertyRegistry.getByName("enderman_staring", Boolean.class))));
}
else if (entity.getType().equals(EntityTypes.EVOKER)) {
add(data, metadataFactory.evokerSpell(properties.getProperty(propertyRegistry.getByName("evoker_spell", SpellType.class)).ordinal()));
data.add(metadataFactory.evokerSpell(properties.getProperty(propertyRegistry.getByName("evoker_spell", SpellType.class)).ordinal()));
}
else if (entity.getType().equals(EntityTypes.FOX)) {
// Not sure if this should be in here or in 1.14 PacketFactory
add(data, metadataFactory.foxVariant(properties.getProperty(propertyRegistry.getByName("fox_variant", FoxVariant.class)).ordinal()));
add(data, metadataFactory.foxProperties(
data.add(metadataFactory.foxVariant(properties.getProperty(propertyRegistry.getByName("fox_variant", FoxVariant.class)).ordinal()));
data.add(metadataFactory.foxProperties(
properties.getProperty(propertyRegistry.getByName("fox_sitting", Boolean.class)),
properties.getProperty(propertyRegistry.getByName("fox_crouching", Boolean.class)),
properties.getProperty(propertyRegistry.getByName("fox_sleeping", Boolean.class)),
@ -212,20 +208,20 @@ public class V1_8PacketFactory implements PacketFactory {
));
}
else if (entity.getType().equals(EntityTypes.FROG)) {
add(data, metadataFactory.frogVariant(properties.getProperty(propertyRegistry.getByName("frog_variant", FrogVariant.class)).ordinal()));
data.add(metadataFactory.frogVariant(properties.getProperty(propertyRegistry.getByName("frog_variant", FrogVariant.class)).ordinal()));
}
else if (entity.getType().equals(EntityTypes.GHAST)) {
add(data, metadataFactory.ghastAttacking(properties.getProperty(propertyRegistry.getByName("attacking", Boolean.class))));
data.add(metadataFactory.ghastAttacking(properties.getProperty(propertyRegistry.getByName("attacking", Boolean.class))));
}
else if (entity.getType().equals(EntityTypes.GOAT)) {
add(data, metadataFactory.goatHasLeftHorn(properties.getProperty(propertyRegistry.getByName("has_left_horn", Boolean.class))));
add(data, metadataFactory.goatHasRightHorn(properties.getProperty(propertyRegistry.getByName("has_right_horn", Boolean.class))));
data.add(metadataFactory.goatHasLeftHorn(properties.getProperty(propertyRegistry.getByName("has_left_horn", Boolean.class))));
data.add(metadataFactory.goatHasRightHorn(properties.getProperty(propertyRegistry.getByName("has_right_horn", Boolean.class))));
}
else if (entity.getType().equals(EntityTypes.GUARDIAN)) {
// TODO
}
else if (entity.getType().equals(EntityTypes.HOGLIN)) {
add(data, metadataFactory.hoglinImmuneToZombification(properties.getProperty(propertyRegistry.getByName("immune_to_zombification", Boolean.class))));
data.add(metadataFactory.hoglinImmuneToZombification(properties.getProperty(propertyRegistry.getByName("immune_to_zombification", Boolean.class))));
}
else if (entity.getType().equals(EntityTypes.VILLAGER)) {
VillagerProfession profession = properties.getProperty(propertyRegistry.getByName("villager_profession", VillagerProfession.class));
@ -233,7 +229,7 @@ public class V1_8PacketFactory implements PacketFactory {
if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_14)) {
professionId = profession.getLegacyId();
}
add(data, metadataFactory.villagerData(
data.add(metadataFactory.villagerData(
properties.getProperty(propertyRegistry.getByName("villager_type", VillagerType.class)).ordinal(),
professionId,
properties.getProperty(propertyRegistry.getByName("villager_level", VillagerLevel.class)).ordinal() + 1
@ -241,49 +237,33 @@ public class V1_8PacketFactory implements PacketFactory {
}
if (properties.getProperty(propertyRegistry.getByName("dinnerbone", Boolean.class))) {
add(data, metadataFactory.name(Component.text("Dinnerbone")));
data.add(metadataFactory.name(Component.text("Dinnerbone")));
}
else if (properties.hasProperty(propertyRegistry.getByName("name"))) {
add(data, metadataFactory.name(PapiUtil.set(textSerializer, player, properties.getProperty(propertyRegistry.getByName("name", Component.class)))));
add(data, metadataFactory.nameShown());
data.add(metadataFactory.name(PapiUtil.set(textSerializer, player, properties.getProperty(propertyRegistry.getByName("name", Component.class)))));
data.add(metadataFactory.nameShown());
}
return data;
}
*/
@Override
public void sendAllMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
sendMetadata(player, entity, new ArrayList<>(generateMetadata(player, entity, properties).values()));
sendEquipment(player, entity, properties);
Map<Integer, EntityData> datas = new HashMap<>();
for (EntityProperty<?> property : properties.getAppliedProperties())
((EntityPropertyImpl<?>) property).UNSAFE_update(properties.getProperty(property), player, entity, false, datas);
sendMetadata(player, entity, new ArrayList<>(datas.values()));
}
@Override
public void sendMetadata(Player player, PacketEntity entity, List<EntityData> data) {
packetEvents.getPlayerManager().sendPacket(player, new WrapperPlayServerEntityMetadata(entity.getEntityId(), data));
sendPacket(player, new WrapperPlayServerEntityMetadata(entity.getEntityId(), data));
}
@Override
public void sendEquipment(Player player, PacketEntity entity, PropertyHolder properties) {
for (Equipment equipment : generateEquipments(properties))
public void sendEquipment(Player player, PacketEntity entity, Equipment equipment) {
sendPacket(player, new WrapperPlayServerEntityEquipment(entity.getEntityId(), Collections.singletonList(equipment)));
}
protected List<Equipment> generateEquipments(PropertyHolder properties) {
HashMap<String, EquipmentSlot> equipmentSlotMap = new HashMap<>();
equipmentSlotMap.put("helmet", EquipmentSlot.HELMET);
equipmentSlotMap.put("chestplate", EquipmentSlot.CHEST_PLATE);
equipmentSlotMap.put("leggings", EquipmentSlot.LEGGINGS);
equipmentSlotMap.put("boots", EquipmentSlot.BOOTS);
equipmentSlotMap.put("hand", EquipmentSlot.MAIN_HAND);
equipmentSlotMap.put("offhand", EquipmentSlot.OFF_HAND);
List<Equipment> equipements = new ArrayList<>();
for (Map.Entry<String, EquipmentSlot> entry : equipmentSlotMap.entrySet()) {
if (!properties.hasProperty(propertyRegistry.getByName(entry.getKey()))) continue;
equipements.add(new Equipment(entry.getValue(), properties.getProperty(propertyRegistry.getByName(entry.getKey(), ItemStack.class))));
}
return equipements;
}
protected void sendPacket(Player player, PacketWrapper<?> packet) {
packetEvents.getPlayerManager().sendPacket(player, packet);
}

@ -1,32 +0,0 @@
package lol.pyr.znpcsplus.packets;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PacketEntity;
import lol.pyr.znpcsplus.metadata.MetadataFactory;
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.Map;
public class V1_9PacketFactory extends V1_8PacketFactory {
public V1_9PacketFactory(TaskScheduler scheduler, MetadataFactory metadataFactory, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) {
super(scheduler, metadataFactory, packetEvents, propertyRegistry, textSerializer);
}
@Override
public Map<Integer, EntityData> generateMetadata(Player player, PacketEntity entity, PropertyHolder properties) {
Map<Integer, EntityData> data = super.generateMetadata(player, entity, properties);
add(data, metadataFactory.effects(properties.getProperty(propertyRegistry.getByName("fire", Boolean.class)),
properties.hasProperty(propertyRegistry.getByName("glow", Boolean.class)),
properties.getProperty(propertyRegistry.getByName("invisible", Boolean.class)),
false,
properties.getProperty(propertyRegistry.getByName("using_item", Boolean.class))
));
return data;
}
}

@ -1,8 +1,10 @@
package lol.pyr.znpcsplus.storage.yaml;
import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.config.ConfigManager;
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
import lol.pyr.znpcsplus.entity.PropertySerializer;
import lol.pyr.znpcsplus.hologram.HologramImpl;
import lol.pyr.znpcsplus.hologram.HologramLine;
import lol.pyr.znpcsplus.interaction.ActionRegistry;
@ -52,7 +54,7 @@ public class YamlStorage implements NpcStorage {
for (File file : files) if (file.isFile() && file.getName().toLowerCase().endsWith(".yml")) {
YamlConfiguration config = YamlConfiguration.loadConfiguration(file);
UUID uuid = config.contains("uuid") ? UUID.fromString(config.getString("uuid")) : UUID.randomUUID();
NpcImpl npc = new NpcImpl(uuid, configManager, packetFactory, textSerializer, config.getString("world"),
NpcImpl npc = new NpcImpl(uuid, propertyRegistry, configManager, packetFactory, textSerializer, config.getString("world"),
typeRegistry.getByName(config.getString("type")), deserializeLocation(config.getConfigurationSection("location")));
if (config.isBoolean("enabled")) npc.setEnabled(config.getBoolean("enabled"));
@ -65,7 +67,7 @@ public class YamlStorage implements NpcStorage {
Bukkit.getLogger().log(Level.WARNING, "Unknown property '" + key + "' for npc '" + config.getString("id") + "'. skipping ...");
continue;
}
npc.UNSAFE_setProperty(property, property.deserialize(properties.getString(key)));
npc.UNSAFE_setProperty(property, propertyRegistry.getSerializer(property.getType()).deserialize(properties.getString(key)));
}
}
HologramImpl hologram = npc.getHologram();
@ -101,8 +103,9 @@ public class YamlStorage implements NpcStorage {
config.set("location", serializeLocation(npc.getLocation()));
config.set("type", npc.getType().getName());
for (EntityPropertyImpl<?> property : npc.getAppliedProperties()) {
config.set("properties." + property.getName(), property.serialize(npc));
for (EntityProperty<?> property : npc.getAppliedProperties()) {
PropertySerializer<?> serializer = propertyRegistry.getSerializer(((EntityPropertyImpl<?>) property).getType());
config.set("properties." + property.getName(), serializer.UNSAFE_serialize(npc.getProperty(property)));
}
HologramImpl hologram = npc.getHologram();