From 6bf66ec98cae159598932f160e95508eefcc54a0 Mon Sep 17 00:00:00 2001 From: Florian CUNY Date: Sun, 14 Apr 2019 14:55:24 +0200 Subject: [PATCH] Started implementation of Blueprints (replacement of Schems) --- .../world/bentobox/bentobox/BentoBox.java | 14 +- .../bentobox/api/blueprints/Blueprint.java | 84 ++++++++++++ .../api/blueprints/BlueprintBundle.java | 21 +++ .../bentobox/api/blueprints/Clipboard.java | 8 ++ .../bentobox/managers/AddonsManager.java | 30 +++-- .../bentobox/managers/BlueprintsManager.java | 123 ++++++++++++++++++ .../bentobox/managers/SchemsManager.java | 25 ++-- 7 files changed, 276 insertions(+), 29 deletions(-) create mode 100644 src/main/java/world/bentobox/bentobox/api/blueprints/Blueprint.java create mode 100644 src/main/java/world/bentobox/bentobox/api/blueprints/BlueprintBundle.java create mode 100644 src/main/java/world/bentobox/bentobox/api/blueprints/Clipboard.java create mode 100644 src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java index 30521dd32..bfaadf47a 100644 --- a/src/main/java/world/bentobox/bentobox/BentoBox.java +++ b/src/main/java/world/bentobox/bentobox/BentoBox.java @@ -26,6 +26,7 @@ import world.bentobox.bentobox.listeners.PanelListenerManager; import world.bentobox.bentobox.listeners.PortalTeleportationListener; import world.bentobox.bentobox.listeners.StandardSpawnProtectionListener; import world.bentobox.bentobox.managers.AddonsManager; +import world.bentobox.bentobox.managers.BlueprintsManager; import world.bentobox.bentobox.managers.CommandsManager; import world.bentobox.bentobox.managers.FlagsManager; import world.bentobox.bentobox.managers.HooksManager; @@ -62,6 +63,7 @@ public class BentoBox extends JavaPlugin { private IslandWorldManager islandWorldManager; private RanksManager ranksManager; private SchemsManager schemsManager; + private BlueprintsManager blueprintsManager; private HooksManager hooksManager; private PlaceholdersManager placeholdersManager; private IslandDeletionManager islandDeletionManager; @@ -135,6 +137,7 @@ public class BentoBox extends JavaPlugin { islandWorldManager = new IslandWorldManager(this); // Load schems manager schemsManager = new SchemsManager(this); + blueprintsManager = new BlueprintsManager(this); // Locales manager must be loaded before addons localesManager = new LocalesManager(this); @@ -378,6 +381,15 @@ public class BentoBox extends JavaPlugin { return schemsManager; } + /** + * Returns the instance of the {@link BlueprintsManager}. + * @return the {@link BlueprintsManager}. + * @since 1.5.0 + */ + public BlueprintsManager getBlueprintsManager() { + return blueprintsManager; + } + /** * Returns whether BentoBox is fully loaded or not. * This basically means that all managers are instantiated and can therefore be safely accessed. @@ -432,7 +444,7 @@ public class BentoBox extends JavaPlugin { * @see org.bukkit.plugin.java.JavaPlugin#getDefaultWorldGenerator(java.lang.String, java.lang.String) */ @Override - public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { + public ChunkGenerator getDefaultWorldGenerator(@NonNull String worldName, String id) { return addonsManager.getDefaultWorldGenerator(worldName, id); } diff --git a/src/main/java/world/bentobox/bentobox/api/blueprints/Blueprint.java b/src/main/java/world/bentobox/bentobox/api/blueprints/Blueprint.java new file mode 100644 index 000000000..3714a417a --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/api/blueprints/Blueprint.java @@ -0,0 +1,84 @@ +package world.bentobox.bentobox.api.blueprints; + +import com.google.gson.Gson; +import com.google.gson.stream.JsonReader; +import org.bukkit.Material; +import org.bukkit.World; +import org.eclipse.jdt.annotation.NonNull; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.List; +import java.util.zip.ZipFile; + +/** + * @since 1.5.0 + * @author Poslovitch + */ +public class Blueprint { + + public static final @NonNull String FILE_EXTENSION = "blueprint"; + + private @NonNull String name; + private String displayName; + private @NonNull Material icon = Material.PAPER; + private List description; //TODO + private World.Environment environment; + + private Clipboard clipboard; + + public Blueprint(@NonNull String name, @NonNull ZipFile zip) throws IOException { + this.name = name; + try (JsonReader reader = new Gson().newJsonReader(new InputStreamReader(zip.getInputStream(zip.getEntry("properties.json"))))) { + readProperties(reader); + } + } + + private void readProperties(@NonNull JsonReader reader) throws IOException { + reader.beginObject(); + while (reader.hasNext()) { + String field = reader.nextName(); + switch (field) { + case "displayName": + displayName = reader.nextString(); + break; + case "icon": + icon = Material.valueOf(reader.nextString()); + break; + case "environment": + environment = World.Environment.valueOf(reader.nextString()); + break; + default: + reader.skipValue(); + break; + } + } + reader.endObject(); + } + + @NonNull + public String getName() { + return name; + } + + public String getDisplayName() { + return displayName; + } + + @NonNull + public Material getIcon() { + return icon; + } + + public List getDescription() { + return description; + } + + public World.Environment getEnvironment() { + return environment; + } + + public Clipboard getClipboard() { + return clipboard; + } +} diff --git a/src/main/java/world/bentobox/bentobox/api/blueprints/BlueprintBundle.java b/src/main/java/world/bentobox/bentobox/api/blueprints/BlueprintBundle.java new file mode 100644 index 000000000..3942b9074 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/api/blueprints/BlueprintBundle.java @@ -0,0 +1,21 @@ +package world.bentobox.bentobox.api.blueprints; + +import org.bukkit.Material; + +import java.util.List; + +/** + * Represents a bundle of three {@link Blueprint}s. + * This is what the player will choose when creating his island. + * @since 1.5.0 + * @author Poslovitch + */ +public class BlueprintBundle { + + private Material icon; + private String displayName; + private List description; + private Blueprint overworldBlueprint; + private Blueprint netherBlueprint; + private Blueprint endBlueprint; +} diff --git a/src/main/java/world/bentobox/bentobox/api/blueprints/Clipboard.java b/src/main/java/world/bentobox/bentobox/api/blueprints/Clipboard.java new file mode 100644 index 000000000..4e5aa34dc --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/api/blueprints/Clipboard.java @@ -0,0 +1,8 @@ +package world.bentobox.bentobox.api.blueprints; + +/** + * @author tastybento, Poslovitch + * @since 1.5.0 + */ +public class Clipboard { +} diff --git a/src/main/java/world/bentobox/bentobox/managers/AddonsManager.java b/src/main/java/world/bentobox/bentobox/managers/AddonsManager.java index 06dc6c7fa..bf0ab0dd1 100644 --- a/src/main/java/world/bentobox/bentobox/managers/AddonsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/AddonsManager.java @@ -1,5 +1,18 @@ package world.bentobox.bentobox.managers; +import org.bukkit.Bukkit; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.generator.ChunkGenerator; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.addons.Addon; +import world.bentobox.bentobox.api.addons.AddonClassLoader; +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonFormatException; +import world.bentobox.bentobox.api.events.addon.AddonEvent; + import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -17,20 +30,6 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; -import org.bukkit.Bukkit; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.generator.ChunkGenerator; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; - -import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.api.addons.Addon; -import world.bentobox.bentobox.api.addons.AddonClassLoader; -import world.bentobox.bentobox.api.addons.GameModeAddon; -import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonFormatException; -import world.bentobox.bentobox.api.events.addon.AddonEvent; - /** * @author tastybento, ComminQ */ @@ -116,6 +115,9 @@ public class AddonsManager { plugin.getIWM().addGameMode(gameMode); // Register the schems plugin.getSchemsManager().loadIslands(gameMode); + + plugin.getBlueprintsManager().extractDefaultBlueprints(gameMode); + plugin.getBlueprintsManager().loadBlueprints(gameMode); } // Addon successfully loaded addon.setState(Addon.State.LOADED); diff --git a/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java b/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java new file mode 100644 index 000000000..ce29fccd5 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/managers/BlueprintsManager.java @@ -0,0 +1,123 @@ +package world.bentobox.bentobox.managers; + +import org.eclipse.jdt.annotation.NonNull; +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.blueprints.Blueprint; +import world.bentobox.bentobox.api.blueprints.BlueprintBundle; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.zip.ZipFile; + +/** + * Handles {@link world.bentobox.bentobox.api.blueprints.Blueprint Blueprints}. + * @since 1.5.0 + * @author Poslovitch + */ +public class BlueprintsManager { + + public static final @NonNull String FOLDER_NAME = "blueprints"; + + private @NonNull BentoBox plugin; + + private @NonNull Map> blueprints; + private @NonNull Map> blueprintBundles; + + public BlueprintsManager(@NonNull BentoBox plugin) { + this.plugin = plugin; + this.blueprints = new HashMap<>(); + this.blueprintBundles = new HashMap<>(); + } + + /** + * Extracts the blueprints provided by this {@link GameModeAddon} in its .jar file. + * This will do nothing if the blueprints folder already exists for this GameModeAddon. + * @param addon the {@link GameModeAddon} to extract the blueprints from. + */ + public void extractDefaultBlueprints(@NonNull GameModeAddon addon) { + File folder = getBlueprintsFolder(addon); + if (folder.exists()) { + // If the folder exists, do not copy anything from the jar + return; + } + + if (!folder.exists() && !folder.mkdirs()) { + plugin.logError("Could not create the '" + FOLDER_NAME + "' folder!"); + plugin.logError("This might be due to incorrectly set-up write permissions on the operating system."); + return; + } + + // Get any blueprints from the jar and save them. + // TODO + } + + /** + * Loads the blueprints of this addon from its blueprints folder. + * @param addon the {@link GameModeAddon} to load the blueprints of. + */ + public void loadBlueprints(@NonNull GameModeAddon addon) { + File folder = getBlueprintsFolder(addon); + // Create the empty list if not already there + blueprints.putIfAbsent(addon, new LinkedList<>()); + // Look through the folder + FilenameFilter filter = (dir, name) -> name.toLowerCase().endsWith("." + Blueprint.FILE_EXTENSION); + Arrays.stream(Objects.requireNonNull(folder.list(filter))).map(name -> name.split("\\.")[0]).forEach(name -> loadBlueprint(addon, name)); + } + + /** + * Loads the blueprint of this addon corresponding to this name. + * @param addon the {@link GameModeAddon} to load the blueprint from. + * @param name the name of the blueprint to load, without the file extension. + * E.g: {@code "island"}. + */ + public void loadBlueprint(@NonNull GameModeAddon addon, @NonNull String name) { + File folder = getBlueprintsFolder(addon); + // Create the empty list if not already there + blueprints.putIfAbsent(addon, new LinkedList<>()); + // Load the blueprint + plugin.log("Loading " + name + ".blueprint for " + addon.getDescription().getName()); + try { + Blueprint blueprint = new Blueprint(name, new ZipFile(new File(folder, name + "." + Blueprint.FILE_EXTENSION))); + blueprints.get(addon).add(blueprint); + } catch (Exception e) { + // TODO: add error debug + } + } + + @NonNull + public Map> getBlueprints() { + return blueprints; + } + + @NonNull + public List getBlueprints(@NonNull GameModeAddon addon) { + return blueprints.getOrDefault(addon, new LinkedList<>()); + } + + @NonNull + public Map> getBlueprintBundles() { + return blueprintBundles; + } + + @NonNull + public List getBlueprintBundles(@NonNull GameModeAddon addon) { + return blueprintBundles.getOrDefault(addon, new LinkedList<>()); + } + + /** + * Returns a {@link File} instance of the blueprints folder of this {@link GameModeAddon}. + * @param addon the {@link GameModeAddon} + * @return a {@link File} instance of the blueprints folder of this GameModeAddon. + */ + @NonNull + public File getBlueprintsFolder(@NonNull GameModeAddon addon) { + return new File(addon.getDataFolder(), FOLDER_NAME); + } +} diff --git a/src/main/java/world/bentobox/bentobox/managers/SchemsManager.java b/src/main/java/world/bentobox/bentobox/managers/SchemsManager.java index 3343fb41f..2be595d3d 100644 --- a/src/main/java/world/bentobox/bentobox/managers/SchemsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/SchemsManager.java @@ -1,5 +1,16 @@ package world.bentobox.bentobox.managers; +import org.bukkit.World; +import org.bukkit.configuration.InvalidConfigurationException; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.addons.Addon; +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.schems.Clipboard; +import world.bentobox.bentobox.util.Util; + import java.io.File; import java.io.FilenameFilter; import java.io.IOException; @@ -11,18 +22,6 @@ import java.util.Set; import java.util.TreeMap; import java.util.jar.JarFile; -import org.bukkit.World; -import org.bukkit.configuration.InvalidConfigurationException; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; - -import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.api.addons.Addon; -import world.bentobox.bentobox.api.addons.GameModeAddon; -import world.bentobox.bentobox.database.objects.Island; -import world.bentobox.bentobox.schems.Clipboard; -import world.bentobox.bentobox.util.Util; - public class SchemsManager { /** @@ -96,8 +95,6 @@ public class SchemsManager { Arrays.stream(Objects.requireNonNull(schems.list(schemFilter))).map(name -> name.substring(0, name.length() - 6)).forEach(name -> importSchem(addon, schems, name)); } - - /** * Imports one schem to the game mode * @param addon