Implements #2 and #4

Adds a unique identifier to arenas
Stores frequently updated arena data separately from arena settings
Stores arenas keyed by their id
Prepares for storage of which players have beaten an arena
This commit is contained in:
Kristian Knarvik 2023-03-27 21:43:16 +02:00
parent 9a7d3ca360
commit 3626d997b8
9 changed files with 237 additions and 57 deletions

View File

@ -1,5 +1,6 @@
package net.knarcraft.dropper;
import net.knarcraft.dropper.arena.DropperArenaData;
import net.knarcraft.dropper.arena.DropperArenaHandler;
import net.knarcraft.dropper.arena.DropperArenaPlayerRegistry;
import net.knarcraft.dropper.arena.DropperArenaRecordsRegistry;
@ -84,6 +85,7 @@ public final class Dropper extends JavaPlugin {
ConfigurationSerialization.registerClass(SerializableMaterial.class);
ConfigurationSerialization.registerClass(DropperArenaRecordsRegistry.class);
ConfigurationSerialization.registerClass(SerializableUUID.class);
ConfigurationSerialization.registerClass(DropperArenaData.class);
}
@Override

View File

@ -5,11 +5,19 @@ import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.UUID;
/**
* A representation of one dropper arena
*/
public class DropperArena {
/**
* An unique and persistent identifier for this arena
*/
private final UUID arenaId;
/**
* A name used when listing and storing this arena.
*/
@ -43,21 +51,22 @@ public class DropperArena {
*/
private final @Nullable Integer stage;
/**
* The registry used to save this arena's records
*/
private final @NotNull DropperArenaRecordsRegistry recordsRegistry;
/**
* The material of the block players have to hit to win this dropper arena
*/
private final @NotNull Material winBlockType;
/**
* The arena data for this arena
*/
private final DropperArenaData dropperArenaData;
//TODO: It should be possible to get records in sorted order (smallest to largest)
/**
* Instantiates a new dropper arena
*
* @param arenaId <p>The id of the arena</p>
* @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>
@ -65,11 +74,13 @@ public class DropperArena {
* @param playerHorizontalVelocity <p>The velocity to use for players' horizontal velocity (-1 to 1)</p>
* @param stage <p>The stage number of this stage, or null if not limited to stages</p>
* @param winBlockType <p>The material of the block players have to hit to win this dropper arena</p>
* @param recordsRegistry <p>The registry keeping track of all of this arena's records</p>
* @param dropperArenaData <p>The arena data keeping track of which players have done what in this arena</p>
*/
public DropperArena(@NotNull String arenaName, @NotNull Location spawnLocation, @Nullable Location exitLocation,
double playerVerticalVelocity, float playerHorizontalVelocity, @Nullable Integer stage,
@NotNull Material winBlockType, @NotNull DropperArenaRecordsRegistry recordsRegistry) {
public DropperArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
@Nullable Location exitLocation, double playerVerticalVelocity, float playerHorizontalVelocity,
@Nullable Integer stage, @NotNull Material winBlockType,
@NotNull DropperArenaData dropperArenaData) {
this.arenaId = arenaId;
this.arenaName = arenaName;
this.spawnLocation = spawnLocation;
this.exitLocation = exitLocation;
@ -77,7 +88,7 @@ public class DropperArena {
this.playerHorizontalVelocity = playerHorizontalVelocity;
this.stage = stage;
this.winBlockType = winBlockType;
this.recordsRegistry = recordsRegistry;
this.dropperArenaData = dropperArenaData;
}
/**
@ -90,29 +101,40 @@ public class DropperArena {
* @param spawnLocation <p>The location players spawn in when entering the arena</p>
*/
public DropperArena(@NotNull String arenaName, @NotNull Location spawnLocation) {
this.arenaId = UUID.randomUUID();
this.arenaName = arenaName;
this.spawnLocation = spawnLocation;
this.exitLocation = null;
this.playerVerticalVelocity = 1;
this.playerHorizontalVelocity = 1;
this.stage = null;
this.recordsRegistry = new DropperArenaRecordsRegistry();
this.dropperArenaData = new DropperArenaData(this.arenaId, new DropperArenaRecordsRegistry(this.arenaId),
new HashSet<>());
this.winBlockType = Material.WATER;
}
/**
* Gets the registry keeping track of this arena's records
* Gets this arena's data
*
* @return <p>This arena's record registry</p>
* @return <p>This arena's data</p>
*/
public @NotNull DropperArenaRecordsRegistry getRecordsRegistry() {
return this.recordsRegistry;
public @NotNull DropperArenaData getData() {
return this.dropperArenaData;
}
/**
* Gets the id of this arena
*
* @return <p>This arena's identifier</p>
*/
public @NotNull UUID getArenaId() {
return this.arenaId;
}
/**
* Gets the name of this arena
*
* @return <p>The name of this arena.</p>
* @return <p>The name of this arena</p>
*/
public @NotNull String getArenaName() {
return this.arenaName;

View File

@ -0,0 +1,81 @@
package net.knarcraft.dropper.arena;
import net.knarcraft.dropper.container.SerializableUUID;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
* Data stored for an arena
*
* @param arenaId <p>The id of the arena this data belongs to</p>
* @param recordsRegistry <p>The records belonging to the arena</p>
* @param playersCompleted <p>A list of all player that have completed this arena</p>
*/
public record DropperArenaData(@NotNull UUID arenaId, @NotNull DropperArenaRecordsRegistry recordsRegistry,
@NotNull Set<SerializableUUID> playersCompleted) implements ConfigurationSerializable {
/**
* Instantiates a new dropper arena data object
*
* @param arenaId <p>The id of the arena this data belongs to</p>
* @param recordsRegistry <p>The registry of this arena's records</p>
* @param playersCompleted <p>The set of ids for players that have cleared this data's arena</p>
*/
public DropperArenaData(@NotNull UUID arenaId, @NotNull DropperArenaRecordsRegistry recordsRegistry,
@NotNull Set<SerializableUUID> playersCompleted) {
this.arenaId = arenaId;
this.recordsRegistry = recordsRegistry;
this.playersCompleted = new HashSet<>(playersCompleted);
}
/**
* Gets whether the given player has cleared this arena
*
* @param player <p>The player to check</p>
* @return <p>True if the player has cleared the arena this data belongs to</p>
*/
public boolean hasCompleted(@NotNull Player player) {
return this.playersCompleted.contains(new SerializableUUID(player.getUniqueId()));
}
/**
* Registers the given player as having completed this arena
*
* @param player <p>The player that completed this data's arena</p>
*/
public void addCompleted(@NotNull Player player) {
this.playersCompleted.add(new SerializableUUID(player.getUniqueId()));
}
@NotNull
@Override
public Map<String, Object> serialize() {
Map<String, Object> data = new HashMap<>();
data.put("arenaId", new SerializableUUID(this.arenaId));
data.put("recordsRegistry", this.recordsRegistry);
data.put("playersCompleted", this.playersCompleted);
return data;
}
/**
* Deserializes a dropper arena data from the given data
*
* @param data <p>The data to deserialize</p>
* @return <p>The deserialized dropper arena data</p>
*/
@SuppressWarnings({"unused", "unchecked"})
public static @NotNull DropperArenaData deserialize(@NotNull Map<String, Object> data) {
SerializableUUID serializableUUID = (SerializableUUID) data.get("arenaId");
DropperArenaRecordsRegistry recordsRegistry = (DropperArenaRecordsRegistry) data.get("recordsRegistry");
Set<SerializableUUID> playersCompleted = (Set<SerializableUUID>) data.get("playersCompleted");
return new DropperArenaData(serializableUUID.uuid(), recordsRegistry, playersCompleted);
}
}

View File

@ -6,12 +6,10 @@ import org.bukkit.entity.Player;
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.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
/**
@ -19,9 +17,7 @@ import java.util.logging.Level;
*/
public class DropperArenaHandler {
private static final File arenaFile = new File(Dropper.getInstance().getDataFolder(), "arenas.yml");
private List<DropperArena> arenas = new ArrayList<>();
private Map<UUID, DropperArena> arenas = new HashMap<>();
private final Map<Player, Integer> stagesCleared = new HashMap<>();
/**
@ -47,7 +43,7 @@ public class DropperArenaHandler {
* @param arena <p>The arena to add</p>
*/
public void addArena(@NotNull DropperArena arena) {
this.arenas.add(arena);
this.arenas.put(arena.getArenaId(), arena);
this.saveArenas();
}
@ -59,7 +55,7 @@ public class DropperArenaHandler {
*/
public @Nullable DropperArena getArena(@NotNull String arenaName) {
arenaName = ArenaStorageHelper.sanitizeArenaName(arenaName);
for (DropperArena arena : arenas) {
for (DropperArena arena : arenas.values()) {
if (ArenaStorageHelper.sanitizeArenaName(arena.getArenaName()).equals(arenaName)) {
return arena;
}
@ -72,8 +68,8 @@ public class DropperArenaHandler {
*
* @return <p>All known arenas</p>
*/
public @NotNull List<DropperArena> getArenas() {
return new ArrayList<>(this.arenas);
public @NotNull Map<UUID, DropperArena> getArenas() {
return new HashMap<>(this.arenas);
}
/**
@ -83,19 +79,34 @@ public class DropperArenaHandler {
*/
public void removeArena(@NotNull DropperArena arena) {
Dropper.getInstance().getPlayerRegistry().removeForArena(arena);
this.arenas.remove(arena);
this.arenas.remove(arena.getArenaId());
this.saveArenas();
}
/**
* Stores the data for the given arena
*
* @param arenaId <p>The id of the arena whose data should be saved</p>
*/
public void saveData(UUID arenaId) {
try {
ArenaStorageHelper.saveArenaData(this.arenas.get(arenaId).getData());
} catch (IOException e) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to save arena data! Data loss can occur!");
Dropper.getInstance().getLogger().log(Level.SEVERE, e.getMessage());
}
}
/**
* Saves all current arenas to disk
*/
public void saveArenas() {
try {
ArenaStorageHelper.saveArenas(this.arenas, arenaFile);
ArenaStorageHelper.saveArenas(this.arenas);
} catch (IOException e) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to save current arenas! " +
"Data loss can occur!");
Dropper.getInstance().getLogger().log(Level.SEVERE, e.getMessage());
}
}
@ -103,7 +114,7 @@ public class DropperArenaHandler {
* Loads all arenas from disk
*/
public void loadArenas() {
this.arenas = ArenaStorageHelper.loadArenas(arenaFile);
this.arenas = ArenaStorageHelper.loadArenas();
}
}

View File

@ -16,13 +16,15 @@ import java.util.stream.Stream;
*/
public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
private final UUID arenaId;
private final Map<SerializableUUID, Integer> leastDeaths;
private final Map<SerializableUUID, Long> shortestTimeMilliSeconds;
/**
* Instantiates a new empty records registry
*/
public DropperArenaRecordsRegistry() {
public DropperArenaRecordsRegistry(@NotNull UUID arenaId) {
this.arenaId = arenaId;
this.leastDeaths = new HashMap<>();
this.shortestTimeMilliSeconds = new HashMap<>();
}
@ -33,8 +35,9 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
* @param leastDeaths <p>The existing least death records to use</p>
* @param shortestTimeMilliSeconds <p>The existing leash time records to use</p>
*/
public DropperArenaRecordsRegistry(@NotNull Map<SerializableUUID, Integer> leastDeaths,
public DropperArenaRecordsRegistry(@NotNull UUID arenaId, @NotNull Map<SerializableUUID, Integer> leastDeaths,
@NotNull Map<SerializableUUID, Long> shortestTimeMilliSeconds) {
this.arenaId = arenaId;
this.leastDeaths = new HashMap<>(leastDeaths);
this.shortestTimeMilliSeconds = new HashMap<>(shortestTimeMilliSeconds);
}
@ -70,16 +73,20 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
SerializableUUID serializableUUID = new SerializableUUID(playerId);
if (records.allMatch((entry) -> deaths < entry.getValue())) {
//If the given value is less than all other values, that's a world record!
// If the given value is less than all other values, that's a world record!
result = RecordResult.WORLD_RECORD;
leastDeaths.put(serializableUUID, deaths);
save();
} else if (leastDeaths.containsKey(serializableUUID) && deaths < leastDeaths.get(serializableUUID)) {
//If the given value is less than the player's previous value, that's a personal best!
// If the given value is less than the player's previous value, that's a personal best!
result = RecordResult.PERSONAL_BEST;
leastDeaths.put(serializableUUID, deaths);
save();
} else {
// Make sure to save the record if this is the user's first attempt
if (!leastDeaths.containsKey(serializableUUID)) {
save();
}
result = RecordResult.NONE;
}
@ -110,6 +117,10 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
shortestTimeMilliSeconds.put(serializableUUID, milliseconds);
save();
} else {
// Make sure to save the record if this is the user's first attempt
if (!shortestTimeMilliSeconds.containsKey(serializableUUID)) {
save();
}
result = RecordResult.NONE;
}
@ -120,13 +131,14 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
* Saves changed records
*/
private void save() {
Dropper.getInstance().getArenaHandler().saveArenas();
Dropper.getInstance().getArenaHandler().saveData(this.arenaId);
}
@NotNull
@Override
public Map<String, Object> serialize() {
Map<String, Object> data = new HashMap<>();
data.put("arenaId", new SerializableUUID(this.arenaId));
data.put("leastDeaths", this.leastDeaths);
data.put("shortestTime", this.shortestTimeMilliSeconds);
return data;
@ -140,12 +152,13 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
*/
@SuppressWarnings({"unused", "unchecked"})
public static DropperArenaRecordsRegistry deserialize(Map<String, Object> data) {
UUID arenaId = ((SerializableUUID) data.get("arenaId")).uuid();
Map<SerializableUUID, Integer> leastDeathsData =
(Map<SerializableUUID, Integer>) data.getOrDefault("leastDeaths", new HashMap<>());
Map<SerializableUUID, Long> shortestTimeMillisecondsData =
(Map<SerializableUUID, Long>) data.getOrDefault("shortestTime", new HashMap<>());
return new DropperArenaRecordsRegistry(leastDeathsData, shortestTimeMillisecondsData);
return new DropperArenaRecordsRegistry(arenaId, leastDeathsData, shortestTimeMillisecondsData);
}
}

View File

@ -108,7 +108,7 @@ public class DropperArenaSession {
* Registers the player's record if necessary, and prints record information to the player
*/
private void registerRecord() {
DropperArenaRecordsRegistry recordsRegistry = this.arena.getRecordsRegistry();
DropperArenaRecordsRegistry recordsRegistry = this.arena.getData().recordsRegistry();
RecordResult recordResult = switch (this.gameMode) {
case LEAST_TIME -> recordsRegistry.registerTimeRecord(this.player.getUniqueId(),
System.currentTimeMillis() - this.startTime);

View File

@ -7,6 +7,11 @@ import org.jetbrains.annotations.NotNull;
*/
public enum ArenaStorageKey {
/**
* The key for an arena's id
*/
ID("arenaId"),
/**
* The key for an arena's name
*/
@ -43,9 +48,9 @@ public enum ArenaStorageKey {
WIN_BLOCK_TYPE("winBlockType"),
/**
* The hey for this arena's records
* The hey for this arena's data
*/
RECORDS("records"),
DATA("arenaData"),
;
private final @NotNull String key;

View File

@ -2,8 +2,10 @@ package net.knarcraft.dropper.util;
import net.knarcraft.dropper.Dropper;
import net.knarcraft.dropper.arena.DropperArena;
import net.knarcraft.dropper.arena.DropperArenaData;
import net.knarcraft.dropper.arena.DropperArenaRecordsRegistry;
import net.knarcraft.dropper.container.SerializableMaterial;
import net.knarcraft.dropper.container.SerializableUUID;
import net.knarcraft.dropper.property.ArenaStorageKey;
import org.bukkit.Location;
import org.bukkit.Material;
@ -14,8 +16,10 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
/**
@ -24,6 +28,8 @@ import java.util.logging.Level;
public final class ArenaStorageHelper {
private final static String arenasConfigurationSection = "arenas";
private static final File arenaFile = new File(Dropper.getInstance().getDataFolder(), "arenas.yml");
private static final File arenaDataFolder = new File(Dropper.getInstance().getDataFolder(), "arena_data");
private ArenaStorageHelper() {
@ -32,18 +38,18 @@ public final class ArenaStorageHelper {
/**
* 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>
* @param arenas <p>The arenas to save</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 {
public static void saveArenas(@NotNull Map<UUID, DropperArena> arenas) throws IOException {
YamlConfiguration configuration = new YamlConfiguration();
ConfigurationSection arenaSection = configuration.createSection(arenasConfigurationSection);
for (DropperArena arena : arenas) {
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(sanitizeArenaName(
arena.getArenaName()));
configSection.set(ArenaStorageKey.ID.getKey(), new SerializableUUID(arena.getArenaId()));
configSection.set(ArenaStorageKey.NAME.getKey(), arena.getArenaName());
configSection.set(ArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation());
configSection.set(ArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation());
@ -51,7 +57,7 @@ public final class ArenaStorageHelper {
configSection.set(ArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey(), arena.getPlayerHorizontalVelocity());
configSection.set(ArenaStorageKey.STAGE.getKey(), arena.getStage());
configSection.set(ArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
configSection.set(ArenaStorageKey.RECORDS.getKey(), arena.getRecordsRegistry());
saveArenaData(arena.getData());
}
configuration.save(arenaFile);
}
@ -59,18 +65,17 @@ public final class ArenaStorageHelper {
/**
* 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 @NotNull List<DropperArena> loadArenas(@NotNull File arenaFile) {
public static @NotNull Map<UUID, DropperArena> loadArenas() {
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 new ArrayList<>();
return new HashMap<>();
}
List<DropperArena> loadedArenas = new ArrayList<>();
Map<UUID, DropperArena> loadedArenas = new HashMap<>();
for (String sectionName : arenaSection.getKeys(false)) {
ConfigurationSection configurationSection = arenaSection.getConfigurationSection(sectionName);
@ -81,7 +86,7 @@ public final class ArenaStorageHelper {
DropperArena arena = loadArena(configurationSection);
if (arena != null) {
loadedArenas.add(arena);
loadedArenas.put(arena.getArenaId(), arena);
}
}
@ -95,6 +100,8 @@ public final class ArenaStorageHelper {
* @return <p>The loaded arena, or null if invalid</p>
*/
private static @Nullable DropperArena loadArena(@NotNull ConfigurationSection configurationSection) {
UUID arenaId = ((SerializableUUID) configurationSection.get(ArenaStorageKey.ID.getKey(),
new SerializableUUID(UUID.randomUUID()))).uuid();
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());
@ -104,8 +111,6 @@ public final class ArenaStorageHelper {
Integer stage = (Integer) configurationSection.get(ArenaStorageKey.STAGE.getKey());
SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get(
ArenaStorageKey.WIN_BLOCK_TYPE.getKey());
DropperArenaRecordsRegistry recordsRegistry = (DropperArenaRecordsRegistry) configurationSection.get(
ArenaStorageKey.RECORDS.getKey());
if (arenaName == null || spawnLocation == null) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Could not load the arena at configuration " +
@ -115,12 +120,15 @@ public final class ArenaStorageHelper {
if (winBlockType == null) {
winBlockType = new SerializableMaterial(Material.WATER);
}
if (recordsRegistry == null) {
recordsRegistry = new DropperArenaRecordsRegistry();
DropperArenaData arenaData = loadArenaData(arenaId);
if (arenaData == null) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to load arena data for " + arenaId);
arenaData = new DropperArenaData(arenaId, new DropperArenaRecordsRegistry(arenaId), new HashSet<>());
}
return new DropperArena(arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity, stage,
winBlockType.material(), recordsRegistry);
return new DropperArena(arenaId, arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity,
stage, winBlockType.material(), arenaData);
}
/**
@ -133,6 +141,44 @@ public final class ArenaStorageHelper {
return arenaName.toLowerCase().trim().replaceAll(" ", "_");
}
/**
* Stores the given arena data to a file
*
* @param arenaData <p>The arena data to store</p>
*/
public static void saveArenaData(@NotNull DropperArenaData arenaData) throws IOException {
YamlConfiguration configuration = new YamlConfiguration();
configuration.set(ArenaStorageKey.DATA.getKey(), arenaData);
configuration.save(getArenaDataFile(arenaData.arenaId()));
}
/**
* 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 loadArenaData(@NotNull UUID arenaId) {
File arenaDataFile = getArenaDataFile(arenaId);
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile);
return (DropperArenaData) configuration.get(ArenaStorageKey.DATA.getKey());
}
/**
* 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 getArenaDataFile(@NotNull UUID arenaId) {
File arenaDataFile = new File(arenaDataFolder, arenaId + ".yml");
if (!arenaDataFolder.exists() && !arenaDataFolder.mkdirs()) {
Dropper.getInstance().getLogger().log(Level.SEVERE, "Unable to create the arena data directories");
}
return arenaDataFile;
}
/**
* Sanitizes the given horizontal velocity to make sure it doesn't leave its bounds
*

View File

@ -23,7 +23,7 @@ public final class TabCompleteHelper {
*/
public static @NotNull List<String> getArenas() {
List<String> arenaNames = new ArrayList<>();
for (DropperArena dropperArena : Dropper.getInstance().getArenaHandler().getArenas()) {
for (DropperArena dropperArena : Dropper.getInstance().getArenaHandler().getArenas().values()) {
arenaNames.add(dropperArena.getArenaName());
}
return arenaNames;