From c780c0ec78c8ea422cecbe9da9d16e52c46a368d Mon Sep 17 00:00:00 2001 From: Pyrbu Date: Tue, 24 Dec 2024 16:11:13 +0100 Subject: [PATCH] add npc serialization methods to the api --- .../java/lol/pyr/znpcsplus/api/NpcApi.java | 7 + .../pyr/znpcsplus/api/npc/NpcRegistry.java | 7 + .../api/serialization/NpcSerializer.java | 20 +++ .../serialization/NpcSerializerRegistry.java | 19 +++ .../java/lol/pyr/znpcsplus/ZNpcsPlus.java | 12 +- .../java/lol/pyr/znpcsplus/ZNpcsPlusApi.java | 10 +- .../commands/storage/MigrateCommand.java | 9 +- .../pyr/znpcsplus/npc/NpcRegistryImpl.java | 13 +- .../NpcSerializerRegistryImpl.java | 33 ++++ .../serialization/YamlSerializer.java | 154 ++++++++++++++++++ .../pyr/znpcsplus/storage/NpcStorageType.java | 11 +- .../znpcsplus/storage/yaml/YamlStorage.java | 115 ++----------- 12 files changed, 289 insertions(+), 121 deletions(-) create mode 100644 api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializer.java create mode 100644 api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializerRegistry.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/serialization/NpcSerializerRegistryImpl.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/NpcApi.java b/api/src/main/java/lol/pyr/znpcsplus/api/NpcApi.java index b32c050..2faf2c8 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/NpcApi.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/NpcApi.java @@ -5,6 +5,7 @@ import lol.pyr.znpcsplus.api.interaction.ActionFactory; import lol.pyr.znpcsplus.api.interaction.ActionRegistry; import lol.pyr.znpcsplus.api.npc.NpcRegistry; import lol.pyr.znpcsplus.api.npc.NpcTypeRegistry; +import lol.pyr.znpcsplus.api.serialization.NpcSerializerRegistry; import lol.pyr.znpcsplus.api.skin.SkinDescriptorFactory; /** @@ -46,4 +47,10 @@ public interface NpcApi { * @return the skin descriptor factory */ SkinDescriptorFactory getSkinDescriptorFactory(); + + /** + * Gets the npc serializer registry. + * @return the npc serializer registry + */ + NpcSerializerRegistry getNpcSerializerRegistry(); } diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java b/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java index 4722e0b..b822354 100644 --- a/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java +++ b/api/src/main/java/lol/pyr/znpcsplus/api/npc/NpcRegistry.java @@ -64,4 +64,11 @@ public interface NpcRegistry { * @param id The ID of the NPC entry */ void delete(String id); + + /** + * Register an NPC to this registry + * NpcEntry instances can be obtained through the NpcSerializer classes + * @param entry The npc to be registered + */ + void register(NpcEntry entry); } diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializer.java b/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializer.java new file mode 100644 index 0000000..f35cbed --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializer.java @@ -0,0 +1,20 @@ +package lol.pyr.znpcsplus.api.serialization; + +import lol.pyr.znpcsplus.api.npc.NpcEntry; + +public interface NpcSerializer { + /** + * Serialize an npc into the type of this serializer + * @param entry The npc entry + * @return The serialized class + */ + T serialize(NpcEntry entry); + + /** + * Deserialize an npc from a serialized class + * Note: This npc will not be registered, you need to also register it using the NpcRegistry#register(NpcEntry) method + * @param model The serialized class + * @return The deserialized NpcEntry + */ + NpcEntry deserialize(T model); +} diff --git a/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializerRegistry.java b/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializerRegistry.java new file mode 100644 index 0000000..74e8d89 --- /dev/null +++ b/api/src/main/java/lol/pyr/znpcsplus/api/serialization/NpcSerializerRegistry.java @@ -0,0 +1,19 @@ +package lol.pyr.znpcsplus.api.serialization; + +public interface NpcSerializerRegistry { + /** + * Get an NpcSerializer that serializes npcs into the provided class + * @param clazz The class to serialize into + * @return The npc serializer instance + * @param The type of the class that the serializer serializes into + */ + NpcSerializer getSerializer(Class clazz); + + /** + * Register an NpcSerializer to be used by other plugins + * @param clazz The class that the serializer serializes into + * @param serializer The serializer itself + * @param The type of the class that the serializer serializes into + */ + void registerSerializer(Class clazz, NpcSerializer serializer); +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java index 07aadf3..2a0d64f 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlus.java @@ -38,6 +38,7 @@ import lol.pyr.znpcsplus.parsers.*; import lol.pyr.znpcsplus.scheduling.FoliaScheduler; import lol.pyr.znpcsplus.scheduling.SpigotScheduler; import lol.pyr.znpcsplus.scheduling.TaskScheduler; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; import lol.pyr.znpcsplus.skin.cache.SkinCacheCleanTask; import lol.pyr.znpcsplus.storage.NpcStorageType; @@ -135,8 +136,9 @@ public class ZNpcsPlus { ActionRegistryImpl actionRegistry = new ActionRegistryImpl(); ActionFactoryImpl actionFactory = new ActionFactoryImpl(scheduler, adventure, textSerializer, bungeeConnector); NpcTypeRegistryImpl typeRegistry = new NpcTypeRegistryImpl(); + NpcSerializerRegistryImpl serializerRegistry = new NpcSerializerRegistryImpl(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer); NpcRegistryImpl npcRegistry = new NpcRegistryImpl(configManager, this, packetFactory, actionRegistry, - scheduler, typeRegistry, propertyRegistry, textSerializer); + scheduler, typeRegistry, propertyRegistry, serializerRegistry, textSerializer); shutdownTasks.add(npcRegistry::unload); UserManager userManager = new UserManager(); @@ -159,7 +161,7 @@ public class ZNpcsPlus { pluginManager.registerEvents(new UserListener(userManager), bootstrap); registerCommands(npcRegistry, skinCache, adventure, actionRegistry, - typeRegistry, propertyRegistry, importerRegistry, configManager, packetFactory); + typeRegistry, propertyRegistry, importerRegistry, configManager, packetFactory, serializerRegistry); log(ChatColor.WHITE + " * Starting tasks..."); if (configManager.getConfig().checkForUpdates()) { @@ -193,7 +195,7 @@ public class ZNpcsPlus { } } - NpcApiProvider.register(bootstrap, new ZNpcsPlusApi(npcRegistry, typeRegistry, propertyRegistry, actionRegistry, actionFactory, skinCache)); + NpcApiProvider.register(bootstrap, new ZNpcsPlusApi(npcRegistry, typeRegistry, propertyRegistry, actionRegistry, actionFactory, skinCache, serializerRegistry)); log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)"); log(""); @@ -246,7 +248,7 @@ public class ZNpcsPlus { private void registerCommands(NpcRegistryImpl npcRegistry, MojangSkinCache skinCache, BukkitAudiences adventure, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, DataImporterRegistry importerRegistry, - ConfigManager configManager, PacketFactory packetFactory) { + ConfigManager configManager, PacketFactory packetFactory, NpcSerializerRegistryImpl serializerRegistry) { Message incorrectUsageMessage = context -> context.send(Component.text("Incorrect usage: /" + context.getUsage(), NamedTextColor.RED)); CommandManager manager = new CommandManager(bootstrap, adventure, incorrectUsageMessage); @@ -322,7 +324,7 @@ public class ZNpcsPlus { .addSubcommand("save", new SaveAllCommand(npcRegistry)) .addSubcommand("reload", new LoadAllCommand(npcRegistry)) .addSubcommand("import", new ImportCommand(npcRegistry, importerRegistry)) - .addSubcommand("migrate", new MigrateCommand(configManager, this, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, npcRegistry.getStorage(), configManager.getConfig().storageType(), npcRegistry))) + .addSubcommand("migrate", new MigrateCommand(configManager, this, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, npcRegistry.getStorage(), configManager.getConfig().storageType(), npcRegistry, serializerRegistry))) .addSubcommand("holo", new MultiCommand(bootstrap.loadHelpMessage("holo")) .addSubcommand("add", new HoloAddCommand(npcRegistry)) .addSubcommand("additem", new HoloAddItemCommand(npcRegistry)) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlusApi.java b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlusApi.java index ef9c8ee..7d272da 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlusApi.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/ZNpcsPlusApi.java @@ -12,6 +12,7 @@ import lol.pyr.znpcsplus.interaction.ActionFactoryImpl; import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.skin.SkinDescriptorFactoryImpl; import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; @@ -22,14 +23,16 @@ public class ZNpcsPlusApi implements NpcApi { private final ActionRegistryImpl actionRegistry; private final ActionFactoryImpl actionFactory; private final SkinDescriptorFactoryImpl skinDescriptorFactory; + private final NpcSerializerRegistryImpl npcSerializerRegistry; - public ZNpcsPlusApi(NpcRegistryImpl npcRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, ActionRegistryImpl actionRegistry, ActionFactoryImpl actionFactory, MojangSkinCache skinCache) { + public ZNpcsPlusApi(NpcRegistryImpl npcRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, ActionRegistryImpl actionRegistry, ActionFactoryImpl actionFactory, MojangSkinCache skinCache, NpcSerializerRegistryImpl npcSerializerRegistry) { this.npcRegistry = npcRegistry; this.typeRegistry = typeRegistry; this.propertyRegistry = propertyRegistry; this.actionRegistry = actionRegistry; this.actionFactory = actionFactory; this.skinDescriptorFactory = new SkinDescriptorFactoryImpl(skinCache); + this.npcSerializerRegistry = npcSerializerRegistry; } @Override @@ -62,4 +65,9 @@ public class ZNpcsPlusApi implements NpcApi { public SkinDescriptorFactory getSkinDescriptorFactory() { return skinDescriptorFactory; } + + @Override + public NpcSerializerRegistryImpl getNpcSerializerRegistry() { + return npcSerializerRegistry; + } } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/MigrateCommand.java b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/MigrateCommand.java index cda3b3c..063b98a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/MigrateCommand.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/commands/storage/MigrateCommand.java @@ -11,6 +11,7 @@ import lol.pyr.znpcsplus.npc.NpcEntryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.storage.NpcStorage; import lol.pyr.znpcsplus.storage.NpcStorageType; import net.kyori.adventure.text.Component; @@ -35,8 +36,9 @@ public class MigrateCommand implements CommandHandler { private final NpcStorage currentStorage; private final NpcStorageType currentStorageType; private final NpcRegistryImpl npcRegistry; + private final NpcSerializerRegistryImpl serializerRegistry; - public MigrateCommand(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcStorage currentStorage, NpcStorageType currentStorageType, NpcRegistryImpl npcRegistry) { + public MigrateCommand(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcStorage currentStorage, NpcStorageType currentStorageType, NpcRegistryImpl npcRegistry, NpcSerializerRegistryImpl serializerRegistry) { this.configManager = configManager; this.plugin = plugin; this.packetFactory = packetFactory; @@ -47,6 +49,7 @@ public class MigrateCommand implements CommandHandler { this.currentStorage = currentStorage; this.currentStorageType = currentStorageType; this.npcRegistry = npcRegistry; + this.serializerRegistry = serializerRegistry; } @Override @@ -63,7 +66,7 @@ public class MigrateCommand implements CommandHandler { if (currentStorageType == from) { fromStorage = currentStorage; } else { - fromStorage = from.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer); + fromStorage = from.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, serializerRegistry); if (fromStorage == null) { context.halt(Component.text("Failed to initialize the source storage. Please check the console for more information.", NamedTextColor.RED)); return; @@ -84,7 +87,7 @@ public class MigrateCommand implements CommandHandler { if (currentStorageType == to) { toStorage = currentStorage; } else { - toStorage = to.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer); + toStorage = to.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, serializerRegistry); if (toStorage == null) { context.halt(Component.text("Failed to initialize the destination storage. Please check the console for more information.", NamedTextColor.RED)); return; diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java index e95cecd..0dc8a1a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/npc/NpcRegistryImpl.java @@ -14,6 +14,7 @@ import lol.pyr.znpcsplus.hologram.HologramText; import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.scheduling.TaskScheduler; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.storage.NpcStorage; import lol.pyr.znpcsplus.storage.NpcStorageType; import lol.pyr.znpcsplus.util.NpcLocation; @@ -35,13 +36,13 @@ public class NpcRegistryImpl implements NpcRegistry { private final Map npcIdLookupMap = new HashMap<>(); private final Map npcUuidLookupMap = new HashMap<>(); - public NpcRegistryImpl(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, TaskScheduler scheduler, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + public NpcRegistryImpl(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, TaskScheduler scheduler, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, NpcSerializerRegistryImpl serializerRegistry, LegacyComponentSerializer textSerializer) { this.textSerializer = textSerializer; this.propertyRegistry = propertyRegistry; - storage = configManager.getConfig().storageType().create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer); + storage = configManager.getConfig().storageType().create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, serializerRegistry); if (storage == null) { Bukkit.getLogger().warning("Failed to initialize storage, falling back to YAML"); - storage = NpcStorageType.YAML.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer); + storage = NpcStorageType.YAML.create(configManager, plugin, packetFactory, actionRegistry, typeRegistry, propertyRegistry, textSerializer, serializerRegistry); } this.packetFactory = packetFactory; this.configManager = configManager; @@ -52,7 +53,13 @@ public class NpcRegistryImpl implements NpcRegistry { } } + @Override + public void register(NpcEntry entry) { + register((NpcEntryImpl) entry); + } + private void register(NpcEntryImpl entry) { + if (entry == null) throw new NullPointerException(); unregister(npcIdLookupMap.put(entry.getId(), entry)); unregister(npcUuidLookupMap.put(entry.getNpc().getUuid(), entry)); npcList.add(entry); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/serialization/NpcSerializerRegistryImpl.java b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/NpcSerializerRegistryImpl.java new file mode 100644 index 0000000..71a7a95 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/NpcSerializerRegistryImpl.java @@ -0,0 +1,33 @@ +package lol.pyr.znpcsplus.serialization; + +import lol.pyr.znpcsplus.api.serialization.NpcSerializer; +import lol.pyr.znpcsplus.api.serialization.NpcSerializerRegistry; +import lol.pyr.znpcsplus.config.ConfigManager; +import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; +import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; +import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; +import lol.pyr.znpcsplus.packets.PacketFactory; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.util.HashMap; +import java.util.Map; + +public class NpcSerializerRegistryImpl implements NpcSerializerRegistry { + private final Map, NpcSerializer> serializerMap = new HashMap<>(); + + public NpcSerializerRegistryImpl(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + registerSerializer(YamlConfiguration.class, new YamlSerializer(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer)); + } + + @SuppressWarnings("unchecked") + @Override + public NpcSerializer getSerializer(Class clazz) { + return (NpcSerializer) serializerMap.get(clazz); + } + + @Override + public void registerSerializer(Class clazz, NpcSerializer serializer) { + serializerMap.put(clazz, serializer); + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java new file mode 100644 index 0000000..6a87564 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/serialization/YamlSerializer.java @@ -0,0 +1,154 @@ +package lol.pyr.znpcsplus.serialization; + +import lol.pyr.znpcsplus.api.entity.EntityProperty; +import lol.pyr.znpcsplus.api.npc.NpcEntry; +import lol.pyr.znpcsplus.api.serialization.NpcSerializer; +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.interaction.ActionRegistryImpl; +import lol.pyr.znpcsplus.npc.NpcEntryImpl; +import lol.pyr.znpcsplus.npc.NpcImpl; +import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; +import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.util.NpcLocation; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class YamlSerializer implements NpcSerializer { + private final static Logger logger = Logger.getLogger("YamlSerializer"); + + private final PacketFactory packetFactory; + private final ConfigManager configManager; + private final ActionRegistryImpl actionRegistry; + private final NpcTypeRegistryImpl typeRegistry; + private final EntityPropertyRegistryImpl propertyRegistry; + private final LegacyComponentSerializer textSerializer; + + public YamlSerializer(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + this.packetFactory = packetFactory; + this.configManager = configManager; + this.actionRegistry = actionRegistry; + this.typeRegistry = typeRegistry; + this.propertyRegistry = propertyRegistry; + this.textSerializer = textSerializer; + } + + @Override + public YamlConfiguration serialize(NpcEntry entry) { + YamlConfiguration config = new YamlConfiguration(); + config.set("id", entry.getId()); + config.set("is-processed", entry.isProcessed()); + config.set("allow-commands", entry.isAllowCommandModification()); + config.set("save", entry.isSave()); + + NpcImpl npc = (NpcImpl) entry.getNpc(); + config.set("enabled", npc.isEnabled()); + config.set("uuid", npc.getUuid().toString()); + config.set("world", npc.getWorldName()); + config.set("location", serializeLocation(npc.getLocation())); + config.set("type", npc.getType().getName()); + + for (EntityProperty property : npc.getAllProperties()) try { + PropertySerializer serializer = propertyRegistry.getSerializer(((EntityPropertyImpl) property).getType()); + if (serializer == null) { + Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + property.getName() + "' for npc '" + entry.getId() + "'. skipping ..."); + continue; + } + config.set("properties." + property.getName(), serializer.UNSAFE_serialize(npc.getProperty(property))); + } catch (Exception exception) { + logger.severe("Failed to serialize property " + property.getName() + " for npc with id " + entry.getId()); + exception.printStackTrace(); + } + + HologramImpl hologram = npc.getHologram(); + if (hologram.getOffset() != 0.0) config.set("hologram.offset", hologram.getOffset()); + if (hologram.getRefreshDelay() != -1) config.set("hologram.refresh-delay", hologram.getRefreshDelay()); + List lines = new ArrayList<>(npc.getHologram().getLines().size()); + for (int i = 0; i < hologram.getLines().size(); i++) { + lines.add(hologram.getLine(i)); + } + config.set("hologram.lines", lines); + config.set("actions", npc.getActions().stream() + .map(actionRegistry::serialize) + .filter(Objects::nonNull) + .collect(Collectors.toList())); + + return config; + } + + @Override + public NpcEntry deserialize(YamlConfiguration config) { + UUID uuid = config.contains("uuid") ? UUID.fromString(config.getString("uuid")) : UUID.randomUUID(); + 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")); + + ConfigurationSection properties = config.getConfigurationSection("properties"); + if (properties != null) { + for (String key : properties.getKeys(false)) { + EntityPropertyImpl property = propertyRegistry.getByName(key); + if (property == null) { + Bukkit.getLogger().log(Level.WARNING, "Unknown property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); + continue; + } + PropertySerializer serializer = propertyRegistry.getSerializer(property.getType()); + if (serializer == null) { + Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); + continue; + } + Object value = serializer.deserialize(properties.getString(key)); + if (value == null) { + Bukkit.getLogger().log(Level.WARNING, "Failed to deserialize property '" + key + "' for npc '" + config.getString("id") + "'. Resetting to default ..."); + value = property.getDefaultValue(); + } + npc.UNSAFE_setProperty(property, value); + } + } + HologramImpl hologram = npc.getHologram(); + hologram.setOffset(config.getDouble("hologram.offset", 0.0)); + hologram.setRefreshDelay(config.getLong("hologram.refresh-delay", -1)); + for (String line : config.getStringList("hologram.lines")) hologram.addLine(line); + for (String s : config.getStringList("actions")) npc.addAction(actionRegistry.deserialize(s)); + + NpcEntryImpl entry = new NpcEntryImpl(config.getString("id"), npc); + entry.setProcessed(config.getBoolean("is-processed")); + entry.setAllowCommandModification(config.getBoolean("allow-commands")); + entry.setSave(config.getBoolean("save")); + + return entry; + } + + public NpcLocation deserializeLocation(ConfigurationSection section) { + return new NpcLocation( + section.getDouble("x"), + section.getDouble("y"), + section.getDouble("z"), + (float) section.getDouble("yaw"), + (float) section.getDouble("pitch") + ); + } + + public YamlConfiguration serializeLocation(NpcLocation location) { + YamlConfiguration config = new YamlConfiguration(); + config.set("x", location.getX()); + config.set("y", location.getY()); + config.set("z", location.getZ()); + config.set("yaw", location.getYaw()); + config.set("pitch", location.getPitch()); + return config; + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java index 5205dfc..b4139cc 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java @@ -6,6 +6,7 @@ import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.interaction.ActionRegistryImpl; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.storage.mysql.MySQLStorage; import lol.pyr.znpcsplus.storage.sqlite.SQLiteStorage; import lol.pyr.znpcsplus.storage.yaml.YamlStorage; @@ -16,13 +17,13 @@ import java.io.File; public enum NpcStorageType { YAML { @Override - public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { - return new YamlStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer, new File(plugin.getDataFolder(), "data")); + public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcSerializerRegistryImpl serializerRegistry) { + return new YamlStorage(serializerRegistry, new File(plugin.getDataFolder(), "data")); } }, SQLITE { @Override - public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcSerializerRegistryImpl serializerRegistry) { try { return new SQLiteStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer, new File(plugin.getDataFolder(), "znpcsplus.sqlite")); } catch (Exception e) { @@ -33,7 +34,7 @@ public enum NpcStorageType { }, MYSQL { @Override - public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcSerializerRegistryImpl serializerRegistry) { try { return new MySQLStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer); } catch (Exception e) { @@ -43,5 +44,5 @@ public enum NpcStorageType { } }; - public abstract NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer); + public abstract NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, NpcSerializerRegistryImpl serializerRegistry); } diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java index 55e46dd..b985fa7 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/yaml/YamlStorage.java @@ -1,47 +1,28 @@ 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.interaction.ActionRegistryImpl; +import lol.pyr.znpcsplus.api.serialization.NpcSerializer; import lol.pyr.znpcsplus.npc.NpcEntryImpl; -import lol.pyr.znpcsplus.npc.NpcImpl; -import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; -import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.serialization.NpcSerializerRegistryImpl; import lol.pyr.znpcsplus.storage.NpcStorage; import lol.pyr.znpcsplus.util.NpcLocation; -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; -import java.util.*; -import java.util.logging.Level; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.logging.Logger; -import java.util.stream.Collectors; public class YamlStorage implements NpcStorage { private final static Logger logger = Logger.getLogger("YamlStorage"); - private final PacketFactory packetFactory; - private final ConfigManager configManager; - private final ActionRegistryImpl actionRegistry; - private final NpcTypeRegistryImpl typeRegistry; - private final EntityPropertyRegistryImpl propertyRegistry; - private final LegacyComponentSerializer textSerializer; private final File folder; + private final NpcSerializer yamlSerializer; - public YamlStorage(PacketFactory packetFactory, ConfigManager configManager, ActionRegistryImpl actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, File folder) { - this.packetFactory = packetFactory; - this.configManager = configManager; - this.actionRegistry = actionRegistry; - this.typeRegistry = typeRegistry; - this.propertyRegistry = propertyRegistry; - this.textSerializer = textSerializer; + public YamlStorage(NpcSerializerRegistryImpl serializerRegistry, File folder) { + this.yamlSerializer = serializerRegistry.getSerializer(YamlConfiguration.class); this.folder = folder; if (!this.folder.exists()) this.folder.mkdirs(); } @@ -53,45 +34,7 @@ public class YamlStorage implements NpcStorage { List npcs = new ArrayList<>(files.length); for (File file : files) if (file.isFile() && file.getName().toLowerCase().endsWith(".yml")) try { YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - UUID uuid = config.contains("uuid") ? UUID.fromString(config.getString("uuid")) : UUID.randomUUID(); - 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")); - - ConfigurationSection properties = config.getConfigurationSection("properties"); - if (properties != null) { - for (String key : properties.getKeys(false)) { - EntityPropertyImpl property = propertyRegistry.getByName(key); - if (property == null) { - Bukkit.getLogger().log(Level.WARNING, "Unknown property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); - continue; - } - PropertySerializer serializer = propertyRegistry.getSerializer(property.getType()); - if (serializer == null) { - Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + key + "' for npc '" + config.getString("id") + "'. skipping ..."); - continue; - } - Object value = serializer.deserialize(properties.getString(key)); - if (value == null) { - Bukkit.getLogger().log(Level.WARNING, "Failed to deserialize property '" + key + "' for npc '" + config.getString("id") + "'. Resetting to default ..."); - value = property.getDefaultValue(); - } - npc.UNSAFE_setProperty(property, value); - } - } - HologramImpl hologram = npc.getHologram(); - hologram.setOffset(config.getDouble("hologram.offset", 0.0)); - hologram.setRefreshDelay(config.getLong("hologram.refresh-delay", -1)); - for (String line : config.getStringList("hologram.lines")) hologram.addLine(line); - for (String s : config.getStringList("actions")) npc.addAction(actionRegistry.deserialize(s)); - - NpcEntryImpl entry = new NpcEntryImpl(config.getString("id"), npc); - entry.setProcessed(config.getBoolean("is-processed")); - entry.setAllowCommandModification(config.getBoolean("allow-commands")); - entry.setSave(true); - - npcs.add(entry); + npcs.add((NpcEntryImpl) yamlSerializer.deserialize(config)); } catch (Throwable t) { logger.severe("Failed to load npc file: " + file.getName()); t.printStackTrace(); @@ -102,43 +45,7 @@ public class YamlStorage implements NpcStorage { @Override public void saveNpcs(Collection npcs) { for (NpcEntryImpl entry : npcs) try { - YamlConfiguration config = new YamlConfiguration(); - config.set("id", entry.getId()); - config.set("is-processed", entry.isProcessed()); - config.set("allow-commands", entry.isAllowCommandModification()); - - NpcImpl npc = entry.getNpc(); - config.set("enabled", npc.isEnabled()); - config.set("uuid", npc.getUuid().toString()); - config.set("world", npc.getWorldName()); - config.set("location", serializeLocation(npc.getLocation())); - config.set("type", npc.getType().getName()); - - for (EntityProperty property : npc.getAllProperties()) try { - PropertySerializer serializer = propertyRegistry.getSerializer(((EntityPropertyImpl) property).getType()); - if (serializer == null) { - Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + property.getName() + "' for npc '" + entry.getId() + "'. skipping ..."); - continue; - } - config.set("properties." + property.getName(), serializer.UNSAFE_serialize(npc.getProperty(property))); - } catch (Exception exception) { - logger.severe("Failed to serialize property " + property.getName() + " for npc with id " + entry.getId()); - exception.printStackTrace(); - } - - HologramImpl hologram = npc.getHologram(); - if (hologram.getOffset() != 0.0) config.set("hologram.offset", hologram.getOffset()); - if (hologram.getRefreshDelay() != -1) config.set("hologram.refresh-delay", hologram.getRefreshDelay()); - List lines = new ArrayList<>(npc.getHologram().getLines().size()); - for (int i = 0; i < hologram.getLines().size(); i++) { - lines.add(hologram.getLine(i)); - } - config.set("hologram.lines", lines); - config.set("actions", npc.getActions().stream() - .map(actionRegistry::serialize) - .filter(Objects::nonNull) - .collect(Collectors.toList())); - + YamlConfiguration config = yamlSerializer.serialize(entry); config.save(fileFor(entry)); } catch (Exception exception) { logger.severe("Failed to save npc with id " + entry.getId());