Adds code for saving and loading arenas

This commit is contained in:
Kristian Knarvik 2023-03-22 10:23:04 +01:00
parent 0a8669263a
commit bcde657fdd
5 changed files with 287 additions and 6 deletions

View File

@ -5,9 +5,22 @@ import org.bukkit.plugin.java.JavaPlugin;
@SuppressWarnings("unused")
public final class Dropper extends JavaPlugin {
private static Dropper instance;
/**
* Gets an instance of this plugin
*
* @return <p>An instance of this plugin, or null if not initialized yet.</p>
*/
public static Dropper getInstance() {
return instance;
}
@Override
public void onEnable() {
// Plugin startup logic
instance = this;
//TODO: Keep track of whether players are in a dropper arena, and which arena they are in
//TODO: Make an event listener that kicks players from an arena if they take damage (EntityDamageEvent).
// Remember to cancel the event so they don't die.

View File

@ -1,34 +1,124 @@
package net.knarcraft.dropper.arena;
import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class DropperArena {
/**
* A name used when listing this arena. Only used for differentiation.
* A name used when listing and storing this arena.
*/
private String arenaName;
private final String arenaName;
/**
* The location players are teleported to when joining this arena.
*/
private Location spawnLocation;
private final Location spawnLocation;
/**
* The location players will be sent to when they win or lose the arena. If not set, their entry location should be
* used instead.
*/
private Location exitLocation;
private final Location exitLocation;
/**
* The velocity in the y-direction to apply to all players in this arena.
*/
private double playerVelocity;
private final double playerVelocity;
/**
* The stage number of this arena. If not null, the previous stage number must be cleared before access.
*/
private Integer stage;
private final Integer stage;
/**
* Instantiates a new dropper arena
*
* @param arenaName <p>The name of 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 playerVelocity <p>The velocity multiplier to use for players' velocity</p>
* @param stage <p>The stage number of this stage, or null if not limited to stages</p>
*/
public DropperArena(@NotNull String arenaName, @NotNull Location spawnLocation, @Nullable Location exitLocation,
double playerVelocity, @Nullable Integer stage) {
this.arenaName = arenaName;
this.spawnLocation = spawnLocation;
this.exitLocation = exitLocation;
this.playerVelocity = playerVelocity;
this.stage = stage;
}
/**
* Instantiates a new dropper arena
*
* <p>Note that this minimal constructor can be used to quickly create a new dropper arena at the player's given
* location, simply by them giving an arena name.</p>
*
* @param arenaName <p>The name of the arena</p>
* @param spawnLocation <p>The location players spawn in when entering the arena</p>
*/
public DropperArena(@NotNull String arenaName, @NotNull Location spawnLocation) {
this.arenaName = arenaName;
this.spawnLocation = spawnLocation;
this.exitLocation = null;
this.playerVelocity = 1;
this.stage = null;
}
/**
* Gets the name of this arena
*
* @return <p>The name of this arena.</p>
*/
public @NotNull String getArenaName() {
return this.arenaName;
}
/**
* Gets this arena's spawn location
*
* <p>The spawn location is the location every player starts from when entering the dropper.</p>
*
* @return <p>This arena's spawn location.</p>
*/
public @NotNull Location getSpawnLocation() {
return this.spawnLocation;
}
/**
* Gets this arena's exit location
*
* @return <p>This arena's exit location, or null if no such location is set.</p>
*/
public @Nullable Location getExitLocation() {
return this.exitLocation;
}
/**
* Gets the velocity for players in this arena
*
* <p>The velocity is the multiplier used to define players' dropping speed in this dropper arena. 1.0 is the normal
* falling speed. 0.5 is half speed. 2 is double speed etc.</p>
*
* @return <p>Players' velocity in this arena</p>
*/
public double getPlayerVelocity() {
return this.playerVelocity;
}
/**
* Gets the stage this arena belongs to
*
* <p>It's assumed that arena stages go from 1,2,3,4,... and upwards. If the stage number is set, this arena can
* only be played if all previous stages have been beaten. If not set, however, this arena can be used freely.</p>
*
* @return <p>This arena's stage number</p>
*/
public @Nullable Integer getStage() {
return this.stage;
}
//TODO: Add the appropriate getters/setters and other methods

View File

@ -1,8 +1,40 @@
package net.knarcraft.dropper.arena;
import net.knarcraft.dropper.Dropper;
import net.knarcraft.dropper.util.ArenaStorageHelper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
public class DropperArenaHandler {
List<DropperArena> arenas = new ArrayList<>();
private static final File arenaFile = new File(Dropper.getInstance().getDataFolder(), "arenas.yml");
//TODO: Use this class to keep track of all created arenas. Saving and loading arenas is this class's responsibility
//TODO: Keep track of which players are in which arenas (should possibly be its own class, depending on complexity)
/**
* Saves all current arenas to disk
*/
private void saveArenas() {
try {
ArenaStorageHelper.saveArenas(this.arenas, arenaFile);
} catch (IOException e) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to save current arenas! " +
"Data loss can occur!");
}
}
/**
* Loads all arenas from disk
*/
private void loadArenas() {
this.arenas = ArenaStorageHelper.loadArenas(arenaFile);
}
}

View File

@ -0,0 +1,35 @@
package net.knarcraft.dropper.property;
/**
* A representation of each key used for storing arena data
*/
public enum ArenaStorageKey {
NAME("arenaName"),
SPAWN_LOCATION("arenaSpawnLocation"),
EXIT_LOCATION("arenaExitLocation"),
PLAYER_VELOCITY("arenaPlayerVelocity"),
STAGE("arenaStage"),
;
private final String key;
/**
* Instantiates a new arena storage key
*
* @param key <p>The string path of the configuration key this value represents.</p>
*/
ArenaStorageKey(String key) {
this.key = key;
}
/**
* Gets the configuration key this enum represents
*
* @return <p>The string key representation.</p>
*/
public String getKey() {
return this.key;
}
}

View File

@ -0,0 +1,111 @@
package net.knarcraft.dropper.util;
import net.knarcraft.dropper.Dropper;
import net.knarcraft.dropper.arena.DropperArena;
import net.knarcraft.dropper.property.ArenaStorageKey;
import org.bukkit.Location;
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.List;
import java.util.logging.Level;
/**
* A helper class for saving and loading arenas
*/
public final class ArenaStorageHelper {
private final static String arenasConfigurationSection = "arenas";
/**
* Saves the given arenas to the given file
*
* @param arenas <p>The arenas to save</p>
* @param arenaFile <p>The file to save the arenas to</p>
* @throws IOException <p>If unable to write to the file</p>
*/
public static void saveArenas(@NotNull List<DropperArena> arenas, @NotNull File arenaFile) throws IOException {
YamlConfiguration configuration = new YamlConfiguration();
ConfigurationSection arenaSection = configuration.createSection(arenasConfigurationSection);
for (DropperArena arena : arenas) {
//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(sanitizeArenaName(
arena.getArenaName()));
configSection.set(ArenaStorageKey.NAME.getKey(), arena.getArenaName());
configSection.set(ArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation());
configSection.set(ArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation());
configSection.set(ArenaStorageKey.PLAYER_VELOCITY.getKey(), arena.getPlayerVelocity());
configSection.set(ArenaStorageKey.STAGE.getKey(), arena.getStage());
}
configuration.save(arenaFile);
}
/**
* Loads all arenas from the given file
*
* @param arenaFile <p>The file used to store the arenas</p>
* @return <p>The loaded arenas, or null if the arenas configuration section is missing.</p>
*/
public static @Nullable List<DropperArena> loadArenas(@NotNull File arenaFile) {
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaFile);
ConfigurationSection arenaSection = configuration.getConfigurationSection(arenasConfigurationSection);
//If no such section exists, it must be the case that there is no data to load
if (arenaSection == null) {
return null;
}
List<DropperArena> loadedArenas = new ArrayList<>();
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 = loadArena(configurationSection);
if (arena != null) {
loadedArenas.add(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 loadArena(ConfigurationSection configurationSection) {
String arenaName = configurationSection.getString(ArenaStorageKey.NAME.getKey());
Location spawnLocation = (Location) configurationSection.get(ArenaStorageKey.SPAWN_LOCATION.getKey());
Location exitLocation = (Location) configurationSection.get(ArenaStorageKey.EXIT_LOCATION.getKey());
double playerVelocity = configurationSection.getDouble(ArenaStorageKey.PLAYER_VELOCITY.getKey());
Integer stage = (Integer) configurationSection.get(ArenaStorageKey.STAGE.getKey());
if (arenaName == null || spawnLocation == null) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Could not load the arena at configuration " +
"section " + configurationSection.getName() + ". Please check the arenas storage file for issues.");
return null;
}
return new DropperArena(arenaName, spawnLocation, exitLocation, playerVelocity, stage);
}
/**
* Sanitizes an arena name for usage as a YAML key
*
* @param arenaName <p>The arena name to sanitize</p>
* @return <p>The sanitized arena name</p>
*/
private static String sanitizeArenaName(String arenaName) {
return arenaName.toLowerCase().trim().replaceAll(" ", "_");
}
}