diff --git a/src/main/java/net/knarcraft/minigames/arena/Arena.java b/src/main/java/net/knarcraft/minigames/arena/Arena.java deleted file mode 100644 index 880a97c..0000000 --- a/src/main/java/net/knarcraft/minigames/arena/Arena.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.knarcraft.minigames.arena; - -import org.jetbrains.annotations.NotNull; - -import java.util.UUID; - -/** - * An interface describing all arenas - */ -public interface Arena { - - /** - * Gets the id of this arena - * - * @return

This arena's identifier

- */ - @NotNull UUID getArenaId(); - - /** - * Gets the name of this arena - * - * @return

The name of this arena

- */ - @NotNull String getArenaName(); - - /** - * Gets this arena's sanitized name - * - * @return

This arena's sanitized name

- */ - @NotNull String getArenaNameSanitized(); - -} diff --git a/src/main/java/net/knarcraft/minigames/arena/ArenaGameMode.java b/src/main/java/net/knarcraft/minigames/arena/ArenaGameMode.java index cc1130a..ebfdfdc 100644 --- a/src/main/java/net/knarcraft/minigames/arena/ArenaGameMode.java +++ b/src/main/java/net/knarcraft/minigames/arena/ArenaGameMode.java @@ -1,4 +1,8 @@ package net.knarcraft.minigames.arena; +/** + * An interface describing any arena game-mode + */ public interface ArenaGameMode { + } diff --git a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java index 037e234..b2608d3 100644 --- a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java +++ b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java @@ -1,7 +1,6 @@ package net.knarcraft.minigames.arena.dropper; import net.knarcraft.minigames.MiniGames; -import net.knarcraft.minigames.arena.Arena; import net.knarcraft.minigames.arena.ArenaGameMode; import net.knarcraft.minigames.arena.ArenaRecordsRegistry; import net.knarcraft.minigames.config.DropperConfiguration; @@ -20,7 +19,7 @@ import static net.knarcraft.minigames.util.InputValidationHelper.isInvalid; /** * A representation of one dropper arena */ -public class DropperArena implements Arena { +public class DropperArena { /** * An unique and persistent identifier for this arena @@ -134,12 +133,20 @@ public class DropperArena implements Arena { return this.dropperArenaData; } - @Override + /** + * Gets the id of this arena + * + * @return

This arena's identifier

+ */ public @NotNull UUID getArenaId() { return this.arenaId; } - @Override + /** + * Gets the name of this arena + * + * @return

The name of this arena

+ */ public @NotNull String getArenaName() { return this.arenaName; } @@ -196,7 +203,11 @@ public class DropperArena implements Arena { return this.winBlockType; } - @Override + /** + * Gets this arena's sanitized name + * + * @return

This arena's sanitized name

+ */ public @NotNull String getArenaNameSanitized() { return StringSanitizer.sanitizeArenaName(this.getArenaName()); } diff --git a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaGroup.java b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaGroup.java index b06f222..190bceb 100644 --- a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaGroup.java +++ b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaGroup.java @@ -114,7 +114,7 @@ public class DropperArenaGroup extends ArenaGroup { String name = (String) data.get("groupName"); List serializableArenas = (List) data.get("arenas"); List arenas = new ArrayList<>(); - + SerializableConverter.getRawValue(new ArrayList<>(serializableArenas), arenas); return new DropperArenaGroup(id, name, arenas); } diff --git a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaHandler.java b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaHandler.java index 3fbeb8f..4861a4c 100644 --- a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaHandler.java +++ b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaHandler.java @@ -1,7 +1,7 @@ package net.knarcraft.minigames.arena.dropper; import net.knarcraft.minigames.MiniGames; -import net.knarcraft.minigames.util.ArenaStorageHelper; +import net.knarcraft.minigames.util.DropperArenaStorageHelper; import net.knarcraft.minigames.util.StringSanitizer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -163,7 +163,7 @@ public class DropperArenaHandler { this.arenas.remove(arenaId); this.arenaNameLookup.remove(arena.getArenaNameSanitized()); this.arenaGroups.remove(arenaId); - if (!ArenaStorageHelper.removeDropperArenaData(arenaId)) { + if (!DropperArenaStorageHelper.removeDropperArenaData(arenaId)) { MiniGames.log(Level.WARNING, "Unable to remove dropper arena data file " + arenaId + ".yml. " + "You must remove it manually!"); } @@ -177,7 +177,7 @@ public class DropperArenaHandler { */ public void saveData(UUID arenaId) { try { - ArenaStorageHelper.saveDropperArenaData(this.arenas.get(arenaId).getData()); + DropperArenaStorageHelper.saveDropperArenaData(this.arenas.get(arenaId).getData()); } catch (IOException e) { MiniGames.log(Level.SEVERE, "Unable to save arena data! Data loss can occur!"); MiniGames.log(Level.SEVERE, e.getMessage()); @@ -189,7 +189,7 @@ public class DropperArenaHandler { */ public void saveGroups() { try { - ArenaStorageHelper.saveDropperArenaGroups(new HashSet<>(this.arenaGroups.values())); + DropperArenaStorageHelper.saveDropperArenaGroups(new HashSet<>(this.arenaGroups.values())); } catch (IOException e) { MiniGames.log(Level.SEVERE, "Unable to save current arena groups! " + "Data loss can occur!"); @@ -209,7 +209,7 @@ public class DropperArenaHandler { * Loads all dropper groups from disk */ private void loadGroups() { - Set arenaGroups = ArenaStorageHelper.loadDropperArenaGroups(); + Set arenaGroups = DropperArenaStorageHelper.loadDropperArenaGroups(); Map arenaGroupMap = new HashMap<>(); for (DropperArenaGroup arenaGroup : arenaGroups) { for (UUID arenaId : arenaGroup.getArenas()) { @@ -224,7 +224,7 @@ public class DropperArenaHandler { */ public void saveArenas() { try { - ArenaStorageHelper.saveDropperArenas(this.arenas); + DropperArenaStorageHelper.saveDropperArenas(this.arenas); } catch (IOException e) { MiniGames.log(Level.SEVERE, "Unable to save current arenas! " + "Data loss can occur!"); @@ -236,7 +236,7 @@ public class DropperArenaHandler { * Loads all arenas from disk */ private void loadArenas() { - this.arenas = ArenaStorageHelper.loadDropperArenas(); + this.arenas = DropperArenaStorageHelper.loadDropperArenas(); // Save a map from arena name to arena id for improved performance this.arenaNameLookup = new HashMap<>(); diff --git a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java index 8cb6026..d62581e 100644 --- a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java +++ b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java @@ -3,6 +3,7 @@ package net.knarcraft.minigames.arena.parkour; import net.knarcraft.minigames.MiniGames; import net.knarcraft.minigames.arena.ArenaGameMode; import net.knarcraft.minigames.arena.ArenaRecordsRegistry; +import net.knarcraft.minigames.util.MaterialHelper; import net.knarcraft.minigames.util.StringSanitizer; import org.bukkit.Location; import org.bukkit.Material; @@ -55,6 +56,11 @@ public class ParkourArena { */ private @Nullable Location winLocation; + /** + * The names of the block types constituting this arena's kill plane + */ + private @Nullable Set killPlaneBlockNames; + /** * The block types constituting this arena's kill plane */ @@ -80,19 +86,23 @@ public class ParkourArena { * @param spawnLocation

The location players spawn in when entering the arena

* @param exitLocation

The location the players are teleported to when exiting the arena, or null

* @param winBlockType

The material of the block players have to hit to win this parkour arena

+ * @param winLocation

The location a player has to reach to win this arena

* @param parkourArenaData

The arena data keeping track of which players have done what in this arena

* @param arenaHandler

The arena handler used for saving any changes

*/ public ParkourArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation, - @Nullable Location exitLocation, @NotNull Material winBlockType, - @Nullable Set killPlaneBlocks, @NotNull List checkpoints, + @Nullable Location exitLocation, @NotNull Material winBlockType, @Nullable Location winLocation, + @Nullable Set killPlaneBlockNames, @NotNull List checkpoints, @NotNull ParkourArenaData parkourArenaData, @NotNull ParkourArenaHandler arenaHandler) { this.arenaId = arenaId; this.arenaName = arenaName; this.spawnLocation = spawnLocation; this.exitLocation = exitLocation; this.winBlockType = winBlockType; - this.killPlaneBlocks = killPlaneBlocks; + this.winLocation = winLocation; + this.killPlaneBlockNames = killPlaneBlockNames; + this.killPlaneBlocks = this.killPlaneBlockNames == null ? null : MaterialHelper.loadMaterialList( + new ArrayList<>(killPlaneBlockNames)); this.checkpoints = checkpoints; this.parkourArenaData = parkourArenaData; this.parkourArenaHandler = arenaHandler; @@ -208,6 +218,15 @@ public class ParkourArena { } } + /** + * Gets the names of the block types used for this parkour arena's kill plane + * + * @return

The names of the types of blocks that cause a loss

+ */ + public @Nullable Set getKillPlaneBlockNames() { + return this.killPlaneBlockNames; + } + /** * Gets all checkpoint locations for this arena * @@ -309,7 +328,7 @@ public class ParkourArena { if (isInvalid(newLocation)) { return false; } else { - this.exitLocation = newLocation.clone(); + this.winLocation = newLocation.clone(); parkourArenaHandler.saveArenas(); return true; } @@ -318,19 +337,10 @@ public class ParkourArena { /** * Sets the type of blocks constituting this arena's kill plane * - * @param killPlaneBlocks

The blocks that will cause players to lose

- * @return

True if successfully changed

+ * @param killPlaneBlockNames

The names of the blocks that will cause players to lose

*/ - public boolean setKillPlaneBlocks(@NotNull Set killPlaneBlocks) { - for (Material material : killPlaneBlocks) { - // Make sure no nulls have entered the set - if (material == null) { - return false; - } - } - - this.killPlaneBlocks = new HashSet<>(killPlaneBlocks); - return true; + public void setKillPlaneBlocks(@NotNull Set killPlaneBlockNames) { + this.killPlaneBlocks = MaterialHelper.loadMaterialList(new ArrayList<>(killPlaneBlockNames)); } /** diff --git a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaHandler.java b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaHandler.java index 271bc51..e48d98f 100644 --- a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaHandler.java +++ b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaHandler.java @@ -1,7 +1,7 @@ package net.knarcraft.minigames.arena.parkour; import net.knarcraft.minigames.MiniGames; -import net.knarcraft.minigames.util.ArenaStorageHelper; +import net.knarcraft.minigames.util.ParkourArenaStorageHelper; import net.knarcraft.minigames.util.StringSanitizer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -163,7 +163,7 @@ public class ParkourArenaHandler { this.arenas.remove(arenaId); this.arenaNameLookup.remove(arena.getArenaNameSanitized()); this.arenaGroups.remove(arenaId); - if (!ArenaStorageHelper.removeParkourArenaData(arenaId)) { + if (!ParkourArenaStorageHelper.removeParkourArenaData(arenaId)) { MiniGames.log(Level.WARNING, "Unable to remove parkour arena data file " + arenaId + ".yml. " + "You must remove it manually!"); } @@ -177,7 +177,7 @@ public class ParkourArenaHandler { */ public void saveData(UUID arenaId) { try { - ArenaStorageHelper.saveParkourArenaData(this.arenas.get(arenaId).getData()); + ParkourArenaStorageHelper.saveParkourArenaData(this.arenas.get(arenaId).getData()); } catch (IOException e) { MiniGames.log(Level.SEVERE, "Unable to save arena data! Data loss can occur!"); MiniGames.log(Level.SEVERE, e.getMessage()); @@ -189,7 +189,7 @@ public class ParkourArenaHandler { */ public void saveGroups() { try { - ArenaStorageHelper.saveParkourArenaGroups(new HashSet<>(this.arenaGroups.values())); + ParkourArenaStorageHelper.saveParkourArenaGroups(new HashSet<>(this.arenaGroups.values())); } catch (IOException e) { MiniGames.log(Level.SEVERE, "Unable to save current arena groups! " + "Data loss can occur!"); @@ -209,7 +209,7 @@ public class ParkourArenaHandler { * Loads all parkour groups from disk */ private void loadGroups() { - Set arenaGroups = ArenaStorageHelper.loadParkourArenaGroups(); + Set arenaGroups = ParkourArenaStorageHelper.loadParkourArenaGroups(); Map arenaGroupMap = new HashMap<>(); for (ParkourArenaGroup arenaGroup : arenaGroups) { for (UUID arenaId : arenaGroup.getArenas()) { @@ -224,7 +224,7 @@ public class ParkourArenaHandler { */ public void saveArenas() { try { - ArenaStorageHelper.saveParkourArenas(this.arenas); + ParkourArenaStorageHelper.saveParkourArenas(this.arenas); } catch (IOException e) { MiniGames.log(Level.SEVERE, "Unable to save current arenas! " + "Data loss can occur!"); @@ -236,7 +236,7 @@ public class ParkourArenaHandler { * Loads all arenas from disk */ private void loadArenas() { - this.arenas = ArenaStorageHelper.loadParkourArenas(); + this.arenas = ParkourArenaStorageHelper.loadParkourArenas(); // Save a map from arena name to arena id for improved performance this.arenaNameLookup = new HashMap<>(); diff --git a/src/main/java/net/knarcraft/minigames/config/MiniGameConfiguration.java b/src/main/java/net/knarcraft/minigames/config/MiniGameConfiguration.java index 71af689..6786308 100644 --- a/src/main/java/net/knarcraft/minigames/config/MiniGameConfiguration.java +++ b/src/main/java/net/knarcraft/minigames/config/MiniGameConfiguration.java @@ -1,20 +1,13 @@ package net.knarcraft.minigames.config; -import net.knarcraft.minigames.MiniGames; -import org.bukkit.Bukkit; +import net.knarcraft.minigames.util.MaterialHelper; import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Tag; import org.bukkit.configuration.file.FileConfiguration; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.logging.Level; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * A configuration for a mini-game @@ -51,52 +44,9 @@ public abstract class MiniGameConfiguration { /** * Loads the materials specified in the block whitelist */ - protected @NotNull Set loadMaterialList(@NotNull String path) { - Set parsedMaterials = new HashSet<>(); + public @NotNull Set loadMaterialList(@NotNull String path) { List blockWhitelist = configuration.getList(path, new ArrayList<>()); - for (Object value : blockWhitelist) { - if (!(value instanceof String string)) { - continue; - } - - // Try to parse a material tag first - if (parseMaterialTag(parsedMaterials, string)) { - continue; - } - - // Try to parse a material name - Material matched = Material.matchMaterial(string); - if (matched != null) { - parsedMaterials.add(matched); - } else { - MiniGames.log(Level.WARNING, "Unable to parse: " + string); - } - } - return parsedMaterials; - } - - /** - * Tries to parse the material tag in the specified material name - * - * @param targetSet

The set all parsed materials should be added to

- * @param materialName

The material name that might be a material tag

- * @return

True if a tag was found

- */ - protected boolean parseMaterialTag(@NotNull Set targetSet, @NotNull String materialName) { - Pattern pattern = Pattern.compile("^\\+([a-zA-Z_]+)"); - Matcher matcher = pattern.matcher(materialName); - if (matcher.find()) { - // The material is a material tag - Tag tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, NamespacedKey.minecraft( - matcher.group(1).toLowerCase()), Material.class); - if (tag != null) { - targetSet.addAll(tag.getValues()); - } else { - MiniGames.log(Level.WARNING, "Unable to parse: " + materialName); - } - return true; - } - return false; + return MaterialHelper.loadMaterialList(blockWhitelist); } } diff --git a/src/main/java/net/knarcraft/minigames/util/ArenaStorageHelper.java b/src/main/java/net/knarcraft/minigames/util/ArenaStorageHelper.java index 642bd5f..c64ad1d 100644 --- a/src/main/java/net/knarcraft/minigames/util/ArenaStorageHelper.java +++ b/src/main/java/net/knarcraft/minigames/util/ArenaStorageHelper.java @@ -1,305 +1,18 @@ package net.knarcraft.minigames.util; import net.knarcraft.minigames.MiniGames; -import net.knarcraft.minigames.arena.ArenaGameMode; -import net.knarcraft.minigames.arena.ArenaRecordsRegistry; -import net.knarcraft.minigames.arena.dropper.DropperArena; -import net.knarcraft.minigames.arena.dropper.DropperArenaData; -import net.knarcraft.minigames.arena.dropper.DropperArenaGameMode; -import net.knarcraft.minigames.arena.dropper.DropperArenaGroup; -import net.knarcraft.minigames.arena.dropper.DropperArenaRecordsRegistry; -import net.knarcraft.minigames.arena.dropper.DropperArenaStorageKey; -import net.knarcraft.minigames.arena.parkour.ParkourArena; -import net.knarcraft.minigames.arena.parkour.ParkourArenaData; -import net.knarcraft.minigames.arena.parkour.ParkourArenaStorageKey; -import net.knarcraft.minigames.container.SerializableMaterial; -import net.knarcraft.minigames.container.SerializableUUID; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.YamlConfiguration; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; import java.util.UUID; import java.util.logging.Level; -/** - * A helper class for saving and loading arenas - */ public final class ArenaStorageHelper { - private final static File dataFolder = MiniGames.getInstance().getDataFolder(); - private final static String dropperArenasConfigurationSection = "dropperArenas"; - private final static String dropperGroupsConfigurationSection = "dropperGroups"; - private final static String parkourArenasConfigurationSection = "parkourArenas"; - private final static String parkourGroupsConfigurationSection = "parkourGroups"; - private static final File arenaFile = new File(dataFolder, "arenas.yml"); - private static final File groupFile = new File(dataFolder, "groups.yml"); - private static final File dropperArenaDataFolder = new File(dataFolder, "dropper_arena_data"); - private static final File parkourArenaDataFolder = new File(dataFolder, "parkour_arena_data"); - private ArenaStorageHelper() { } - /** - * Saves the given dropper arena groups - * - * @param arenaGroups

The arena groups to save

- * @throws IOException

If unable to write to the file

- */ - public static void saveDropperArenaGroups(@NotNull Set arenaGroups) throws IOException { - YamlConfiguration configuration = new YamlConfiguration(); - ConfigurationSection groupSection = configuration.createSection(dropperGroupsConfigurationSection); - - for (DropperArenaGroup arenaGroup : arenaGroups) { - groupSection.set(arenaGroup.getGroupId().toString(), arenaGroup); - } - - configuration.save(groupFile); - } - - /** - * Loads all existing dropper arena groups - * - * @return

The loaded arena groups

- */ - public static @NotNull Set loadDropperArenaGroups() { - YamlConfiguration configuration = YamlConfiguration.loadConfiguration(groupFile); - ConfigurationSection groupSection = configuration.getConfigurationSection(dropperGroupsConfigurationSection); - //If no such section exists, it must be the case that there is no data to load - if (groupSection == null) { - return new HashSet<>(); - } - - Set arenaGroups = new HashSet<>(); - - for (String sectionName : groupSection.getKeys(false)) { - arenaGroups.add((DropperArenaGroup) groupSection.get(sectionName)); - } - - return arenaGroups; - } - - /** - * Saves the given arenas - * - * @param arenas

The arenas to save

- * @throws IOException

If unable to write to the file

- */ - public static void saveDropperArenas(@NotNull Map arenas) throws IOException { - YamlConfiguration configuration = new YamlConfiguration(); - ConfigurationSection arenaSection = configuration.createSection(dropperArenasConfigurationSection); - for (DropperArena arena : arenas.values()) { - //Note: While the arena name is used as the key, as the key has to be sanitized, the un-sanitized arena name - // must be stored as well - @NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString()); - configSection.set(DropperArenaStorageKey.ID.getKey(), new SerializableUUID(arena.getArenaId())); - configSection.set(DropperArenaStorageKey.NAME.getKey(), arena.getArenaName()); - configSection.set(DropperArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation()); - configSection.set(DropperArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation()); - configSection.set(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey(), arena.getPlayerVerticalVelocity()); - configSection.set(DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey(), arena.getPlayerHorizontalVelocity()); - configSection.set(DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType())); - saveDropperArenaData(arena.getData()); - } - configuration.save(arenaFile); - } - - /** - * Saves the given arenas - * - * @param arenas

The arenas to save

- * @throws IOException

If unable to write to the file

- */ - public static void saveParkourArenas(@NotNull Map arenas) throws IOException { - YamlConfiguration configuration = new YamlConfiguration(); - ConfigurationSection arenaSection = configuration.createSection(parkourArenasConfigurationSection); - for (ParkourArena arena : arenas.values()) { - //Note: While the arena name is used as the key, as the key has to be sanitized, the un-sanitized arena name - // must be stored as well - @NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString()); - configSection.set(ParkourArenaStorageKey.ID.getKey(), new SerializableUUID(arena.getArenaId())); - configSection.set(ParkourArenaStorageKey.NAME.getKey(), arena.getArenaName()); - configSection.set(ParkourArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation()); - configSection.set(ParkourArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation()); - configSection.set(ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType())); - configSection.set(ParkourArenaStorageKey.WIN_LOCATION.getKey(), arena.getWinLocation()); - configSection.set(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey(), arena.getKillPlaneBlocks()); - configSection.set(ParkourArenaStorageKey.CHECKPOINTS.getKey(), arena.getCheckpoints()); - saveParkourArenaData(arena.getData()); - } - configuration.save(arenaFile); - } - - /** - * Loads all arenas - * - * @return

The loaded arenas, or null if the arenas configuration section is missing.

- */ - public static @NotNull Map loadDropperArenas() { - YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaFile); - ConfigurationSection arenaSection = configuration.getConfigurationSection(dropperArenasConfigurationSection); - //If no such section exists, it must be the case that there is no data to load - if (arenaSection == null) { - return new HashMap<>(); - } - - Map loadedArenas = new HashMap<>(); - - for (String sectionName : arenaSection.getKeys(false)) { - ConfigurationSection configurationSection = arenaSection.getConfigurationSection(sectionName); - //I'm not sure whether this could actually happen - if (configurationSection == null) { - continue; - } - - DropperArena arena = loadDropperArena(configurationSection); - if (arena != null) { - loadedArenas.put(arena.getArenaId(), arena); - } - } - - return loadedArenas; - } - - /** - * Loads an arena from the given configuration section - * - * @param configurationSection

The configuration section containing arena data

- * @return

The loaded arena, or null if invalid

- */ - private static @Nullable DropperArena loadDropperArena(@NotNull ConfigurationSection configurationSection) { - UUID arenaId = ((SerializableUUID) configurationSection.get(DropperArenaStorageKey.ID.getKey(), - new SerializableUUID(UUID.randomUUID()))).getRawValue(); - String arenaName = configurationSection.getString(DropperArenaStorageKey.NAME.getKey()); - Location spawnLocation = (Location) configurationSection.get(DropperArenaStorageKey.SPAWN_LOCATION.getKey()); - Location exitLocation = (Location) configurationSection.get(DropperArenaStorageKey.EXIT_LOCATION.getKey()); - double verticalVelocity = configurationSection.getDouble(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey()); - float horizontalVelocity = sanitizeHorizontalVelocity((float) configurationSection.getDouble( - DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey())); - SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get( - DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey()); - - if (arenaName == null || spawnLocation == null) { - MiniGames.log(Level.SEVERE, "Could not load the arena at configuration " + - "section " + configurationSection.getName() + ". Please check the arenas storage file for issues."); - return null; - } - if (winBlockType == null) { - winBlockType = new SerializableMaterial(Material.WATER); - } - - DropperArenaData arenaData = loadDropperArenaData(arenaId); - if (arenaData == null) { - MiniGames.log(Level.SEVERE, "Unable to load arena data for " + arenaId); - - Map recordRegistries = new HashMap<>(); - for (ArenaGameMode arenaGameMode : DropperArenaGameMode.values()) { - recordRegistries.put(arenaGameMode, new DropperArenaRecordsRegistry(arenaId)); - } - arenaData = new DropperArenaData(arenaId, recordRegistries, new HashMap<>()); - } - - return new DropperArena(arenaId, arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity, - winBlockType.getRawValue(), arenaData, MiniGames.getInstance().getDropperArenaHandler()); - } - - /** - * Stores the given arena data to a file - * - * @param arenaData

The arena data to store

- */ - public static void saveParkourArenaData(@NotNull ParkourArenaData arenaData) throws IOException { - YamlConfiguration configuration = new YamlConfiguration(); - configuration.set(ParkourArenaStorageKey.DATA.getKey(), arenaData); - - configuration.save(getParkourArenaDataFile(arenaData.getArenaId())); - } - - /** - * Stores the given arena data to a file - * - * @param arenaData

The arena data to store

- */ - public static void saveDropperArenaData(@NotNull DropperArenaData arenaData) throws IOException { - YamlConfiguration configuration = new YamlConfiguration(); - configuration.set(DropperArenaStorageKey.DATA.getKey(), arenaData); - - configuration.save(getDropperArenaDataFile(arenaData.getArenaId())); - } - - /** - * Loads arena data for the given arena id - * - * @param arenaId

The id of the arena to get data for

- * @return

The loaded arena data

- */ - private static @Nullable DropperArenaData loadDropperArenaData(@NotNull UUID arenaId) { - File arenaDataFile = getDropperArenaDataFile(arenaId); - YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile); - return (DropperArenaData) configuration.get(DropperArenaStorageKey.DATA.getKey()); - } - - /** - * Loads arena data for the given arena id - * - * @param arenaId

The id of the arena to get data for

- * @return

The loaded arena data

- */ - private static @Nullable ParkourArenaData loadParkourArenaData(@NotNull UUID arenaId) { - File arenaDataFile = getParkourArenaDataFile(arenaId); - YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile); - return (ParkourArenaData) configuration.get(ParkourArenaStorageKey.DATA.getKey()); - } - - /** - * Removes data for the arena with the given id - * - * @param arenaId

The id of the arena to remove data for

- * @return

True if the data was successfully removed

- */ - public static boolean removeDropperArenaData(@NotNull UUID arenaId) { - return getDropperArenaDataFile(arenaId).delete(); - } - - /** - * Removes data for the arena with the given id - * - * @param arenaId

The id of the arena to remove data for

- * @return

True if the data was successfully removed

- */ - public static boolean removeParkourArenaData(@NotNull UUID arenaId) { - return getParkourArenaDataFile(arenaId).delete(); - } - - /** - * Gets the file used to store the given arena id's data - * - * @param arenaId

The id of the arena to get a data file for

- * @return

The file the arena's data is/should be stored in

- */ - private static @NotNull File getDropperArenaDataFile(@NotNull UUID arenaId) { - return getArenaDataFile(dropperArenaDataFolder, arenaId); - } - - /** - * Gets the file used to store the given arena id's data - * - * @param arenaId

The id of the arena to get a data file for

- * @return

The file the arena's data is/should be stored in

- */ - private static @NotNull File getParkourArenaDataFile(@NotNull UUID arenaId) { - return getArenaDataFile(parkourArenaDataFolder, arenaId); - } - /** * Gets the file used to store the given arena id's data * @@ -307,7 +20,7 @@ public final class ArenaStorageHelper { * @param arenaId

The id of the arena to get a data file for

* @return

The file the arena's data is/should be stored in

*/ - private static @NotNull File getArenaDataFile(File root, @NotNull UUID arenaId) { + static @NotNull File getArenaDataFile(File root, @NotNull UUID arenaId) { File arenaDataFile = new File(root, arenaId + ".yml"); if (!root.exists() && !root.mkdirs()) { MiniGames.log(Level.SEVERE, "Unable to create the arena data directories"); @@ -315,20 +28,4 @@ public final class ArenaStorageHelper { return arenaDataFile; } - /** - * Sanitizes the given horizontal velocity to make sure it doesn't leave its bounds - * - * @param horizontalVelocity

The horizontal velocity to sanitize

- * @return

The sanitized horizontal velocity

- */ - private static float sanitizeHorizontalVelocity(float horizontalVelocity) { - if (horizontalVelocity < -1) { - return -1; - } else if (horizontalVelocity > 1) { - return 1; - } else { - return horizontalVelocity; - } - } - } diff --git a/src/main/java/net/knarcraft/minigames/util/DropperArenaStorageHelper.java b/src/main/java/net/knarcraft/minigames/util/DropperArenaStorageHelper.java new file mode 100644 index 0000000..b158669 --- /dev/null +++ b/src/main/java/net/knarcraft/minigames/util/DropperArenaStorageHelper.java @@ -0,0 +1,257 @@ +package net.knarcraft.minigames.util; + +import net.knarcraft.minigames.MiniGames; +import net.knarcraft.minigames.arena.ArenaGameMode; +import net.knarcraft.minigames.arena.ArenaRecordsRegistry; +import net.knarcraft.minigames.arena.dropper.DropperArena; +import net.knarcraft.minigames.arena.dropper.DropperArenaData; +import net.knarcraft.minigames.arena.dropper.DropperArenaGameMode; +import net.knarcraft.minigames.arena.dropper.DropperArenaGroup; +import net.knarcraft.minigames.arena.dropper.DropperArenaRecordsRegistry; +import net.knarcraft.minigames.arena.dropper.DropperArenaStorageKey; +import net.knarcraft.minigames.container.SerializableMaterial; +import net.knarcraft.minigames.container.SerializableUUID; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.logging.Level; + +import static net.knarcraft.minigames.util.ArenaStorageHelper.getArenaDataFile; + +/** + * A helper class for saving and loading arenas + */ +public final class DropperArenaStorageHelper { + + private final static File dataFolder = MiniGames.getInstance().getDataFolder(); + private final static String dropperArenasConfigurationSection = "dropperArenas"; + private final static String dropperGroupsConfigurationSection = "dropperGroups"; + private static final File dropperArenaFile = new File(dataFolder, "dropper_arenas.yml"); + private static final File dropperGroupFile = new File(dataFolder, "dropper_groups.yml"); + private static final File dropperArenaDataFolder = new File(dataFolder, "dropper_arena_data"); + + private DropperArenaStorageHelper() { + + } + + /** + * Saves the given dropper arena groups + * + * @param arenaGroups

The arena groups to save

+ * @throws IOException

If unable to write to the file

+ */ + public static void saveDropperArenaGroups(@NotNull Set arenaGroups) throws IOException { + YamlConfiguration configuration = new YamlConfiguration(); + ConfigurationSection groupSection = configuration.createSection(dropperGroupsConfigurationSection); + + for (DropperArenaGroup arenaGroup : arenaGroups) { + groupSection.set(arenaGroup.getGroupId().toString(), arenaGroup); + } + + configuration.save(dropperGroupFile); + } + + /** + * Loads all existing dropper arena groups + * + * @return

The loaded arena groups

+ */ + public static @NotNull Set loadDropperArenaGroups() { + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(dropperGroupFile); + ConfigurationSection groupSection = configuration.getConfigurationSection(dropperGroupsConfigurationSection); + //If no such section exists, it must be the case that there is no data to load + if (groupSection == null) { + return new HashSet<>(); + } + + Set arenaGroups = new HashSet<>(); + + for (String sectionName : groupSection.getKeys(false)) { + arenaGroups.add((DropperArenaGroup) groupSection.get(sectionName)); + } + + return arenaGroups; + } + + /** + * Saves the given arenas + * + * @param arenas

The arenas to save

+ * @throws IOException

If unable to write to the file

+ */ + public static void saveDropperArenas(@NotNull Map arenas) throws IOException { + YamlConfiguration configuration = new YamlConfiguration(); + ConfigurationSection arenaSection = configuration.createSection(dropperArenasConfigurationSection); + for (DropperArena arena : arenas.values()) { + //Note: While the arena name is used as the key, as the key has to be sanitized, the un-sanitized arena name + // must be stored as well + @NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString()); + configSection.set(DropperArenaStorageKey.ID.getKey(), new SerializableUUID(arena.getArenaId())); + configSection.set(DropperArenaStorageKey.NAME.getKey(), arena.getArenaName()); + configSection.set(DropperArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation()); + configSection.set(DropperArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation()); + configSection.set(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey(), arena.getPlayerVerticalVelocity()); + configSection.set(DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey(), arena.getPlayerHorizontalVelocity()); + configSection.set(DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType())); + saveDropperArenaData(arena.getData()); + } + configuration.save(dropperArenaFile); + } + + /** + * Loads all arenas + * + * @return

The loaded arenas, or null if the arenas configuration section is missing.

+ */ + public static @NotNull Map loadDropperArenas() { + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(dropperArenaFile); + ConfigurationSection arenaSection = configuration.getConfigurationSection(dropperArenasConfigurationSection); + //If no such section exists, it must be the case that there is no data to load + if (arenaSection == null) { + return new HashMap<>(); + } + + Map loadedArenas = new HashMap<>(); + + for (String sectionName : arenaSection.getKeys(false)) { + ConfigurationSection configurationSection = arenaSection.getConfigurationSection(sectionName); + //I'm not sure whether this could actually happen + if (configurationSection == null) { + continue; + } + + DropperArena arena = loadDropperArena(configurationSection); + if (arena != null) { + loadedArenas.put(arena.getArenaId(), arena); + } + } + + return loadedArenas; + } + + /** + * Loads an arena from the given configuration section + * + * @param configurationSection

The configuration section containing arena data

+ * @return

The loaded arena, or null if invalid

+ */ + private static @Nullable DropperArena loadDropperArena(@NotNull ConfigurationSection configurationSection) { + UUID arenaId = ((SerializableUUID) configurationSection.get(DropperArenaStorageKey.ID.getKey(), + new SerializableUUID(UUID.randomUUID()))).getRawValue(); + String arenaName = configurationSection.getString(DropperArenaStorageKey.NAME.getKey()); + Location spawnLocation = (Location) configurationSection.get(DropperArenaStorageKey.SPAWN_LOCATION.getKey()); + Location exitLocation = (Location) configurationSection.get(DropperArenaStorageKey.EXIT_LOCATION.getKey()); + double verticalVelocity = configurationSection.getDouble(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey()); + float horizontalVelocity = sanitizeHorizontalVelocity((float) configurationSection.getDouble( + DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey())); + SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get( + DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey()); + + if (arenaName == null || spawnLocation == null) { + MiniGames.log(Level.SEVERE, "Could not load the arena at configuration " + + "section " + configurationSection.getName() + ". Please check the dropper_arenas storage file for issues."); + return null; + } + if (winBlockType == null) { + winBlockType = new SerializableMaterial(Material.WATER); + } + + // Generate new, empty arena data if not available + DropperArenaData arenaData = loadDropperArenaData(arenaId); + if (arenaData == null) { + MiniGames.log(Level.SEVERE, "Unable to load arena data for dropper arena" + arenaId); + arenaData = getEmptyDropperData(arenaId); + } + + return new DropperArena(arenaId, arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity, + winBlockType.getRawValue(), arenaData, MiniGames.getInstance().getDropperArenaHandler()); + } + + /** + * Gets empty dropper data + * + * @param arenaId

The id to get parkour data for

+ * @return

Empty parkour data

+ */ + private static @NotNull DropperArenaData getEmptyDropperData(@NotNull UUID arenaId) { + Map recordRegistries = new HashMap<>(); + Map> playersCompleted = new HashMap<>(); + for (ArenaGameMode arenaGameMode : DropperArenaGameMode.values()) { + recordRegistries.put(arenaGameMode, new DropperArenaRecordsRegistry(arenaId)); + playersCompleted.put(arenaGameMode, new HashSet<>()); + } + return new DropperArenaData(arenaId, recordRegistries, playersCompleted); + } + + /** + * Stores the given arena data to a file + * + * @param arenaData

The arena data to store

+ */ + public static void saveDropperArenaData(@NotNull DropperArenaData arenaData) throws IOException { + YamlConfiguration configuration = new YamlConfiguration(); + configuration.set(DropperArenaStorageKey.DATA.getKey(), arenaData); + + configuration.save(getDropperArenaDataFile(arenaData.getArenaId())); + } + + /** + * Loads arena data for the given arena id + * + * @param arenaId

The id of the arena to get data for

+ * @return

The loaded arena data

+ */ + private static @Nullable DropperArenaData loadDropperArenaData(@NotNull UUID arenaId) { + File arenaDataFile = getDropperArenaDataFile(arenaId); + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile); + return (DropperArenaData) configuration.get(DropperArenaStorageKey.DATA.getKey()); + } + + /** + * Removes data for the arena with the given id + * + * @param arenaId

The id of the arena to remove data for

+ * @return

True if the data was successfully removed

+ */ + public static boolean removeDropperArenaData(@NotNull UUID arenaId) { + return getDropperArenaDataFile(arenaId).delete(); + } + + /** + * Gets the file used to store the given arena id's data + * + * @param arenaId

The id of the arena to get a data file for

+ * @return

The file the arena's data is/should be stored in

+ */ + private static @NotNull File getDropperArenaDataFile(@NotNull UUID arenaId) { + return getArenaDataFile(dropperArenaDataFolder, arenaId); + } + + /** + * Sanitizes the given horizontal velocity to make sure it doesn't leave its bounds + * + * @param horizontalVelocity

The horizontal velocity to sanitize

+ * @return

The sanitized horizontal velocity

+ */ + private static float sanitizeHorizontalVelocity(float horizontalVelocity) { + if (horizontalVelocity < -1) { + return -1; + } else if (horizontalVelocity > 1) { + return 1; + } else { + return horizontalVelocity; + } + } + +} diff --git a/src/main/java/net/knarcraft/minigames/util/MaterialHelper.java b/src/main/java/net/knarcraft/minigames/util/MaterialHelper.java new file mode 100644 index 0000000..821ba9a --- /dev/null +++ b/src/main/java/net/knarcraft/minigames/util/MaterialHelper.java @@ -0,0 +1,76 @@ +package net.knarcraft.minigames.util; + +import net.knarcraft.minigames.MiniGames; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Tag; +import org.jetbrains.annotations.NotNull; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A helper class for dealing with and parsing materials + */ +public final class MaterialHelper { + + private MaterialHelper() { + + } + + /** + * Loads the materials specified in the block whitelist + */ + public static @NotNull Set loadMaterialList(@NotNull List materials) { + Set parsedMaterials = new HashSet<>(); + for (Object value : materials) { + if (!(value instanceof String string)) { + continue; + } + + // Try to parse a material tag first + if (parseMaterialTag(parsedMaterials, string)) { + continue; + } + + // Try to parse a material name + Material matched = Material.matchMaterial(string); + if (matched != null) { + parsedMaterials.add(matched); + } else { + MiniGames.log(Level.WARNING, "Unable to parse: " + string); + } + } + return parsedMaterials; + } + + /** + * Tries to parse the material tag in the specified material name + * + * @param targetSet

The set all parsed materials should be added to

+ * @param materialName

The material name that might be a material tag

+ * @return

True if a tag was found

+ */ + private static boolean parseMaterialTag(@NotNull Set targetSet, @NotNull String materialName) { + Pattern pattern = Pattern.compile("^\\+([a-zA-Z_]+)"); + Matcher matcher = pattern.matcher(materialName); + if (matcher.find()) { + // The material is a material tag + Tag tag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, NamespacedKey.minecraft( + matcher.group(1).toLowerCase()), Material.class); + if (tag != null) { + targetSet.addAll(tag.getValues()); + } else { + MiniGames.log(Level.WARNING, "Unable to parse: " + materialName); + } + return true; + } + return false; + } + +} diff --git a/src/main/java/net/knarcraft/minigames/util/ParkourArenaStorageHelper.java b/src/main/java/net/knarcraft/minigames/util/ParkourArenaStorageHelper.java new file mode 100644 index 0000000..a1d2aff --- /dev/null +++ b/src/main/java/net/knarcraft/minigames/util/ParkourArenaStorageHelper.java @@ -0,0 +1,252 @@ +package net.knarcraft.minigames.util; + +import net.knarcraft.minigames.MiniGames; +import net.knarcraft.minigames.arena.ArenaGameMode; +import net.knarcraft.minigames.arena.ArenaRecordsRegistry; +import net.knarcraft.minigames.arena.parkour.ParkourArena; +import net.knarcraft.minigames.arena.parkour.ParkourArenaData; +import net.knarcraft.minigames.arena.parkour.ParkourArenaGameMode; +import net.knarcraft.minigames.arena.parkour.ParkourArenaGroup; +import net.knarcraft.minigames.arena.parkour.ParkourArenaRecordsRegistry; +import net.knarcraft.minigames.arena.parkour.ParkourArenaStorageKey; +import net.knarcraft.minigames.container.SerializableMaterial; +import net.knarcraft.minigames.container.SerializableUUID; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.logging.Level; + +import static net.knarcraft.minigames.util.ArenaStorageHelper.getArenaDataFile; + +/** + * A helper class for saving and loading parkour arenas + */ +public final class ParkourArenaStorageHelper { + + private ParkourArenaStorageHelper() { + + } + + private final static File dataFolder = MiniGames.getInstance().getDataFolder(); + private final static String parkourArenasConfigurationSection = "parkourArenas"; + private final static String parkourGroupsConfigurationSection = "parkourGroups"; + private static final File parkourGroupFile = new File(dataFolder, "parkour_groups.yml"); + private static final File parkourArenaFile = new File(dataFolder, "parkour_arenas.yml"); + private static final File parkourArenaDataFolder = new File(dataFolder, "parkour_arena_data"); + + /** + * Saves the given parkour arena groups + * + * @param arenaGroups

The arena groups to save

+ * @throws IOException

If unable to write to the file

+ */ + public static void saveParkourArenaGroups(@NotNull Set arenaGroups) throws IOException { + YamlConfiguration configuration = new YamlConfiguration(); + ConfigurationSection groupSection = configuration.createSection(parkourGroupsConfigurationSection); + + for (ParkourArenaGroup arenaGroup : arenaGroups) { + groupSection.set(arenaGroup.getGroupId().toString(), arenaGroup); + } + + configuration.save(parkourGroupFile); + } + + /** + * Loads all existing parkour arena groups + * + * @return

The loaded arena groups

+ */ + public static @NotNull Set loadParkourArenaGroups() { + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(parkourGroupFile); + ConfigurationSection groupSection = configuration.getConfigurationSection(parkourGroupsConfigurationSection); + //If no such section exists, it must be the case that there is no data to load + if (groupSection == null) { + return new HashSet<>(); + } + + Set arenaGroups = new HashSet<>(); + + for (String sectionName : groupSection.getKeys(false)) { + arenaGroups.add((ParkourArenaGroup) groupSection.get(sectionName)); + } + + return arenaGroups; + } + + /** + * Saves the given arenas + * + * @param arenas

The arenas to save

+ * @throws IOException

If unable to write to the file

+ */ + public static void saveParkourArenas(@NotNull Map arenas) throws IOException { + YamlConfiguration configuration = new YamlConfiguration(); + ConfigurationSection arenaSection = configuration.createSection(parkourArenasConfigurationSection); + for (ParkourArena arena : arenas.values()) { + //Note: While the arena name is used as the key, as the key has to be sanitized, the un-sanitized arena name + // must be stored as well + @NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString()); + configSection.set(ParkourArenaStorageKey.ID.getKey(), new SerializableUUID(arena.getArenaId())); + configSection.set(ParkourArenaStorageKey.NAME.getKey(), arena.getArenaName()); + configSection.set(ParkourArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation()); + configSection.set(ParkourArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation()); + configSection.set(ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType())); + configSection.set(ParkourArenaStorageKey.WIN_LOCATION.getKey(), arena.getWinLocation()); + configSection.set(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey(), arena.getKillPlaneBlockNames()); + configSection.set(ParkourArenaStorageKey.CHECKPOINTS.getKey(), arena.getCheckpoints()); + saveParkourArenaData(arena.getData()); + } + configuration.save(parkourArenaFile); + } + + /** + * Loads all arenas + * + * @return

The loaded arenas, or null if the arenas configuration section is missing.

+ */ + public static @NotNull Map loadParkourArenas() { + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(parkourArenaFile); + ConfigurationSection arenaSection = configuration.getConfigurationSection(parkourArenasConfigurationSection); + //If no such section exists, it must be the case that there is no data to load + if (arenaSection == null) { + return new HashMap<>(); + } + + Map loadedArenas = new HashMap<>(); + + for (String sectionName : arenaSection.getKeys(false)) { + ConfigurationSection configurationSection = arenaSection.getConfigurationSection(sectionName); + //I'm not sure whether this could actually happen + if (configurationSection == null) { + continue; + } + + ParkourArena arena = loadParkourArena(configurationSection); + if (arena != null) { + loadedArenas.put(arena.getArenaId(), arena); + } + } + + return loadedArenas; + } + + /** + * Loads an arena from the given configuration section + * + * @param configurationSection

The configuration section containing arena data

+ * @return

The loaded arena, or null if invalid

+ */ + @SuppressWarnings("unchecked") + private static @Nullable ParkourArena loadParkourArena(@NotNull ConfigurationSection configurationSection) { + UUID arenaId = ((SerializableUUID) configurationSection.get(ParkourArenaStorageKey.ID.getKey(), + new SerializableUUID(UUID.randomUUID()))).getRawValue(); + String arenaName = configurationSection.getString(ParkourArenaStorageKey.NAME.getKey()); + Location spawnLocation = (Location) configurationSection.get(ParkourArenaStorageKey.SPAWN_LOCATION.getKey()); + Location exitLocation = (Location) configurationSection.get(ParkourArenaStorageKey.EXIT_LOCATION.getKey()); + Location winLocation = (Location) configurationSection.get(ParkourArenaStorageKey.WIN_LOCATION.getKey()); + SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get( + ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey()); + List killPlaneBlockNames = configurationSection.getList(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey()); + List checkpoints = (List) configurationSection.get(ParkourArenaStorageKey.CHECKPOINTS.getKey()); + + // The arena name and spawn location must be present + if (arenaName == null || spawnLocation == null) { + MiniGames.log(Level.SEVERE, "Could not load the arena at configuration " + + "section " + configurationSection.getName() + ". Please check the parkour_arenas storage file for issues."); + return null; + } + + // Fall back to the default win block + if (winBlockType == null) { + winBlockType = new SerializableMaterial(Material.EMERALD_BLOCK); + } + + // Generate new, empty arena data if not available + ParkourArenaData arenaData = loadParkourArenaData(arenaId); + if (arenaData == null) { + MiniGames.log(Level.SEVERE, "Unable to load arena data for parkour arena" + arenaId); + arenaData = getEmptyParkourData(arenaId); + } + + if (checkpoints == null) { + checkpoints = new ArrayList<>(); + } + + return new ParkourArena(arenaId, arenaName, spawnLocation, exitLocation, winBlockType.getRawValue(), winLocation, + (Set) killPlaneBlockNames, checkpoints, arenaData, MiniGames.getInstance().getParkourArenaHandler()); + } + + /** + * Gets empty parkour data + * + * @param arenaId

The id to get parkour data for

+ * @return

Empty parkour data

+ */ + private static @NotNull ParkourArenaData getEmptyParkourData(@NotNull UUID arenaId) { + Map recordRegistries = new HashMap<>(); + Map> playersCompleted = new HashMap<>(); + for (ArenaGameMode arenaGameMode : ParkourArenaGameMode.values()) { + recordRegistries.put(arenaGameMode, new ParkourArenaRecordsRegistry(arenaId)); + playersCompleted.put(arenaGameMode, new HashSet<>()); + } + return new ParkourArenaData(arenaId, recordRegistries, playersCompleted); + } + + /** + * Stores the given arena data to a file + * + * @param arenaData

The arena data to store

+ */ + public static void saveParkourArenaData(@NotNull ParkourArenaData arenaData) throws IOException { + YamlConfiguration configuration = new YamlConfiguration(); + configuration.set(ParkourArenaStorageKey.DATA.getKey(), arenaData); + + configuration.save(getParkourArenaDataFile(arenaData.getArenaId())); + } + + /** + * Loads arena data for the given arena id + * + * @param arenaId

The id of the arena to get data for

+ * @return

The loaded arena data

+ */ + private static @Nullable ParkourArenaData loadParkourArenaData(@NotNull UUID arenaId) { + File arenaDataFile = getParkourArenaDataFile(arenaId); + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile); + return (ParkourArenaData) configuration.get(ParkourArenaStorageKey.DATA.getKey()); + } + + /** + * Removes data for the arena with the given id + * + * @param arenaId

The id of the arena to remove data for

+ * @return

True if the data was successfully removed

+ */ + public static boolean removeParkourArenaData(@NotNull UUID arenaId) { + return getParkourArenaDataFile(arenaId).delete(); + } + + /** + * Gets the file used to store the given arena id's data + * + * @param arenaId

The id of the arena to get a data file for

+ * @return

The file the arena's data is/should be stored in

+ */ + private static @NotNull File getParkourArenaDataFile(@NotNull UUID arenaId) { + return getArenaDataFile(parkourArenaDataFolder, arenaId); + } + +}