mirror of
https://github.com/SunNetservers/MiniGames.git
synced 2024-12-05 00:43:15 +01:00
Implements persistent storage of records
This commit is contained in:
parent
49eb0ac82c
commit
592f53ec9e
@ -2,6 +2,7 @@ package net.knarcraft.dropper;
|
||||
|
||||
import net.knarcraft.dropper.arena.DropperArenaHandler;
|
||||
import net.knarcraft.dropper.arena.DropperArenaPlayerRegistry;
|
||||
import net.knarcraft.dropper.arena.DropperArenaRecordsRegistry;
|
||||
import net.knarcraft.dropper.command.CreateArenaCommand;
|
||||
import net.knarcraft.dropper.command.EditArenaCommand;
|
||||
import net.knarcraft.dropper.command.EditArenaTabCompleter;
|
||||
@ -11,12 +12,15 @@ import net.knarcraft.dropper.command.LeaveArenaCommand;
|
||||
import net.knarcraft.dropper.command.ListArenaCommand;
|
||||
import net.knarcraft.dropper.command.RemoveArenaCommand;
|
||||
import net.knarcraft.dropper.command.RemoveArenaTabCompleter;
|
||||
import net.knarcraft.dropper.container.SerializableMaterial;
|
||||
import net.knarcraft.dropper.container.SerializableUUID;
|
||||
import net.knarcraft.dropper.listener.DamageListener;
|
||||
import net.knarcraft.dropper.listener.MoveListener;
|
||||
import net.knarcraft.dropper.listener.PlayerLeaveListener;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -61,6 +65,15 @@ public final class Dropper extends JavaPlugin {
|
||||
return this.playerRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
super.onLoad();
|
||||
// Register serialization classes
|
||||
ConfigurationSerialization.registerClass(SerializableMaterial.class);
|
||||
ConfigurationSerialization.registerClass(DropperArenaRecordsRegistry.class);
|
||||
ConfigurationSerialization.registerClass(SerializableUUID.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Plugin startup logic
|
||||
|
@ -1,20 +1,23 @@
|
||||
package net.knarcraft.dropper.arena;
|
||||
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.container.SerializableUUID;
|
||||
import net.knarcraft.dropper.property.RecordResult;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A registry keeping track of all records
|
||||
*/
|
||||
public class DropperArenaRecordsRegistry {
|
||||
public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
|
||||
|
||||
private final Map<Player, Integer> leastDeaths;
|
||||
private final Map<Player, Long> shortestTimeMilliSeconds;
|
||||
private final Map<SerializableUUID, Integer> leastDeaths;
|
||||
private final Map<SerializableUUID, Long> shortestTimeMilliSeconds;
|
||||
|
||||
/**
|
||||
* Instantiates a new empty records registry
|
||||
@ -30,8 +33,8 @@ public class DropperArenaRecordsRegistry {
|
||||
* @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<Player, Integer> leastDeaths,
|
||||
@NotNull Map<Player, Long> shortestTimeMilliSeconds) {
|
||||
public DropperArenaRecordsRegistry(@NotNull Map<SerializableUUID, Integer> leastDeaths,
|
||||
@NotNull Map<SerializableUUID, Long> shortestTimeMilliSeconds) {
|
||||
this.leastDeaths = new HashMap<>(leastDeaths);
|
||||
this.shortestTimeMilliSeconds = new HashMap<>(shortestTimeMilliSeconds);
|
||||
}
|
||||
@ -41,7 +44,7 @@ public class DropperArenaRecordsRegistry {
|
||||
*
|
||||
* @return <p>Existing death records</p>
|
||||
*/
|
||||
public Map<Player, Integer> getLeastDeathsRecords() {
|
||||
public Map<SerializableUUID, Integer> getLeastDeathsRecords() {
|
||||
return new HashMap<>(this.leastDeaths);
|
||||
}
|
||||
|
||||
@ -50,29 +53,32 @@ public class DropperArenaRecordsRegistry {
|
||||
*
|
||||
* @return <p>Existing time records</p>
|
||||
*/
|
||||
public Map<Player, Long> getShortestTimeMilliSecondsRecords() {
|
||||
public Map<SerializableUUID, Long> getShortestTimeMilliSecondsRecords() {
|
||||
return new HashMap<>(this.shortestTimeMilliSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new deaths-record
|
||||
*
|
||||
* @param player <p>The player that performed the records</p>
|
||||
* @param deaths <p>The number of deaths suffered before the player finished the arena</p>
|
||||
* @param playerId <p>The id of the player that performed the records</p>
|
||||
* @param deaths <p>The number of deaths suffered before the player finished the arena</p>
|
||||
* @return <p>The result explaining what type of record was achieved</p>
|
||||
*/
|
||||
public @NotNull RecordResult registerDeathRecord(@NotNull Player player, int deaths) {
|
||||
public @NotNull RecordResult registerDeathRecord(@NotNull UUID playerId, int deaths) {
|
||||
RecordResult result;
|
||||
Stream<Map.Entry<Player, Integer>> records = leastDeaths.entrySet().stream();
|
||||
Stream<Map.Entry<SerializableUUID, Integer>> records = leastDeaths.entrySet().stream();
|
||||
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!
|
||||
result = RecordResult.WORLD_RECORD;
|
||||
leastDeaths.put(player, deaths);
|
||||
} else if (leastDeaths.containsKey(player) && deaths < leastDeaths.get(player)) {
|
||||
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!
|
||||
result = RecordResult.PERSONAL_BEST;
|
||||
leastDeaths.put(player, deaths);
|
||||
leastDeaths.put(serializableUUID, deaths);
|
||||
save();
|
||||
} else {
|
||||
result = RecordResult.NONE;
|
||||
}
|
||||
@ -83,22 +89,26 @@ public class DropperArenaRecordsRegistry {
|
||||
/**
|
||||
* Registers a new time-record
|
||||
*
|
||||
* @param player <p>The player that performed the records</p>
|
||||
* @param playerId <p>The id of the player that performed the records</p>
|
||||
* @param milliseconds <p>The number of milliseconds it took the player to finish the dropper arena</p>
|
||||
* @return <p>The result explaining what type of record was achieved</p>
|
||||
*/
|
||||
public @NotNull RecordResult registerTimeRecord(@NotNull Player player, long milliseconds) {
|
||||
public @NotNull RecordResult registerTimeRecord(@NotNull UUID playerId, long milliseconds) {
|
||||
RecordResult result;
|
||||
Stream<Map.Entry<Player, Long>> records = shortestTimeMilliSeconds.entrySet().stream();
|
||||
Stream<Map.Entry<SerializableUUID, Long>> records = shortestTimeMilliSeconds.entrySet().stream();
|
||||
SerializableUUID serializableUUID = new SerializableUUID(playerId);
|
||||
|
||||
if (records.allMatch((entry) -> milliseconds < entry.getValue())) {
|
||||
//If the given value is less than all other values, that's a world record!
|
||||
result = RecordResult.WORLD_RECORD;
|
||||
shortestTimeMilliSeconds.put(player, milliseconds);
|
||||
} else if (shortestTimeMilliSeconds.containsKey(player) && milliseconds < shortestTimeMilliSeconds.get(player)) {
|
||||
shortestTimeMilliSeconds.put(serializableUUID, milliseconds);
|
||||
save();
|
||||
} else if (shortestTimeMilliSeconds.containsKey(serializableUUID) &&
|
||||
milliseconds < shortestTimeMilliSeconds.get(serializableUUID)) {
|
||||
//If the given value is less than the player's previous value, that's a personal best!
|
||||
result = RecordResult.PERSONAL_BEST;
|
||||
shortestTimeMilliSeconds.put(player, milliseconds);
|
||||
shortestTimeMilliSeconds.put(serializableUUID, milliseconds);
|
||||
save();
|
||||
} else {
|
||||
result = RecordResult.NONE;
|
||||
}
|
||||
@ -106,4 +116,36 @@ public class DropperArenaRecordsRegistry {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves changed records
|
||||
*/
|
||||
private void save() {
|
||||
Dropper.getInstance().getArenaHandler().saveArenas();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("leastDeaths", this.leastDeaths);
|
||||
data.put("shortestTime", this.shortestTimeMilliSeconds);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the given data
|
||||
*
|
||||
* @param data <p>The data to deserialize</p>
|
||||
* @return <p>The deserialized records registry</p>
|
||||
*/
|
||||
@SuppressWarnings({"unused", "unchecked"})
|
||||
public static DropperArenaRecordsRegistry deserialize(Map<String, Object> data) {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -105,9 +105,9 @@ public class DropperArenaSession {
|
||||
private void registerRecord() {
|
||||
DropperArenaRecordsRegistry recordsRegistry = this.arena.getRecordsRegistry();
|
||||
RecordResult recordResult = switch (this.gameMode) {
|
||||
case LEAST_TIME -> recordsRegistry.registerTimeRecord(this.player,
|
||||
case LEAST_TIME -> recordsRegistry.registerTimeRecord(this.player.getUniqueId(),
|
||||
System.currentTimeMillis() - this.startTime);
|
||||
case LEAST_DEATHS -> recordsRegistry.registerDeathRecord(this.player, this.deaths);
|
||||
case LEAST_DEATHS -> recordsRegistry.registerDeathRecord(this.player.getUniqueId(), this.deaths);
|
||||
case DEFAULT -> RecordResult.NONE;
|
||||
};
|
||||
switch (recordResult) {
|
||||
|
@ -32,9 +32,10 @@ public class CreateArenaCommand implements CommandExecutor {
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: Make sure the arena name doesn't contain any unwanted characters
|
||||
// Remove known characters that are likely to cause trouble if used in an arena name
|
||||
String arenaName = arguments[0].replaceAll("[§ :=&]", "");
|
||||
|
||||
DropperArena arena = new DropperArena(arguments[0], player.getLocation());
|
||||
DropperArena arena = new DropperArena(arenaName, player.getLocation());
|
||||
Dropper.getInstance().getArenaHandler().addArena(arena);
|
||||
commandSender.sendMessage("The arena was successfully created!");
|
||||
return true;
|
||||
|
@ -0,0 +1,37 @@
|
||||
package net.knarcraft.dropper.container;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A material container able to be serialized
|
||||
*
|
||||
* @param material <p>The material stored by this record</p>
|
||||
*/
|
||||
public record SerializableMaterial(Material material) implements ConfigurationSerializable {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("name", material.name());
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes a serialized material
|
||||
*
|
||||
* @param data <p>The serialized data</p>
|
||||
* @return <p>The deserialized material</p>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static SerializableMaterial deserialize(Map<String, Object> data) {
|
||||
Material material = Material.matchMaterial((String) data.getOrDefault("name", "AIR"));
|
||||
return new SerializableMaterial(material);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package net.knarcraft.dropper.container;
|
||||
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A UUID container able to be serialized
|
||||
*
|
||||
* @param uuid <p>The UUID stored by this record</p>
|
||||
*/
|
||||
public record SerializableUUID(UUID uuid) implements ConfigurationSerializable {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("id", uuid.toString());
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes a serialized UUID
|
||||
*
|
||||
* @param data <p>The serialized data</p>
|
||||
* @return <p>The deserialized UUID</p>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public static SerializableUUID deserialize(Map<String, Object> data) {
|
||||
String id = (String) data.getOrDefault("id", null);
|
||||
if (id != null) {
|
||||
return new SerializableUUID(UUID.fromString(id));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object instanceof SerializableUUID) {
|
||||
return this.uuid.equals(((SerializableUUID) object).uuid);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -41,6 +41,11 @@ public enum ArenaStorageKey {
|
||||
* The key for the type of this arena's win block
|
||||
*/
|
||||
WIN_BLOCK_TYPE("winBlockType"),
|
||||
|
||||
/**
|
||||
* The hey for this arena's records
|
||||
*/
|
||||
RECORDS("records"),
|
||||
;
|
||||
|
||||
private final @NotNull String key;
|
||||
|
@ -3,6 +3,7 @@ package net.knarcraft.dropper.util;
|
||||
import net.knarcraft.dropper.Dropper;
|
||||
import net.knarcraft.dropper.arena.DropperArena;
|
||||
import net.knarcraft.dropper.arena.DropperArenaRecordsRegistry;
|
||||
import net.knarcraft.dropper.container.SerializableMaterial;
|
||||
import net.knarcraft.dropper.property.ArenaStorageKey;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -49,7 +50,8 @@ public final class ArenaStorageHelper {
|
||||
configSection.set(ArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey(), arena.getPlayerVerticalVelocity());
|
||||
configSection.set(ArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey(), arena.getPlayerHorizontalVelocity());
|
||||
configSection.set(ArenaStorageKey.STAGE.getKey(), arena.getStage());
|
||||
configSection.set(ArenaStorageKey.WIN_BLOCK_TYPE.getKey(), arena.getWinBlockType());
|
||||
configSection.set(ArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
|
||||
configSection.set(ArenaStorageKey.RECORDS.getKey(), arena.getRecordsRegistry());
|
||||
}
|
||||
//TODO: Save records belonging to the arena
|
||||
configuration.save(arenaFile);
|
||||
@ -100,18 +102,25 @@ public final class ArenaStorageHelper {
|
||||
double verticalVelocity = configurationSection.getDouble(ArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey());
|
||||
double horizontalVelocity = configurationSection.getDouble(ArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey());
|
||||
Integer stage = (Integer) configurationSection.get(ArenaStorageKey.STAGE.getKey());
|
||||
Material winBlockType = (Material) configurationSection.get(ArenaStorageKey.WIN_BLOCK_TYPE.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 " +
|
||||
"section " + configurationSection.getName() + ". Please check the arenas storage file for issues.");
|
||||
return null;
|
||||
}
|
||||
if (winBlockType == null) {
|
||||
winBlockType = Material.WATER;
|
||||
winBlockType = new SerializableMaterial(Material.WATER);
|
||||
}
|
||||
//TODO: Load records for this arena
|
||||
if (recordsRegistry == null) {
|
||||
recordsRegistry = new DropperArenaRecordsRegistry();
|
||||
}
|
||||
|
||||
return new DropperArena(arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity, stage,
|
||||
winBlockType, new DropperArenaRecordsRegistry());
|
||||
winBlockType.material(), recordsRegistry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6,10 +6,14 @@ description: A plugin for dropper mini-games
|
||||
|
||||
commands:
|
||||
dropperlist:
|
||||
aliases:
|
||||
- dlist
|
||||
permission: dropper.join
|
||||
usage: /<command>
|
||||
description: Used to list all current dropper arenas
|
||||
dropperjoin:
|
||||
aliases:
|
||||
- djoin
|
||||
permission: dropper.join
|
||||
usage: |
|
||||
/<command> <arena> [mode]
|
||||
@ -18,18 +22,26 @@ commands:
|
||||
time = A shortest-time competitive game-mode
|
||||
description: Used to join a dropper arena
|
||||
dropperleave:
|
||||
aliases:
|
||||
- dleave
|
||||
permission: dropper.join
|
||||
usage: /<command>
|
||||
description: Used to leave the current dropper arena
|
||||
droppercreate:
|
||||
aliases:
|
||||
- dcreate
|
||||
permission: dropper.create
|
||||
usage: /<command> (Details not finalized)
|
||||
description: Used to create a new dropper arena
|
||||
dropperedit:
|
||||
aliases:
|
||||
- dedit
|
||||
permission: dropper.edit
|
||||
usage: /<command> (Details not finalized)
|
||||
description: Used to edit an existing dropper arena
|
||||
dropperremove:
|
||||
aliases:
|
||||
- dremove
|
||||
permission: dropper.remove
|
||||
usage: /<command> <arena>
|
||||
description: Used to remove an existing dropper arena
|
||||
|
Loading…
Reference in New Issue
Block a user