Makes it possible to get the current value from /dedit

Finally gets rid of the redundancy when checking if a record has been beaten
Adds tab-completions for arenas and properties to the edit command
Adds an ArenaEditableProperty enum to keep track of editable arena properties
This commit is contained in:
Kristian Knarvik 2023-03-29 11:37:26 +02:00
parent 34989e6673
commit ca5b0fcbca
5 changed files with 188 additions and 59 deletions

View File

@ -17,8 +17,8 @@ import java.util.stream.Stream;
public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
private final UUID arenaId;
private final Map<UUID, Integer> leastDeaths;
private final Map<UUID, Long> shortestTimeMilliSeconds;
private final @NotNull Map<UUID, Number> leastDeaths;
private final @NotNull Map<UUID, Number> shortestTimeMilliSeconds;
/**
* Instantiates a new empty records registry
@ -48,7 +48,11 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
* @return <p>Existing death records</p>
*/
public Map<UUID, Integer> getLeastDeathsRecords() {
return new HashMap<>(this.leastDeaths);
Map<UUID, Integer> leastDeathRecords = new HashMap<>();
for (Map.Entry<UUID, Number> entry : this.leastDeaths.entrySet()) {
leastDeathRecords.put(entry.getKey(), entry.getValue().intValue());
}
return leastDeathRecords;
}
/**
@ -57,7 +61,11 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
* @return <p>Existing time records</p>
*/
public Map<UUID, Long> getShortestTimeMilliSecondsRecords() {
return new HashMap<>(this.shortestTimeMilliSeconds);
Map<UUID, Long> leastTimeRecords = new HashMap<>();
for (Map.Entry<UUID, Number> entry : this.shortestTimeMilliSeconds.entrySet()) {
leastTimeRecords.put(entry.getKey(), entry.getValue().longValue());
}
return leastTimeRecords;
}
/**
@ -68,28 +76,7 @@ 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) {
RecordResult result;
Stream<Map.Entry<UUID, Integer>> records = leastDeaths.entrySet().stream();
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(playerId, deaths);
save();
} else if (leastDeaths.containsKey(playerId) && deaths < leastDeaths.get(playerId)) {
// If the given value is less than the player's previous value, that's a personal best!
result = RecordResult.PERSONAL_BEST;
leastDeaths.put(playerId, deaths);
save();
} else {
// Make sure to save the record if this is the user's first attempt
if (!leastDeaths.containsKey(playerId)) {
save();
}
result = RecordResult.NONE;
}
return result;
return registerRecord(leastDeaths, playerId, deaths);
}
/**
@ -100,29 +87,7 @@ 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) {
RecordResult result;
Stream<Map.Entry<UUID, Long>> records = shortestTimeMilliSeconds.entrySet().stream();
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(playerId, milliseconds);
save();
} else if (shortestTimeMilliSeconds.containsKey(playerId) &&
milliseconds < shortestTimeMilliSeconds.get(playerId)) {
//If the given value is less than the player's previous value, that's a personal best!
result = RecordResult.PERSONAL_BEST;
shortestTimeMilliSeconds.put(playerId, milliseconds);
save();
} else {
// Make sure to save the record if this is the user's first attempt
if (!shortestTimeMilliSeconds.containsKey(playerId)) {
save();
}
result = RecordResult.NONE;
}
return result;
return registerRecord(shortestTimeMilliSeconds, playerId, milliseconds);
}
/**
@ -132,20 +97,55 @@ public class DropperArenaRecordsRegistry implements ConfigurationSerializable {
Dropper.getInstance().getArenaHandler().saveData(this.arenaId);
}
/**
* Registers a new record if applicable
*
* @param existingRecords <p>The map of existing records to use</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 @NotNull RecordResult registerRecord(@NotNull Map<UUID, Number> existingRecords, @NotNull UUID playerId,
Number amount) {
RecordResult result;
Stream<Map.Entry<UUID, Number>> records = existingRecords.entrySet().stream();
long amountLong = amount.longValue();
if (records.allMatch((entry) -> amountLong < entry.getValue().longValue())) {
// If the given value is less than all other values, that's a world record!
result = RecordResult.WORLD_RECORD;
existingRecords.put(playerId, amount);
save();
} else if (existingRecords.containsKey(playerId) && amountLong < existingRecords.get(playerId).longValue()) {
// If the given value is less than the player's previous value, that's a personal best!
result = RecordResult.PERSONAL_BEST;
existingRecords.put(playerId, amount);
save();
} else {
// Make sure to save the record if this is the user's first attempt
if (!existingRecords.containsKey(playerId)) {
save();
}
result = RecordResult.NONE;
}
return result;
}
@NotNull
@Override
public Map<String, Object> serialize() {
Map<String, Object> data = new HashMap<>();
data.put("arenaId", new SerializableUUID(this.arenaId));
Map<SerializableUUID, Integer> leastDeaths = new HashMap<>();
for (Map.Entry<UUID, Integer> entry : this.leastDeaths.entrySet()) {
Map<SerializableUUID, Number> leastDeaths = new HashMap<>();
for (Map.Entry<UUID, Number> entry : this.leastDeaths.entrySet()) {
leastDeaths.put(new SerializableUUID(entry.getKey()), entry.getValue());
}
data.put("leastDeaths", leastDeaths);
Map<SerializableUUID, Long> shortestTimeMilliSeconds = new HashMap<>();
for (Map.Entry<UUID, Long> entry : this.shortestTimeMilliSeconds.entrySet()) {
Map<SerializableUUID, Number> shortestTimeMilliSeconds = new HashMap<>();
for (Map.Entry<UUID, Number> entry : this.shortestTimeMilliSeconds.entrySet()) {
shortestTimeMilliSeconds.put(new SerializableUUID(entry.getKey()), entry.getValue());
}
data.put("shortestTime", shortestTimeMilliSeconds);

View File

@ -2,6 +2,7 @@ package net.knarcraft.dropper.command;
import net.knarcraft.dropper.Dropper;
import net.knarcraft.dropper.arena.DropperArena;
import net.knarcraft.dropper.property.ArenaEditableProperty;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@ -31,9 +32,22 @@ public class EditArenaCommand implements CommandExecutor {
return false;
}
//TODO: If an arena name and a property is given, display the current value
//TODO: If an arena name, a property and a value is given, check if it's valid, and update the property
return false;
ArenaEditableProperty editableProperty = ArenaEditableProperty.getFromArgumentString(arguments[1]);
if (editableProperty == null) {
commandSender.sendMessage("Unknown property specified.");
return false;
}
String currentValueFormat = "Current value of %s is: %s";
if (arguments.length < 3) {
// Print the current value of the property
String value = editableProperty.getCurrentValueAsString(specifiedArena);
commandSender.sendMessage(String.format(currentValueFormat, editableProperty.getArgumentString(), value));
} else {
// TODO: Expect a new value for the option, which needs to be validated, and possibly set
}
return true;
}
}

View File

@ -1,11 +1,13 @@
package net.knarcraft.dropper.command;
import net.knarcraft.dropper.util.TabCompleteHelper;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
@ -16,9 +18,16 @@ public class EditArenaTabCompleter implements TabCompleter {
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String label, @NotNull String[] args) {
//TODO: Tab-complete existing arena names
//TODO: If an arena name is given, tab-complete change-able properties
return null;
if (args.length == 1) {
return TabCompleteHelper.getArenas();
} else if (args.length == 2) {
return TabCompleteHelper.getArenaProperties();
} else if (args.length == 3) {
//TODO: Tab-complete possible values for the given property
return null;
} else {
return new ArrayList<>();
}
}
}

View File

@ -0,0 +1,92 @@
package net.knarcraft.dropper.property;
import net.knarcraft.dropper.arena.DropperArena;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
/**
* All editable properties of a dropper arena
*/
public enum ArenaEditableProperty {
/**
* The name of the arena
*/
NAME("name", DropperArena::getArenaName),
/**
* The arena's spawn location
*/
SPAWN_LOCATION("spawnLocation", (arena) -> String.valueOf(arena.getSpawnLocation())),
/**
* The arena's exit location
*/
EXIT_LOCATION("exitLocation", (arena) -> String.valueOf(arena.getExitLocation())),
/**
* The arena's vertical velocity
*/
VERTICAL_VELOCITY("verticalVelocity", (arena) -> String.valueOf(arena.getPlayerVerticalVelocity())),
/**
* The arena's horizontal velocity
*/
HORIZONTAL_VELOCITY("horizontalVelocity", (arena) -> String.valueOf(arena.getPlayerHorizontalVelocity())),
/**
* The arena's win block type
*/
WIN_BLOCK_TYPE("winBlockType", (arena) -> arena.getWinBlockType().toString()),
;
private final @NotNull String argumentString;
private final Function<DropperArena, String> currentValueProvider;
/**
* Instantiates a new arena editable property
*
* @param argumentString <p>The argument string used to specify this property</p>
*/
ArenaEditableProperty(@NotNull String argumentString, Function<DropperArena, String> currentValueProvider) {
this.argumentString = argumentString;
this.currentValueProvider = currentValueProvider;
}
/**
* Gets the string representation of this property's current value
*
* @param arena <p>The arena to check the value for</p>
* @return <p>The current value as a string</p>
*/
public String getCurrentValueAsString(DropperArena arena) {
return this.currentValueProvider.apply(arena);
}
/**
* Gets the argument string used to specify this property
*
* @return <p>The argument string</p>
*/
public @NotNull String getArgumentString() {
return this.argumentString;
}
/**
* Gets the editable property corresponding to the given argument string
*
* @param argumentString <p>The argument string used to specify an editable property</p>
* @return <p>The corresponding editable property, or null if not found</p>
*/
public static @Nullable ArenaEditableProperty getFromArgumentString(String argumentString) {
for (ArenaEditableProperty property : ArenaEditableProperty.values()) {
if (property.argumentString.equalsIgnoreCase(argumentString)) {
return property;
}
}
return null;
}
}

View File

@ -2,6 +2,7 @@ package net.knarcraft.dropper.util;
import net.knarcraft.dropper.Dropper;
import net.knarcraft.dropper.arena.DropperArena;
import net.knarcraft.dropper.property.ArenaEditableProperty;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@ -29,4 +30,17 @@ public final class TabCompleteHelper {
return arenaNames;
}
/**
* Gets the argument strings of all arena properties
*
* @return <p>All arena properties</p>
*/
public static @NotNull List<String> getArenaProperties() {
List<String> arenaProperties = new ArrayList<>();
for (ArenaEditableProperty property : ArenaEditableProperty.values()) {
arenaProperties.add(property.getArgumentString());
}
return arenaProperties;
}
}