mirror of
				https://github.com/SunNetservers/MiniGames.git
				synced 2025-11-04 03:33:47 +01:00 
			
		
		
		
	Parkour implementation safety save 3
This is just a safety save in case the code gets too broken to fix.
This commit is contained in:
		@@ -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 <p>This arena's identifier</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotNull UUID getArenaId();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Gets the name of this arena
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return <p>The name of this arena</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotNull String getArenaName();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Gets this arena's sanitized name
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return <p>This arena's sanitized name</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotNull String getArenaNameSanitized();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,4 +1,8 @@
 | 
				
			|||||||
package net.knarcraft.minigames.arena;
 | 
					package net.knarcraft.minigames.arena;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * An interface describing any arena game-mode
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
public interface ArenaGameMode {
 | 
					public interface ArenaGameMode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,6 @@
 | 
				
			|||||||
package net.knarcraft.minigames.arena.dropper;
 | 
					package net.knarcraft.minigames.arena.dropper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.minigames.MiniGames;
 | 
					import net.knarcraft.minigames.MiniGames;
 | 
				
			||||||
import net.knarcraft.minigames.arena.Arena;
 | 
					 | 
				
			||||||
import net.knarcraft.minigames.arena.ArenaGameMode;
 | 
					import net.knarcraft.minigames.arena.ArenaGameMode;
 | 
				
			||||||
import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
 | 
					import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
 | 
				
			||||||
import net.knarcraft.minigames.config.DropperConfiguration;
 | 
					import net.knarcraft.minigames.config.DropperConfiguration;
 | 
				
			||||||
@@ -20,7 +19,7 @@ import static net.knarcraft.minigames.util.InputValidationHelper.isInvalid;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * A representation of one dropper arena
 | 
					 * A representation of one dropper arena
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class DropperArena implements Arena {
 | 
					public class DropperArena {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * An unique and persistent identifier for this arena
 | 
					     * An unique and persistent identifier for this arena
 | 
				
			||||||
@@ -134,12 +133,20 @@ public class DropperArena implements Arena {
 | 
				
			|||||||
        return this.dropperArenaData;
 | 
					        return this.dropperArenaData;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the id of this arena
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>This arena's identifier</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public @NotNull UUID getArenaId() {
 | 
					    public @NotNull UUID getArenaId() {
 | 
				
			||||||
        return this.arenaId;
 | 
					        return this.arenaId;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets the name of this arena
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>The name of this arena</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public @NotNull String getArenaName() {
 | 
					    public @NotNull String getArenaName() {
 | 
				
			||||||
        return this.arenaName;
 | 
					        return this.arenaName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -196,7 +203,11 @@ public class DropperArena implements Arena {
 | 
				
			|||||||
        return this.winBlockType;
 | 
					        return this.winBlockType;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets this arena's sanitized name
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return <p>This arena's sanitized name</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public @NotNull String getArenaNameSanitized() {
 | 
					    public @NotNull String getArenaNameSanitized() {
 | 
				
			||||||
        return StringSanitizer.sanitizeArenaName(this.getArenaName());
 | 
					        return StringSanitizer.sanitizeArenaName(this.getArenaName());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
package net.knarcraft.minigames.arena.dropper;
 | 
					package net.knarcraft.minigames.arena.dropper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.minigames.MiniGames;
 | 
					import net.knarcraft.minigames.MiniGames;
 | 
				
			||||||
import net.knarcraft.minigames.util.ArenaStorageHelper;
 | 
					import net.knarcraft.minigames.util.DropperArenaStorageHelper;
 | 
				
			||||||
import net.knarcraft.minigames.util.StringSanitizer;
 | 
					import net.knarcraft.minigames.util.StringSanitizer;
 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
import org.jetbrains.annotations.Nullable;
 | 
					import org.jetbrains.annotations.Nullable;
 | 
				
			||||||
@@ -163,7 +163,7 @@ public class DropperArenaHandler {
 | 
				
			|||||||
        this.arenas.remove(arenaId);
 | 
					        this.arenas.remove(arenaId);
 | 
				
			||||||
        this.arenaNameLookup.remove(arena.getArenaNameSanitized());
 | 
					        this.arenaNameLookup.remove(arena.getArenaNameSanitized());
 | 
				
			||||||
        this.arenaGroups.remove(arenaId);
 | 
					        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. " +
 | 
					            MiniGames.log(Level.WARNING, "Unable to remove dropper arena data file " + arenaId + ".yml. " +
 | 
				
			||||||
                    "You must remove it manually!");
 | 
					                    "You must remove it manually!");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -177,7 +177,7 @@ public class DropperArenaHandler {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public void saveData(UUID arenaId) {
 | 
					    public void saveData(UUID arenaId) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            ArenaStorageHelper.saveDropperArenaData(this.arenas.get(arenaId).getData());
 | 
					            DropperArenaStorageHelper.saveDropperArenaData(this.arenas.get(arenaId).getData());
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            MiniGames.log(Level.SEVERE, "Unable to save arena data! Data loss can occur!");
 | 
					            MiniGames.log(Level.SEVERE, "Unable to save arena data! Data loss can occur!");
 | 
				
			||||||
            MiniGames.log(Level.SEVERE, e.getMessage());
 | 
					            MiniGames.log(Level.SEVERE, e.getMessage());
 | 
				
			||||||
@@ -189,7 +189,7 @@ public class DropperArenaHandler {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public void saveGroups() {
 | 
					    public void saveGroups() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            ArenaStorageHelper.saveDropperArenaGroups(new HashSet<>(this.arenaGroups.values()));
 | 
					            DropperArenaStorageHelper.saveDropperArenaGroups(new HashSet<>(this.arenaGroups.values()));
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            MiniGames.log(Level.SEVERE, "Unable to save current arena groups! " +
 | 
					            MiniGames.log(Level.SEVERE, "Unable to save current arena groups! " +
 | 
				
			||||||
                    "Data loss can occur!");
 | 
					                    "Data loss can occur!");
 | 
				
			||||||
@@ -209,7 +209,7 @@ public class DropperArenaHandler {
 | 
				
			|||||||
     * Loads all dropper groups from disk
 | 
					     * Loads all dropper groups from disk
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void loadGroups() {
 | 
					    private void loadGroups() {
 | 
				
			||||||
        Set<DropperArenaGroup> arenaGroups = ArenaStorageHelper.loadDropperArenaGroups();
 | 
					        Set<DropperArenaGroup> arenaGroups = DropperArenaStorageHelper.loadDropperArenaGroups();
 | 
				
			||||||
        Map<UUID, DropperArenaGroup> arenaGroupMap = new HashMap<>();
 | 
					        Map<UUID, DropperArenaGroup> arenaGroupMap = new HashMap<>();
 | 
				
			||||||
        for (DropperArenaGroup arenaGroup : arenaGroups) {
 | 
					        for (DropperArenaGroup arenaGroup : arenaGroups) {
 | 
				
			||||||
            for (UUID arenaId : arenaGroup.getArenas()) {
 | 
					            for (UUID arenaId : arenaGroup.getArenas()) {
 | 
				
			||||||
@@ -224,7 +224,7 @@ public class DropperArenaHandler {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public void saveArenas() {
 | 
					    public void saveArenas() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            ArenaStorageHelper.saveDropperArenas(this.arenas);
 | 
					            DropperArenaStorageHelper.saveDropperArenas(this.arenas);
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            MiniGames.log(Level.SEVERE, "Unable to save current arenas! " +
 | 
					            MiniGames.log(Level.SEVERE, "Unable to save current arenas! " +
 | 
				
			||||||
                    "Data loss can occur!");
 | 
					                    "Data loss can occur!");
 | 
				
			||||||
@@ -236,7 +236,7 @@ public class DropperArenaHandler {
 | 
				
			|||||||
     * Loads all arenas from disk
 | 
					     * Loads all arenas from disk
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void loadArenas() {
 | 
					    private void loadArenas() {
 | 
				
			||||||
        this.arenas = ArenaStorageHelper.loadDropperArenas();
 | 
					        this.arenas = DropperArenaStorageHelper.loadDropperArenas();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Save a map from arena name to arena id for improved performance
 | 
					        // Save a map from arena name to arena id for improved performance
 | 
				
			||||||
        this.arenaNameLookup = new HashMap<>();
 | 
					        this.arenaNameLookup = new HashMap<>();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package net.knarcraft.minigames.arena.parkour;
 | 
				
			|||||||
import net.knarcraft.minigames.MiniGames;
 | 
					import net.knarcraft.minigames.MiniGames;
 | 
				
			||||||
import net.knarcraft.minigames.arena.ArenaGameMode;
 | 
					import net.knarcraft.minigames.arena.ArenaGameMode;
 | 
				
			||||||
import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
 | 
					import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
 | 
				
			||||||
 | 
					import net.knarcraft.minigames.util.MaterialHelper;
 | 
				
			||||||
import net.knarcraft.minigames.util.StringSanitizer;
 | 
					import net.knarcraft.minigames.util.StringSanitizer;
 | 
				
			||||||
import org.bukkit.Location;
 | 
					import org.bukkit.Location;
 | 
				
			||||||
import org.bukkit.Material;
 | 
					import org.bukkit.Material;
 | 
				
			||||||
@@ -55,6 +56,11 @@ public class ParkourArena {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    private @Nullable Location winLocation;
 | 
					    private @Nullable Location winLocation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The names of the block types constituting this arena's kill plane
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private @Nullable Set<String> killPlaneBlockNames;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The block types constituting this arena's kill plane
 | 
					     * The block types constituting this arena's kill plane
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -80,19 +86,23 @@ public class ParkourArena {
 | 
				
			|||||||
     * @param spawnLocation    <p>The location players spawn in when entering the arena</p>
 | 
					     * @param spawnLocation    <p>The location players spawn in when entering the arena</p>
 | 
				
			||||||
     * @param exitLocation     <p>The location the players are teleported to when exiting the arena, or null</p>
 | 
					     * @param exitLocation     <p>The location the players are teleported to when exiting the arena, or null</p>
 | 
				
			||||||
     * @param winBlockType     <p>The material of the block players have to hit to win this parkour arena</p>
 | 
					     * @param winBlockType     <p>The material of the block players have to hit to win this parkour arena</p>
 | 
				
			||||||
 | 
					     * @param winLocation      <p>The location a player has to reach to win this arena</p>
 | 
				
			||||||
     * @param parkourArenaData <p>The arena data keeping track of which players have done what in this arena</p>
 | 
					     * @param parkourArenaData <p>The arena data keeping track of which players have done what in this arena</p>
 | 
				
			||||||
     * @param arenaHandler     <p>The arena handler used for saving any changes</p>
 | 
					     * @param arenaHandler     <p>The arena handler used for saving any changes</p>
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public ParkourArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
 | 
					    public ParkourArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
 | 
				
			||||||
                        @Nullable Location exitLocation, @NotNull Material winBlockType,
 | 
					                        @Nullable Location exitLocation, @NotNull Material winBlockType, @Nullable Location winLocation,
 | 
				
			||||||
                        @Nullable Set<Material> killPlaneBlocks, @NotNull List<Location> checkpoints,
 | 
					                        @Nullable Set<String> killPlaneBlockNames, @NotNull List<Location> checkpoints,
 | 
				
			||||||
                        @NotNull ParkourArenaData parkourArenaData, @NotNull ParkourArenaHandler arenaHandler) {
 | 
					                        @NotNull ParkourArenaData parkourArenaData, @NotNull ParkourArenaHandler arenaHandler) {
 | 
				
			||||||
        this.arenaId = arenaId;
 | 
					        this.arenaId = arenaId;
 | 
				
			||||||
        this.arenaName = arenaName;
 | 
					        this.arenaName = arenaName;
 | 
				
			||||||
        this.spawnLocation = spawnLocation;
 | 
					        this.spawnLocation = spawnLocation;
 | 
				
			||||||
        this.exitLocation = exitLocation;
 | 
					        this.exitLocation = exitLocation;
 | 
				
			||||||
        this.winBlockType = winBlockType;
 | 
					        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.checkpoints = checkpoints;
 | 
				
			||||||
        this.parkourArenaData = parkourArenaData;
 | 
					        this.parkourArenaData = parkourArenaData;
 | 
				
			||||||
        this.parkourArenaHandler = arenaHandler;
 | 
					        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 <p>The names of the types of blocks that cause a loss</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public @Nullable Set<String> getKillPlaneBlockNames() {
 | 
				
			||||||
 | 
					        return this.killPlaneBlockNames;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Gets all checkpoint locations for this arena
 | 
					     * Gets all checkpoint locations for this arena
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -309,7 +328,7 @@ public class ParkourArena {
 | 
				
			|||||||
        if (isInvalid(newLocation)) {
 | 
					        if (isInvalid(newLocation)) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            this.exitLocation = newLocation.clone();
 | 
					            this.winLocation = newLocation.clone();
 | 
				
			||||||
            parkourArenaHandler.saveArenas();
 | 
					            parkourArenaHandler.saveArenas();
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -318,19 +337,10 @@ public class ParkourArena {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Sets the type of blocks constituting this arena's kill plane
 | 
					     * Sets the type of blocks constituting this arena's kill plane
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param killPlaneBlocks <p>The blocks that will cause players to lose</p>
 | 
					     * @param killPlaneBlockNames <p>The names of the blocks that will cause players to lose</p>
 | 
				
			||||||
     * @return <p>True if successfully changed</p>
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public boolean setKillPlaneBlocks(@NotNull Set<Material> killPlaneBlocks) {
 | 
					    public void setKillPlaneBlocks(@NotNull Set<String> killPlaneBlockNames) {
 | 
				
			||||||
        for (Material material : killPlaneBlocks) {
 | 
					        this.killPlaneBlocks = MaterialHelper.loadMaterialList(new ArrayList<>(killPlaneBlockNames));
 | 
				
			||||||
            // Make sure no nulls have entered the set
 | 
					 | 
				
			||||||
            if (material == null) {
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.killPlaneBlocks = new HashSet<>(killPlaneBlocks);
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
package net.knarcraft.minigames.arena.parkour;
 | 
					package net.knarcraft.minigames.arena.parkour;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.minigames.MiniGames;
 | 
					import net.knarcraft.minigames.MiniGames;
 | 
				
			||||||
import net.knarcraft.minigames.util.ArenaStorageHelper;
 | 
					import net.knarcraft.minigames.util.ParkourArenaStorageHelper;
 | 
				
			||||||
import net.knarcraft.minigames.util.StringSanitizer;
 | 
					import net.knarcraft.minigames.util.StringSanitizer;
 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
import org.jetbrains.annotations.Nullable;
 | 
					import org.jetbrains.annotations.Nullable;
 | 
				
			||||||
@@ -163,7 +163,7 @@ public class ParkourArenaHandler {
 | 
				
			|||||||
        this.arenas.remove(arenaId);
 | 
					        this.arenas.remove(arenaId);
 | 
				
			||||||
        this.arenaNameLookup.remove(arena.getArenaNameSanitized());
 | 
					        this.arenaNameLookup.remove(arena.getArenaNameSanitized());
 | 
				
			||||||
        this.arenaGroups.remove(arenaId);
 | 
					        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. " +
 | 
					            MiniGames.log(Level.WARNING, "Unable to remove parkour arena data file " + arenaId + ".yml. " +
 | 
				
			||||||
                    "You must remove it manually!");
 | 
					                    "You must remove it manually!");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -177,7 +177,7 @@ public class ParkourArenaHandler {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public void saveData(UUID arenaId) {
 | 
					    public void saveData(UUID arenaId) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            ArenaStorageHelper.saveParkourArenaData(this.arenas.get(arenaId).getData());
 | 
					            ParkourArenaStorageHelper.saveParkourArenaData(this.arenas.get(arenaId).getData());
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            MiniGames.log(Level.SEVERE, "Unable to save arena data! Data loss can occur!");
 | 
					            MiniGames.log(Level.SEVERE, "Unable to save arena data! Data loss can occur!");
 | 
				
			||||||
            MiniGames.log(Level.SEVERE, e.getMessage());
 | 
					            MiniGames.log(Level.SEVERE, e.getMessage());
 | 
				
			||||||
@@ -189,7 +189,7 @@ public class ParkourArenaHandler {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public void saveGroups() {
 | 
					    public void saveGroups() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            ArenaStorageHelper.saveParkourArenaGroups(new HashSet<>(this.arenaGroups.values()));
 | 
					            ParkourArenaStorageHelper.saveParkourArenaGroups(new HashSet<>(this.arenaGroups.values()));
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            MiniGames.log(Level.SEVERE, "Unable to save current arena groups! " +
 | 
					            MiniGames.log(Level.SEVERE, "Unable to save current arena groups! " +
 | 
				
			||||||
                    "Data loss can occur!");
 | 
					                    "Data loss can occur!");
 | 
				
			||||||
@@ -209,7 +209,7 @@ public class ParkourArenaHandler {
 | 
				
			|||||||
     * Loads all parkour groups from disk
 | 
					     * Loads all parkour groups from disk
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void loadGroups() {
 | 
					    private void loadGroups() {
 | 
				
			||||||
        Set<ParkourArenaGroup> arenaGroups = ArenaStorageHelper.loadParkourArenaGroups();
 | 
					        Set<ParkourArenaGroup> arenaGroups = ParkourArenaStorageHelper.loadParkourArenaGroups();
 | 
				
			||||||
        Map<UUID, ParkourArenaGroup> arenaGroupMap = new HashMap<>();
 | 
					        Map<UUID, ParkourArenaGroup> arenaGroupMap = new HashMap<>();
 | 
				
			||||||
        for (ParkourArenaGroup arenaGroup : arenaGroups) {
 | 
					        for (ParkourArenaGroup arenaGroup : arenaGroups) {
 | 
				
			||||||
            for (UUID arenaId : arenaGroup.getArenas()) {
 | 
					            for (UUID arenaId : arenaGroup.getArenas()) {
 | 
				
			||||||
@@ -224,7 +224,7 @@ public class ParkourArenaHandler {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public void saveArenas() {
 | 
					    public void saveArenas() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            ArenaStorageHelper.saveParkourArenas(this.arenas);
 | 
					            ParkourArenaStorageHelper.saveParkourArenas(this.arenas);
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            MiniGames.log(Level.SEVERE, "Unable to save current arenas! " +
 | 
					            MiniGames.log(Level.SEVERE, "Unable to save current arenas! " +
 | 
				
			||||||
                    "Data loss can occur!");
 | 
					                    "Data loss can occur!");
 | 
				
			||||||
@@ -236,7 +236,7 @@ public class ParkourArenaHandler {
 | 
				
			|||||||
     * Loads all arenas from disk
 | 
					     * Loads all arenas from disk
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void loadArenas() {
 | 
					    private void loadArenas() {
 | 
				
			||||||
        this.arenas = ArenaStorageHelper.loadParkourArenas();
 | 
					        this.arenas = ParkourArenaStorageHelper.loadParkourArenas();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Save a map from arena name to arena id for improved performance
 | 
					        // Save a map from arena name to arena id for improved performance
 | 
				
			||||||
        this.arenaNameLookup = new HashMap<>();
 | 
					        this.arenaNameLookup = new HashMap<>();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,20 +1,13 @@
 | 
				
			|||||||
package net.knarcraft.minigames.config;
 | 
					package net.knarcraft.minigames.config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.minigames.MiniGames;
 | 
					import net.knarcraft.minigames.util.MaterialHelper;
 | 
				
			||||||
import org.bukkit.Bukkit;
 | 
					 | 
				
			||||||
import org.bukkit.Material;
 | 
					import org.bukkit.Material;
 | 
				
			||||||
import org.bukkit.NamespacedKey;
 | 
					 | 
				
			||||||
import org.bukkit.Tag;
 | 
					 | 
				
			||||||
import org.bukkit.configuration.file.FileConfiguration;
 | 
					import org.bukkit.configuration.file.FileConfiguration;
 | 
				
			||||||
import org.jetbrains.annotations.NotNull;
 | 
					import org.jetbrains.annotations.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.HashSet;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Set;
 | 
					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
 | 
					 * A configuration for a mini-game
 | 
				
			||||||
@@ -51,52 +44,9 @@ public abstract class MiniGameConfiguration {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Loads the materials specified in the block whitelist
 | 
					     * Loads the materials specified in the block whitelist
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected @NotNull Set<Material> loadMaterialList(@NotNull String path) {
 | 
					    public @NotNull Set<Material> loadMaterialList(@NotNull String path) {
 | 
				
			||||||
        Set<Material> parsedMaterials = new HashSet<>();
 | 
					 | 
				
			||||||
        List<?> blockWhitelist = configuration.getList(path, new ArrayList<>());
 | 
					        List<?> blockWhitelist = configuration.getList(path, new ArrayList<>());
 | 
				
			||||||
        for (Object value : blockWhitelist) {
 | 
					        return MaterialHelper.loadMaterialList(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    <p>The set all parsed materials should be added to</p>
 | 
					 | 
				
			||||||
     * @param materialName <p>The material name that might be a material tag</p>
 | 
					 | 
				
			||||||
     * @return <p>True if a tag was found</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected boolean parseMaterialTag(@NotNull Set<Material> 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<Material> 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;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,305 +1,18 @@
 | 
				
			|||||||
package net.knarcraft.minigames.util;
 | 
					package net.knarcraft.minigames.util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import net.knarcraft.minigames.MiniGames;
 | 
					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.NotNull;
 | 
				
			||||||
import org.jetbrains.annotations.Nullable;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.File;
 | 
					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.UUID;
 | 
				
			||||||
import java.util.logging.Level;
 | 
					import java.util.logging.Level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * A helper class for saving and loading arenas
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public final class ArenaStorageHelper {
 | 
					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() {
 | 
					    private ArenaStorageHelper() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Saves the given dropper arena groups
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param arenaGroups <p>The arena groups to save</p>
 | 
					 | 
				
			||||||
     * @throws IOException <p>If unable to write to the file</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static void saveDropperArenaGroups(@NotNull Set<DropperArenaGroup> 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 <p>The loaded arena groups</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static @NotNull Set<DropperArenaGroup> 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<DropperArenaGroup> arenaGroups = new HashSet<>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (String sectionName : groupSection.getKeys(false)) {
 | 
					 | 
				
			||||||
            arenaGroups.add((DropperArenaGroup) groupSection.get(sectionName));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return arenaGroups;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Saves the given arenas
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param arenas <p>The arenas to save</p>
 | 
					 | 
				
			||||||
     * @throws IOException <p>If unable to write to the file</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static void saveDropperArenas(@NotNull Map<UUID, DropperArena> 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 <p>The arenas to save</p>
 | 
					 | 
				
			||||||
     * @throws IOException <p>If unable to write to the file</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static void saveParkourArenas(@NotNull Map<UUID, ParkourArena> 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 <p>The loaded arenas, or null if the arenas configuration section is missing.</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static @NotNull Map<UUID, DropperArena> 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<UUID, DropperArena> 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 <p>The configuration section containing arena data</p>
 | 
					 | 
				
			||||||
     * @return <p>The loaded arena, or null if invalid</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    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<ArenaGameMode, ArenaRecordsRegistry> 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 <p>The arena data to store</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    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 <p>The arena data to store</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    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 <p>The id of the arena to get data for</p>
 | 
					 | 
				
			||||||
     * @return <p>The loaded arena data</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    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 <p>The id of the arena to get data for</p>
 | 
					 | 
				
			||||||
     * @return <p>The loaded arena data</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    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 <p>The id of the arena to remove data for</p>
 | 
					 | 
				
			||||||
     * @return <p>True if the data was successfully removed</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static boolean removeDropperArenaData(@NotNull UUID arenaId) {
 | 
					 | 
				
			||||||
        return getDropperArenaDataFile(arenaId).delete();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Removes data for the arena with the given id
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param arenaId <p>The id of the arena to remove data for</p>
 | 
					 | 
				
			||||||
     * @return <p>True if the data was successfully removed</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    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 <p>The id of the arena to get a data file for</p>
 | 
					 | 
				
			||||||
     * @return <p>The file the arena's data is/should be stored in</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    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 <p>The id of the arena to get a data file for</p>
 | 
					 | 
				
			||||||
     * @return <p>The file the arena's data is/should be stored in</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private static @NotNull File getParkourArenaDataFile(@NotNull UUID arenaId) {
 | 
					 | 
				
			||||||
        return getArenaDataFile(parkourArenaDataFolder, arenaId);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Gets the file used to store the given arena id's data
 | 
					     * Gets the file used to store the given arena id's data
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -307,7 +20,7 @@ public final class ArenaStorageHelper {
 | 
				
			|||||||
     * @param arenaId <p>The id of the arena to get a data file for</p>
 | 
					     * @param arenaId <p>The id of the arena to get a data file for</p>
 | 
				
			||||||
     * @return <p>The file the arena's data is/should be stored in</p>
 | 
					     * @return <p>The file the arena's data is/should be stored in</p>
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    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");
 | 
					        File arenaDataFile = new File(root, arenaId + ".yml");
 | 
				
			||||||
        if (!root.exists() && !root.mkdirs()) {
 | 
					        if (!root.exists() && !root.mkdirs()) {
 | 
				
			||||||
            MiniGames.log(Level.SEVERE, "Unable to create the arena data directories");
 | 
					            MiniGames.log(Level.SEVERE, "Unable to create the arena data directories");
 | 
				
			||||||
@@ -315,20 +28,4 @@ public final class ArenaStorageHelper {
 | 
				
			|||||||
        return arenaDataFile;
 | 
					        return arenaDataFile;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Sanitizes the given horizontal velocity to make sure it doesn't leave its bounds
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param horizontalVelocity <p>The horizontal velocity to sanitize</p>
 | 
					 | 
				
			||||||
     * @return <p>The sanitized horizontal velocity</p>
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private static float sanitizeHorizontalVelocity(float horizontalVelocity) {
 | 
					 | 
				
			||||||
        if (horizontalVelocity < -1) {
 | 
					 | 
				
			||||||
            return -1;
 | 
					 | 
				
			||||||
        } else if (horizontalVelocity > 1) {
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return horizontalVelocity;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 <p>The arena groups to save</p>
 | 
				
			||||||
 | 
					     * @throws IOException <p>If unable to write to the file</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static void saveDropperArenaGroups(@NotNull Set<DropperArenaGroup> 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 <p>The loaded arena groups</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static @NotNull Set<DropperArenaGroup> 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<DropperArenaGroup> arenaGroups = new HashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (String sectionName : groupSection.getKeys(false)) {
 | 
				
			||||||
 | 
					            arenaGroups.add((DropperArenaGroup) groupSection.get(sectionName));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return arenaGroups;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Saves the given arenas
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param arenas <p>The arenas to save</p>
 | 
				
			||||||
 | 
					     * @throws IOException <p>If unable to write to the file</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static void saveDropperArenas(@NotNull Map<UUID, DropperArena> 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 <p>The loaded arenas, or null if the arenas configuration section is missing.</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static @NotNull Map<UUID, DropperArena> 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<UUID, DropperArena> 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 <p>The configuration section containing arena data</p>
 | 
				
			||||||
 | 
					     * @return <p>The loaded arena, or null if invalid</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    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 <p>The id to get parkour data for</p>
 | 
				
			||||||
 | 
					     * @return <p>Empty parkour data</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static @NotNull DropperArenaData getEmptyDropperData(@NotNull UUID arenaId) {
 | 
				
			||||||
 | 
					        Map<ArenaGameMode, ArenaRecordsRegistry> recordRegistries = new HashMap<>();
 | 
				
			||||||
 | 
					        Map<ArenaGameMode, Set<UUID>> 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 <p>The arena data to store</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    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 <p>The id of the arena to get data for</p>
 | 
				
			||||||
 | 
					     * @return <p>The loaded arena data</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    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 <p>The id of the arena to remove data for</p>
 | 
				
			||||||
 | 
					     * @return <p>True if the data was successfully removed</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    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 <p>The id of the arena to get a data file for</p>
 | 
				
			||||||
 | 
					     * @return <p>The file the arena's data is/should be stored in</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    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 <p>The horizontal velocity to sanitize</p>
 | 
				
			||||||
 | 
					     * @return <p>The sanitized horizontal velocity</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static float sanitizeHorizontalVelocity(float horizontalVelocity) {
 | 
				
			||||||
 | 
					        if (horizontalVelocity < -1) {
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        } else if (horizontalVelocity > 1) {
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return horizontalVelocity;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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<Material> loadMaterialList(@NotNull List<?> materials) {
 | 
				
			||||||
 | 
					        Set<Material> 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    <p>The set all parsed materials should be added to</p>
 | 
				
			||||||
 | 
					     * @param materialName <p>The material name that might be a material tag</p>
 | 
				
			||||||
 | 
					     * @return <p>True if a tag was found</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static boolean parseMaterialTag(@NotNull Set<Material> 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<Material> 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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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 <p>The arena groups to save</p>
 | 
				
			||||||
 | 
					     * @throws IOException <p>If unable to write to the file</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static void saveParkourArenaGroups(@NotNull Set<ParkourArenaGroup> 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 <p>The loaded arena groups</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static @NotNull Set<ParkourArenaGroup> 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<ParkourArenaGroup> arenaGroups = new HashSet<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (String sectionName : groupSection.getKeys(false)) {
 | 
				
			||||||
 | 
					            arenaGroups.add((ParkourArenaGroup) groupSection.get(sectionName));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return arenaGroups;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Saves the given arenas
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param arenas <p>The arenas to save</p>
 | 
				
			||||||
 | 
					     * @throws IOException <p>If unable to write to the file</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static void saveParkourArenas(@NotNull Map<UUID, ParkourArena> 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 <p>The loaded arenas, or null if the arenas configuration section is missing.</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static @NotNull Map<UUID, ParkourArena> 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<UUID, ParkourArena> 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 <p>The configuration section containing arena data</p>
 | 
				
			||||||
 | 
					     * @return <p>The loaded arena, or null if invalid</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @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<Location> checkpoints = (List<Location>) 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<String>) killPlaneBlockNames, checkpoints, arenaData, MiniGames.getInstance().getParkourArenaHandler());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets empty parkour data
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param arenaId <p>The id to get parkour data for</p>
 | 
				
			||||||
 | 
					     * @return <p>Empty parkour data</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static @NotNull ParkourArenaData getEmptyParkourData(@NotNull UUID arenaId) {
 | 
				
			||||||
 | 
					        Map<ArenaGameMode, ArenaRecordsRegistry> recordRegistries = new HashMap<>();
 | 
				
			||||||
 | 
					        Map<ArenaGameMode, Set<UUID>> 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 <p>The arena data to store</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    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 <p>The id of the arena to get data for</p>
 | 
				
			||||||
 | 
					     * @return <p>The loaded arena data</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    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 <p>The id of the arena to remove data for</p>
 | 
				
			||||||
 | 
					     * @return <p>True if the data was successfully removed</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    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 <p>The id of the arena to get a data file for</p>
 | 
				
			||||||
 | 
					     * @return <p>The file the arena's data is/should be stored in</p>
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static @NotNull File getParkourArenaDataFile(@NotNull UUID arenaId) {
 | 
				
			||||||
 | 
					        return getArenaDataFile(parkourArenaDataFolder, arenaId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user