From 98df9cf76378b6702420f6488be259c2795aadaf Mon Sep 17 00:00:00 2001 From: Oliver Date: Sat, 17 May 2025 20:44:58 +0200 Subject: [PATCH] fancyholograms-v3: Refactor storage system --- .../fancyholograms/api/data/HologramData.java | 11 ++ .../commands/FancyHologramsCMD.java | 12 +- .../commands/hologram/CreateCMD.java | 1 + .../main/FancyHologramsPlugin.java | 11 +- .../storage/HologramStorage.java | 13 +- .../storage/StorageMigrator.java | 15 +-- .../storage/json/JsonStorage.java | 118 ++++++++++++++++-- 7 files changed, 142 insertions(+), 39 deletions(-) diff --git a/plugins/fancyholograms/fh-api/src/main/java/de/oliver/fancyholograms/api/data/HologramData.java b/plugins/fancyholograms/fh-api/src/main/java/de/oliver/fancyholograms/api/data/HologramData.java index 17a3a758..610be8bd 100644 --- a/plugins/fancyholograms/fh-api/src/main/java/de/oliver/fancyholograms/api/data/HologramData.java +++ b/plugins/fancyholograms/fh-api/src/main/java/de/oliver/fancyholograms/api/data/HologramData.java @@ -23,6 +23,7 @@ public class HologramData implements YamlData { private final String name; private final HologramType type; + private String filePath; private Location location; private boolean hasChanges = false; private int visibilityDistance = DEFAULT_VISIBILITY_DISTANCE; @@ -50,6 +51,16 @@ public class HologramData implements YamlData { return type; } + @ApiStatus.Internal + public String getFilePath() { + return filePath; + } + + @ApiStatus.Internal + public void setFilePath(String filePath) { + this.filePath = filePath; + } + public @NotNull Location getLocation() { return location.clone(); } diff --git a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/commands/FancyHologramsCMD.java b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/commands/FancyHologramsCMD.java index 4fb50a5b..a682a8a1 100644 --- a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/commands/FancyHologramsCMD.java +++ b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/commands/FancyHologramsCMD.java @@ -7,8 +7,6 @@ import de.oliver.fancyholograms.converter.FHConversionRegistry; import de.oliver.fancyholograms.converter.HologramConversionSession; import de.oliver.fancyholograms.main.FancyHologramsPlugin; import de.oliver.fancylib.MessageHelper; -import org.bukkit.Bukkit; -import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -48,12 +46,10 @@ public final class FancyHologramsCMD extends Command { this.plugin.getHologramConfiguration().reload(plugin); this.plugin.getRegistry().clear(); - for (World world : Bukkit.getWorlds()) { - Collection hologramData = this.plugin.getStorage().loadAll("worlds/"+world.getName()); - for (HologramData data : hologramData) { - Hologram hologram = this.plugin.getHologramFactory().apply(data); - this.plugin.getRegistry().register(hologram); - } + Collection hologramData = this.plugin.getStorage().loadAll(); + for (HologramData data : hologramData) { + Hologram hologram = this.plugin.getHologramFactory().apply(data); + this.plugin.getRegistry().register(hologram); } MessageHelper.success(sender, "Reloaded config and holograms"); diff --git a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/commands/hologram/CreateCMD.java b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/commands/hologram/CreateCMD.java index 1a798635..0d73f136 100644 --- a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/commands/hologram/CreateCMD.java +++ b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/commands/hologram/CreateCMD.java @@ -73,6 +73,7 @@ public class CreateCMD implements Subcommand { displayData.setBillboard(Display.Billboard.FIXED); } } + displayData.setFilePath(name); final var holo = FancyHologramsPlugin.get().getHologramFactory().apply(displayData); if (!new HologramCreateEvent(holo, player).callEvent()) { diff --git a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/main/FancyHologramsPlugin.java b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/main/FancyHologramsPlugin.java index 5d43b32f..450234dc 100644 --- a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/main/FancyHologramsPlugin.java +++ b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/main/FancyHologramsPlugin.java @@ -41,7 +41,6 @@ import de.oliver.fancysitula.api.IFancySitula; import de.oliver.fancysitula.api.utils.ServerVersion; import org.apache.maven.artifact.versioning.ComparableVersion; import org.bukkit.Bukkit; -import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; @@ -193,12 +192,10 @@ public final class FancyHologramsPlugin extends JavaPlugin implements FancyHolog new StorageMigrator().migrate(); - for (World world : Bukkit.getWorlds()) { - Collection data = storage.loadAll("worlds/"+world.getName()); - for (HologramData d : data) { - Hologram hologram = hologramFactory.apply(d); - registry.register(hologram); - } + Collection data = storage.loadAll(); + for (HologramData d : data) { + Hologram hologram = hologramFactory.apply(d); + registry.register(hologram); } controller.initRefreshTask(); diff --git a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/HologramStorage.java b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/HologramStorage.java index 9b07f3b9..3fa4cc4f 100644 --- a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/HologramStorage.java +++ b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/HologramStorage.java @@ -28,10 +28,17 @@ public interface HologramStorage { void delete(HologramData hologram); /** - * Loads all holograms from a specific world + * Loads all holograms from the specified path (recursive). * - * @param world The world to load the holograms from. + * @param path The relative path to the plugin/FancyHolograms/data/holograms directory. * @return A collection of all loaded holograms. */ - Collection loadAll(String world); + Collection loadAll(String path); + + /** + * Loads all holograms from the default path + */ + default Collection loadAll() { + return loadAll(""); + } } diff --git a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/StorageMigrator.java b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/StorageMigrator.java index dbf3953d..c1b2c63f 100644 --- a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/StorageMigrator.java +++ b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/StorageMigrator.java @@ -3,8 +3,6 @@ package de.oliver.fancyholograms.storage; import de.oliver.fancyholograms.api.data.HologramData; import de.oliver.fancyholograms.api.hologram.Hologram; import de.oliver.fancyholograms.main.FancyHologramsPlugin; -import org.bukkit.Bukkit; -import org.bukkit.World; import java.util.Collection; @@ -19,13 +17,12 @@ public class StorageMigrator { FancyHologramsPlugin.get().getFancyLogger().info("Migrating holograms.yml to JSON format..."); HologramStorage yamlStorage = new YamlHologramStorage(); - for (World world : Bukkit.getWorlds()) { - Collection data = yamlStorage.loadAll(world.getName()); - for (HologramData d : data) { - Hologram hologram = FancyHologramsPlugin.get().getHologramFactory().apply(d); - FancyHologramsPlugin.get().getRegistry().register(hologram); - FancyHologramsPlugin.get().getFancyLogger().info("Migrated hologram " + hologram.getData().getName()); - } + Collection data = yamlStorage.loadAll(); + for (HologramData d : data) { + d.setFilePath("migrated/" + d.getName()); + Hologram hologram = FancyHologramsPlugin.get().getHologramFactory().apply(d); + FancyHologramsPlugin.get().getRegistry().register(hologram); + FancyHologramsPlugin.get().getFancyLogger().info("Migrated hologram " + hologram.getData().getName()); } if (!YamlHologramStorage.HOLOGRAMS_CONFIG_FILE.renameTo(YamlHologramStorage.HOLOGRAMS_CONFIG_FILE.getParentFile().toPath().resolve("holograms-old.yml").toFile())) { diff --git a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/json/JsonStorage.java b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/json/JsonStorage.java index ab909ccd..0840284a 100644 --- a/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/json/JsonStorage.java +++ b/plugins/fancyholograms/src/main/java/de/oliver/fancyholograms/storage/json/JsonStorage.java @@ -9,6 +9,7 @@ import de.oliver.fancyholograms.storage.HologramStorage; import de.oliver.fancyholograms.storage.json.model.JsonDataUnion; import de.oliver.jdb.JDB; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -16,10 +17,12 @@ import java.util.List; public class JsonStorage implements HologramStorage { + private static final String DATA_DIR_PATH = "plugins/FancyHolograms/data/holograms"; + private static final File DATA_DIR = new File(DATA_DIR_PATH); private final JDB jdb; public JsonStorage() { - this.jdb = new JDB("plugins/FancyHolograms/data/holograms"); + this.jdb = new JDB(DATA_DIR_PATH); } @Override @@ -31,6 +34,11 @@ public class JsonStorage implements HologramStorage { @Override public void save(HologramData hologram) { + if (hologram.getFilePath() == null || hologram.getFilePath().isEmpty()) { + FancyHolograms.get().getFancyLogger().error("Hologram " + hologram.getName() + " has no file path set"); + return; + } + JsonDataUnion union = switch (hologram.getType()) { case TEXT -> JsonAdapter.toUnion((TextHologramData) hologram); case ITEM -> JsonAdapter.toUnion((ItemHologramData) hologram); @@ -38,7 +46,24 @@ public class JsonStorage implements HologramStorage { }; try { - jdb.set(getKey(hologram), union); + JsonDataUnion[] existing = jdb.get(hologram.getFilePath(), JsonDataUnion[].class); + if (existing == null) { + existing = new JsonDataUnion[0]; + } + for (int i = 0; i < existing.length; i++) { + JsonDataUnion u = existing[i]; + if (u.hologram_data().name().equals(hologram.getName())) { + existing[i] = union; + jdb.set(hologram.getFilePath(), existing); + return; + } + } + + JsonDataUnion[] newArray = new JsonDataUnion[existing.length + 1]; + System.arraycopy(existing, 0, newArray, 0, existing.length); + newArray[existing.length] = union; + + jdb.set(hologram.getFilePath(), newArray); } catch (IOException e) { FancyHolograms.get().getFancyLogger().error("Failed to save hologram " + hologram.getName()); FancyHolograms.get().getFancyLogger().error(e); @@ -47,25 +72,94 @@ public class JsonStorage implements HologramStorage { @Override public void delete(HologramData hologram) { - jdb.delete(getKey(hologram)); + try { + JsonDataUnion[] existing = jdb.get(hologram.getFilePath(), JsonDataUnion[].class); + if (existing == null) { + return; + } + + ArrayList newArray = new ArrayList<>(); + for (JsonDataUnion u : existing) { + if (u.hologram_data().name().equals(hologram.getName())) { + continue; + } + newArray.add(u); + } + + if (newArray.size() == existing.length) { + FancyHolograms.get().getFancyLogger().warn("Hologram " + hologram.getName() + " not found in file " + hologram.getFilePath()); + return; + } + + if (newArray.isEmpty()) { + jdb.delete(hologram.getFilePath()); + return; + } + + jdb.set(hologram.getFilePath(), newArray.toArray(new JsonDataUnion[0])); + } catch (IOException e) { + FancyHolograms.get().getFancyLogger().error("Failed to save hologram " + hologram.getName()); + FancyHolograms.get().getFancyLogger().error(e); + } } @Override - public Collection loadAll(String subdir) { + public Collection loadAll(String path) { List holograms = new ArrayList<>(); - try { - List allTextUnions = jdb.getAll(subdir, JsonDataUnion.class); - allTextUnions.forEach(u -> holograms.add(JsonAdapter.fromJson(u))); - } catch (IOException e) { - FancyHolograms.get().getFancyLogger().error("Failed to load all holograms from " + subdir); - FancyHolograms.get().getFancyLogger().error(e); + File dir = new File(DATA_DIR, path); + if (!dir.isDirectory()) { + return holograms; + } + + File[] files = dir.listFiles(); + if (files == null) { + return holograms; + } + + for (File file : files) { + String fileName = file.getName(); + + if (file.isDirectory()) { + holograms.addAll(loadAll(path + "/" + fileName)); + continue; + } + + // Skip hidden files + if (fileName.startsWith(".") || fileName.startsWith("_")) { + continue; + } + + // Check if the file is a JSON file + if (fileName.endsWith(".json")) { + holograms.addAll(loadFile(path + "/" + fileName.substring(0, fileName.length() - 5))); + } else { + FancyHolograms.get().getFancyLogger().warn("File " + fileName + " is not a valid hologram file"); + } } return holograms; } - public String getKey(HologramData data) { - return "worlds/" + data.getLocation().getWorld().getName() + "/" + data.getName(); + public Collection loadFile(String path) { + List holograms = new ArrayList<>(); + + try { + JsonDataUnion[] allTextUnions = jdb.get(path, JsonDataUnion[].class); + if (allTextUnions == null) { + FancyHolograms.get().getFancyLogger().debug("File " + path + " is empty or does not exist"); + return holograms; + } + for (JsonDataUnion union : allTextUnions) { + HologramData data = JsonAdapter.fromJson(union); + data.setFilePath(path); + holograms.add(data); + } + } catch (IOException e) { + FancyHolograms.get().getFancyLogger().error("Failed to load all holograms from " + path); + FancyHolograms.get().getFancyLogger().error(e); + } + + return holograms; } }