Fixes various issues

Makes ArenaRecord abstract to make serialization possible
Makes IntegerRecord and LongRecord serializable
Adds a null check when summing records
Fixes records not being saved, as a copy was edited
This commit is contained in:
Kristian Knarvik 2023-04-07 15:15:41 +02:00
parent 5be6f0d00e
commit e1c4a6a97c
7 changed files with 62 additions and 19 deletions

View File

@ -6,7 +6,8 @@ import net.knarcraft.dropper.arena.DropperArenaHandler;
import net.knarcraft.dropper.arena.DropperArenaPlayerRegistry;
import net.knarcraft.dropper.arena.DropperArenaRecordsRegistry;
import net.knarcraft.dropper.arena.DropperArenaSession;
import net.knarcraft.dropper.arena.record.ArenaRecord;
import net.knarcraft.dropper.arena.record.IntegerRecord;
import net.knarcraft.dropper.arena.record.LongRecord;
import net.knarcraft.dropper.command.CreateArenaCommand;
import net.knarcraft.dropper.command.EditArenaCommand;
import net.knarcraft.dropper.command.EditArenaTabCompleter;
@ -97,7 +98,8 @@ public final class Dropper extends JavaPlugin {
ConfigurationSerialization.registerClass(DropperArenaData.class);
ConfigurationSerialization.registerClass(DropperArenaGroup.class);
ConfigurationSerialization.registerClass(ArenaGameMode.class);
ConfigurationSerialization.registerClass(ArenaRecord.class);
ConfigurationSerialization.registerClass(LongRecord.class);
ConfigurationSerialization.registerClass(IntegerRecord.class);
}
@Override

View File

@ -103,6 +103,12 @@ public record DropperArenaData(@NotNull UUID arenaId,
Map<ArenaGameMode, Set<SerializableUUID>> playersCompletedData =
(Map<ArenaGameMode, Set<SerializableUUID>>) data.get("playersCompleted");
if (recordsRegistry == null) {
recordsRegistry = new HashMap<>();
} else if (playersCompletedData == null) {
playersCompletedData = new HashMap<>();
}
// Convert the serializable UUIDs to normal UUIDs
Map<ArenaGameMode, Set<UUID>> allPlayersCompleted = new HashMap<>();
for (ArenaGameMode arenaGameMode : playersCompletedData.keySet()) {
@ -111,6 +117,10 @@ public record DropperArenaData(@NotNull UUID arenaId,
playersCompleted.add(completedId.uuid());
}
allPlayersCompleted.put(arenaGameMode, playersCompleted);
if (!recordsRegistry.containsKey(arenaGameMode) || recordsRegistry.get(arenaGameMode) == null) {
recordsRegistry.put(arenaGameMode, new DropperArenaRecordsRegistry(serializableUUID.uuid()));
}
}
return new DropperArenaData(serializableUUID.uuid(), recordsRegistry, allPlayersCompleted);
}

View File

@ -14,9 +14,11 @@ import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
/**
* A registry keeping track of all records
@ -75,8 +77,9 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
* @return <p>The result explaining what type of record was achieved</p>
*/
public @NotNull RecordResult registerDeathRecord(@NotNull UUID playerId, int deaths) {
Consumer<Integer> consumer = (value) -> leastDeaths.add(new IntegerRecord(playerId, value));
Set<ArenaRecord<Integer>> asInt = new HashSet<>(leastDeaths);
return registerRecord(asInt, playerId, deaths);
return registerRecord(asInt, consumer, playerId, deaths);
}
/**
@ -87,8 +90,9 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
* @return <p>The result explaining what type of record was achieved</p>
*/
public @NotNull RecordResult registerTimeRecord(@NotNull UUID playerId, long milliseconds) {
Consumer<Long> consumer = (value) -> shortestTimeMilliSeconds.add(new LongRecord(playerId, value));
Set<ArenaRecord<Long>> asLong = new HashSet<>(shortestTimeMilliSeconds);
return registerRecord(asLong, playerId, milliseconds);
return registerRecord(asLong, consumer, playerId, milliseconds);
}
/**
@ -102,17 +106,19 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
* Registers a new record if applicable
*
* @param existingRecords <p>The map of existing records to use</p>
* @param recordSetter <p>The consumer used to set a new record</p>
* @param playerId <p>The id of the player that potentially achieved a record</p>
* @param amount <p>The amount of whatever the player achieved</p>
* @return <p>The result of the player's record attempt</p>
*/
private <T extends Comparable<T>> @NotNull RecordResult registerRecord(@NotNull Set<ArenaRecord<T>> existingRecords,
@NotNull Consumer<T> recordSetter,
@NotNull UUID playerId, T amount) {
RecordResult result;
if (existingRecords.stream().allMatch((entry) -> amount.compareTo(entry.getRecord()) < 0)) {
// If the given value is less than all other values, that's a world record!
result = RecordResult.WORLD_RECORD;
existingRecords.add(new ArenaRecord<>(playerId, amount));
recordSetter.accept(amount);
save();
return result;
}
@ -121,11 +127,12 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
if (playerRecord != null && amount.compareTo(playerRecord.getRecord()) < 0) {
// If the given value is less than the player's previous value, that's a personal best!
result = RecordResult.PERSONAL_BEST;
existingRecords.add(new ArenaRecord<>(playerId, amount));
recordSetter.accept(amount);
save();
} else {
// Make sure to save the record if this is the user's first attempt
if (playerRecord == null) {
recordSetter.accept(amount);
save();
}
result = RecordResult.NONE;
@ -176,6 +183,9 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
(Set<IntegerRecord>) data.getOrDefault("leastDeaths", new HashMap<>());
Set<LongRecord> shortestTimeMilliseconds =
(Set<LongRecord>) data.getOrDefault("shortestTime", new HashMap<>());
leastDeaths.removeIf(Objects::isNull);
shortestTimeMilliseconds.removeIf(Objects::isNull);
return new DropperArenaRecordsRegistry(arenaId, leastDeaths, shortestTimeMilliseconds);
}

View File

@ -12,7 +12,7 @@ import java.util.UUID;
/**
* A record stored for an arena
*/
public class ArenaRecord<K extends Comparable<K>> implements Comparable<ArenaRecord<K>>, ConfigurationSerializable {
public abstract class ArenaRecord<K extends Comparable<K>> implements Comparable<ArenaRecord<K>>, ConfigurationSerializable {
private final UUID userId;
private final K record;
@ -63,18 +63,6 @@ public class ArenaRecord<K extends Comparable<K>> implements Comparable<ArenaRec
return data;
}
/**
* Deserializes the saved arena record
*
* @param data <p>The data to deserialize</p>
* @param <K> <p>The type of the deserialized record</p>
* @return <p>The deserialized data</p>
*/
@SuppressWarnings({"unused", "unchecked"})
public static <K extends Comparable<K>> ArenaRecord<K> deserialize(@NotNull Map<String, Object> data) {
return new ArenaRecord<>(((SerializableUUID) data.get("userId")).uuid(), (K) data.get("record"));
}
@Override
public int hashCode() {
return Objects.hash(userId, record);

View File

@ -1,5 +1,9 @@
package net.knarcraft.dropper.arena.record;
import net.knarcraft.dropper.container.SerializableUUID;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.UUID;
/**
@ -20,4 +24,15 @@ public class IntegerRecord extends SummableArenaRecord<Integer> {
return new IntegerRecord(this.getUserId(), this.getRecord() + value);
}
/**
* Deserializes the saved arena record
*
* @param data <p>The data to deserialize</p>
* @return <p>The deserialized data</p>
*/
@SuppressWarnings("unused")
public static IntegerRecord deserialize(@NotNull Map<String, Object> data) {
return new IntegerRecord(((SerializableUUID) data.get("userId")).uuid(), (Integer) data.get("record"));
}
}

View File

@ -1,5 +1,9 @@
package net.knarcraft.dropper.arena.record;
import net.knarcraft.dropper.container.SerializableUUID;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.UUID;
/**
@ -20,4 +24,15 @@ public class LongRecord extends SummableArenaRecord<Long> {
return new LongRecord(this.getUserId(), this.getRecord() + value);
}
/**
* Deserializes the saved arena record
*
* @param data <p>The data to deserialize</p>
* @return <p>The deserialized data</p>
*/
@SuppressWarnings("unused")
public static LongRecord deserialize(@NotNull Map<String, Object> data) {
return new LongRecord(((SerializableUUID) data.get("userId")).uuid(), ((Number) data.get("record")).longValue());
}
}

View File

@ -147,6 +147,9 @@ public final class DropperGroupRecordHelper {
Set<SummableArenaRecord<K>> existingRecords = recordSupplier.apply(arena, gameMode);
// For each arena's record registry, calculate the combined records
for (SummableArenaRecord<K> value : existingRecords) {
if (value == null) {
continue;
}
UUID userId = value.getUserId();
// Bump the number of records found for the user