Mostly finishes rewards

This commit is contained in:
Kristian Knarvik 2023-07-10 17:51:59 +02:00
parent d7b1695cd9
commit 9dff407713
21 changed files with 762 additions and 31 deletions

View File

@ -126,7 +126,7 @@
<dependency>
<groupId>net.knarcraft</groupId>
<artifactId>knarlib</artifactId>
<version>1.2.3</version>
<version>1.2.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -29,9 +29,12 @@ import net.knarcraft.minigames.arena.reward.CommandReward;
import net.knarcraft.minigames.arena.reward.EconomyReward;
import net.knarcraft.minigames.arena.reward.ItemReward;
import net.knarcraft.minigames.arena.reward.PermissionReward;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import net.knarcraft.minigames.command.LeaveArenaCommand;
import net.knarcraft.minigames.command.MenuCommand;
import net.knarcraft.minigames.command.ReloadCommand;
import net.knarcraft.minigames.command.SetArenaRewardCommand;
import net.knarcraft.minigames.command.SetArenaRewardTabCompleter;
import net.knarcraft.minigames.command.dropper.CreateDropperArenaCommand;
import net.knarcraft.minigames.command.dropper.DropperGroupListCommand;
import net.knarcraft.minigames.command.dropper.DropperGroupSetCommand;
@ -276,6 +279,7 @@ public final class MiniGames extends JavaPlugin {
ConfigurationSerialization.registerClass(EconomyReward.class);
ConfigurationSerialization.registerClass(ItemReward.class);
ConfigurationSerialization.registerClass(PermissionReward.class);
ConfigurationSerialization.registerClass(RewardCondition.class);
}
@Override
@ -386,6 +390,7 @@ public final class MiniGames extends JavaPlugin {
registerCommand("miniGamesReload", new ReloadCommand(), null);
registerCommand("miniGamesLeave", new LeaveArenaCommand(), null);
registerCommand("miniGamesMenu", new MenuCommand(), null);
registerCommand("miniGamesReward", new SetArenaRewardCommand(), new SetArenaRewardTabCompleter());
registerDropperCommands();
registerParkourCommands();

View File

@ -2,9 +2,12 @@ package net.knarcraft.minigames.arena;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.minigames.MiniGames;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import net.knarcraft.minigames.config.MiniGameMessage;
import net.knarcraft.minigames.property.RecordResult;
import net.knarcraft.minigames.property.RecordType;
import net.knarcraft.minigames.util.PlayerTeleporter;
import net.knarcraft.minigames.util.RewardHelper;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@ -59,9 +62,9 @@ public abstract class AbstractArenaSession implements ArenaSession {
* Announces a record set by this player
*
* @param recordResult <p>The result of the record</p>
* @param type <p>The type of record set (time or deaths)</p>
* @param recordType <p>The type of record set (time or deaths)</p>
*/
protected void announceRecord(@NotNull RecordResult recordResult, @NotNull String type) {
protected void announceRecord(@NotNull RecordResult recordResult, @NotNull RecordType recordType) {
if (recordResult == RecordResult.NONE) {
return;
}
@ -75,11 +78,15 @@ public abstract class AbstractArenaSession implements ArenaSession {
default -> throw new IllegalStateException("Unexpected value: " + recordResult);
};
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
String recordInfo = stringFormatter.replacePlaceholder(recordInfoMiniGameMessage, "{recordType}", type);
String recordInfo = stringFormatter.replacePlaceholder(recordInfoMiniGameMessage, "{recordType}",
recordType.name().toLowerCase().replace("_", " "));
stringFormatter.displaySuccessMessage(player, stringFormatter.replacePlaceholders(
MiniGameMessage.SUCCESS_RECORD_ACHIEVED, new String[]{"{gameMode}", "{recordInfo}"},
new String[]{gameModeString, recordInfo}));
// Reward the player
rewardRecord(recordResult, recordType);
}
/**
@ -88,8 +95,32 @@ public abstract class AbstractArenaSession implements ArenaSession {
protected void registerRecord() {
ArenaRecordsRegistry recordsRegistry = this.arena.getData().getRecordRegistries().get(this.gameMode);
long timeElapsed = System.currentTimeMillis() - this.startTime;
announceRecord(recordsRegistry.registerTimeRecord(this.player.getUniqueId(), timeElapsed), "time");
announceRecord(recordsRegistry.registerDeathRecord(this.player.getUniqueId(), this.deaths), "least deaths");
announceRecord(recordsRegistry.registerTimeRecord(this.player.getUniqueId(), timeElapsed), RecordType.TIME);
announceRecord(recordsRegistry.registerDeathRecord(this.player.getUniqueId(), this.deaths), RecordType.DEATHS);
}
/**
* Rewards the specified achieved record
*
* @param recordResult <p>The result of the record achieved</p>
* @param recordType <p>The type of record achieved</p>
*/
protected void rewardRecord(RecordResult recordResult, RecordType recordType) {
RewardCondition condition = null;
if (recordResult == RecordResult.WORLD_RECORD) {
if (recordType == RecordType.DEATHS) {
condition = RewardCondition.GLOBAL_DEATH_RECORD;
} else if (recordType == RecordType.TIME) {
condition = RewardCondition.GLOBAL_TIME_RECORD;
}
} else if (recordResult == RecordResult.PERSONAL_BEST) {
if (recordType == RecordType.DEATHS) {
condition = RewardCondition.PERSONAL_DEATH_RECORD;
} else if (recordType == RecordType.TIME) {
condition = RewardCondition.PERSONAL_TIME_RECORD;
}
}
RewardHelper.grantRewards(this.player, this.arena.getRewards(condition));
}
/**

View File

@ -1,10 +1,13 @@
package net.knarcraft.minigames.arena;
import net.knarcraft.minigames.arena.reward.Reward;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.UUID;
/**
@ -91,4 +94,27 @@ public interface Arena {
*/
@Nullable Location getExitLocation();
/**
* Adds a reward to this arena
*
* @param rewardCondition <p>The condition for the reward to be granted</p>
* @param reward <p>The reward to be granted</p>
*/
void addReward(@NotNull RewardCondition rewardCondition, @NotNull Reward reward);
/**
* Clears this arena's rewards for the given condition
*
* @param rewardCondition <p>The reward condition to clear all rewards for</p>
*/
void clearRewards(@NotNull RewardCondition rewardCondition);
/**
* Gets all rewards for the given reward condition
*
* @param rewardCondition <p>The condition to get the rewards for</p>
* @return <p>All rewards</p>
*/
@NotNull Set<Reward> getRewards(RewardCondition rewardCondition);
}

View File

@ -4,6 +4,8 @@ import net.knarcraft.minigames.MiniGames;
import net.knarcraft.minigames.arena.Arena;
import net.knarcraft.minigames.arena.ArenaGameMode;
import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
import net.knarcraft.minigames.arena.reward.Reward;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import net.knarcraft.minigames.config.DropperConfiguration;
import net.knarcraft.minigames.util.DropperArenaStorageHelper;
import net.knarcraft.minigames.util.StringSanitizer;
@ -15,7 +17,9 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import static net.knarcraft.minigames.util.InputValidationHelper.isInvalid;
@ -70,6 +74,8 @@ public class DropperArena implements Arena {
private final DropperArenaHandler dropperArenaHandler;
private Map<RewardCondition, Set<Reward>> rewards = new HashMap<>();
private static final DropperConfiguration dropperConfiguration = MiniGames.getInstance().getDropperConfiguration();
/**
@ -82,13 +88,14 @@ public class DropperArena implements Arena {
* @param playerVerticalVelocity <p>The velocity to use for players' vertical velocity</p>
* @param playerHorizontalVelocity <p>The velocity to use for players' horizontal velocity (-1 to 1)</p>
* @param winBlockType <p>The material of the block players have to hit to win this dropper arena</p>
* @param rewards <p>The rewards given by this arena</p>
* @param dropperArenaData <p>The arena data keeping track of which players have done what in this arena</p>
* @param arenaHandler <p>The arena handler used for saving any changes</p>
*/
public DropperArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
@Nullable Location exitLocation, double playerVerticalVelocity, float playerHorizontalVelocity,
@NotNull Material winBlockType, @NotNull DropperArenaData dropperArenaData,
@NotNull DropperArenaHandler arenaHandler) {
@NotNull Material winBlockType, @NotNull Map<RewardCondition, Set<Reward>> rewards,
@NotNull DropperArenaData dropperArenaData, @NotNull DropperArenaHandler arenaHandler) {
this.arenaId = arenaId;
this.arenaName = arenaName;
this.spawnLocation = spawnLocation;
@ -98,6 +105,7 @@ public class DropperArena implements Arena {
this.winBlockType = winBlockType;
this.dropperArenaData = dropperArenaData;
this.dropperArenaHandler = arenaHandler;
this.rewards = rewards;
}
/**
@ -155,6 +163,28 @@ public class DropperArena implements Arena {
return this.exitLocation != null ? this.exitLocation.clone() : null;
}
@Override
public void addReward(@NotNull RewardCondition rewardCondition, @NotNull Reward reward) {
this.rewards.computeIfAbsent(rewardCondition, k -> new HashSet<>());
this.rewards.get(rewardCondition).add(reward);
this.dropperArenaHandler.saveArenas();
}
@Override
public void clearRewards(@NotNull RewardCondition rewardCondition) {
this.rewards.remove(rewardCondition);
this.dropperArenaHandler.saveArenas();
}
@Override
public @NotNull Set<Reward> getRewards(RewardCondition rewardCondition) {
if (this.rewards.containsKey(rewardCondition) && this.rewards.get(rewardCondition) != null) {
return this.rewards.get(rewardCondition);
} else {
return new HashSet<>();
}
}
/**
* Gets the vertical velocity for players in this arena
*
@ -237,7 +267,7 @@ public class DropperArena implements Arena {
return false;
} else {
this.spawnLocation = newLocation;
dropperArenaHandler.saveArenas();
this.dropperArenaHandler.saveArenas();
return true;
}
}
@ -253,7 +283,7 @@ public class DropperArena implements Arena {
return false;
} else {
this.exitLocation = newLocation;
dropperArenaHandler.saveArenas();
this.dropperArenaHandler.saveArenas();
return true;
}
}
@ -269,8 +299,8 @@ public class DropperArena implements Arena {
String oldName = this.getArenaNameSanitized();
this.arenaName = arenaName;
// Update the arena lookup map to make sure the new name can be used immediately
dropperArenaHandler.updateLookupName(oldName, this.getArenaNameSanitized());
dropperArenaHandler.saveArenas();
this.dropperArenaHandler.updateLookupName(oldName, this.getArenaNameSanitized());
this.dropperArenaHandler.saveArenas();
return true;
} else {
return false;
@ -290,7 +320,7 @@ public class DropperArena implements Arena {
return false;
} else {
this.winBlockType = material;
dropperArenaHandler.saveArenas();
this.dropperArenaHandler.saveArenas();
return true;
}
}
@ -308,7 +338,7 @@ public class DropperArena implements Arena {
return false;
} else {
this.playerHorizontalVelocity = horizontalVelocity;
dropperArenaHandler.saveArenas();
this.dropperArenaHandler.saveArenas();
return true;
}
}
@ -324,7 +354,7 @@ public class DropperArena implements Arena {
return false;
} else {
this.playerVerticalVelocity = verticalVelocity;
dropperArenaHandler.saveArenas();
this.dropperArenaHandler.saveArenas();
return true;
}
}

View File

@ -4,10 +4,12 @@ import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.minigames.MiniGames;
import net.knarcraft.minigames.arena.AbstractArenaSession;
import net.knarcraft.minigames.arena.PlayerEntryState;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import net.knarcraft.minigames.config.MiniGameMessage;
import net.knarcraft.minigames.gui.ArenaGUI;
import net.knarcraft.minigames.gui.DropperGUI;
import net.knarcraft.minigames.util.PlayerTeleporter;
import net.knarcraft.minigames.util.RewardHelper;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@ -98,8 +100,10 @@ public class DropperArenaSession extends AbstractArenaSession {
// Mark the arena as cleared
if (this.arena.getData().setCompleted(this.gameMode, this.player)) {
stringFormatter.displaySuccessMessage(this.player, MiniGameMessage.SUCCESS_ARENA_FIRST_CLEAR);
RewardHelper.grantRewards(this.player, this.arena.getRewards(RewardCondition.FIRST_WIN));
}
stringFormatter.displaySuccessMessage(this.player, MiniGameMessage.SUCCESS_ARENA_WIN);
RewardHelper.grantRewards(this.player, this.arena.getRewards(RewardCondition.WIN));
// Teleport the player out of the arena
teleportToExit(false);

View File

@ -43,9 +43,14 @@ public enum DropperArenaStorageKey {
WIN_BLOCK_TYPE("winBlockType"),
/**
* The hey for this arena's data
* The key for this arena's data
*/
DATA("arenaData"),
/**
* The key for this arena's rewards
*/
REWARDS("rewards"),
;
private final @NotNull String key;

View File

@ -5,6 +5,8 @@ import net.knarcraft.minigames.MiniGames;
import net.knarcraft.minigames.arena.Arena;
import net.knarcraft.minigames.arena.ArenaGameMode;
import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
import net.knarcraft.minigames.arena.reward.Reward;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import net.knarcraft.minigames.util.ParkourArenaStorageHelper;
import net.knarcraft.minigames.util.StringSanitizer;
import org.bukkit.Location;
@ -82,21 +84,27 @@ public class ParkourArena implements Arena {
private final @NotNull ParkourArenaHandler parkourArenaHandler;
private Map<RewardCondition, Set<Reward>> rewards = new HashMap<>();
/**
* Instantiates a new parkour 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>
* @param winBlockType <p>The material of the block players have to hit to win this parkour arena</p>
* @param winLocation <p>The location a player has to reach to win this arena</p>
* @param parkourArenaData <p>The arena data keeping track of which players have done what in this arena</p>
* @param arenaHandler <p>The arena handler used for saving any changes</p>
* @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>
* @param winBlockType <p>The material of the block players have to hit to win this parkour arena</p>
* @param winLocation <p>The location a player has to reach to win this arena</p>
* @param killPlaneBlockNames <p>The names of the type of blocks</p>
* @param checkpoints <p>The checkpoints set for this arena</p>
* @param rewards <p>The rewards given by this arena</p>
* @param parkourArenaData <p>The arena data keeping track of which players have done what in this arena</p>
* @param arenaHandler <p>The arena handler used for saving any changes</p>
*/
public ParkourArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
@Nullable Location exitLocation, @NotNull Material winBlockType, @Nullable Location winLocation,
@Nullable Set<String> killPlaneBlockNames, @NotNull List<Location> checkpoints,
@NotNull Map<RewardCondition, Set<Reward>> rewards,
@NotNull ParkourArenaData parkourArenaData, @NotNull ParkourArenaHandler arenaHandler) {
this.arenaId = arenaId;
this.arenaName = arenaName;
@ -110,6 +118,7 @@ public class ParkourArena implements Arena {
this.checkpoints = checkpoints;
this.parkourArenaData = parkourArenaData;
this.parkourArenaHandler = arenaHandler;
this.rewards = rewards;
}
/**
@ -167,6 +176,28 @@ public class ParkourArena implements Arena {
return this.exitLocation;
}
@Override
public void addReward(@NotNull RewardCondition rewardCondition, @NotNull Reward reward) {
this.rewards.computeIfAbsent(rewardCondition, k -> new HashSet<>());
this.rewards.get(rewardCondition).add(reward);
this.parkourArenaHandler.saveArenas();
}
@Override
public void clearRewards(@NotNull RewardCondition rewardCondition) {
this.rewards.remove(rewardCondition);
this.parkourArenaHandler.saveArenas();
}
@Override
public @NotNull Set<Reward> getRewards(RewardCondition rewardCondition) {
if (this.rewards.containsKey(rewardCondition)) {
return this.rewards.get(rewardCondition);
} else {
return new HashSet<>();
}
}
/**
* Gets the type of block a player has to hit to win this arena
*

View File

@ -1,12 +1,15 @@
package net.knarcraft.minigames.arena.parkour;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.minigames.MiniGames;
import net.knarcraft.minigames.arena.AbstractArenaSession;
import net.knarcraft.minigames.arena.PlayerEntryState;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import net.knarcraft.minigames.config.MiniGameMessage;
import net.knarcraft.minigames.gui.ArenaGUI;
import net.knarcraft.minigames.gui.ParkourGUI;
import net.knarcraft.minigames.util.PlayerTeleporter;
import net.knarcraft.minigames.util.RewardHelper;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@ -87,13 +90,15 @@ public class ParkourArenaSession extends AbstractArenaSession {
registerRecord();
}
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
// Mark the arena as cleared
if (this.arena.getData().setCompleted(this.gameMode, this.player)) {
MiniGames.getInstance().getStringFormatter().displaySuccessMessage(this.player,
MiniGameMessage.SUCCESS_ARENA_FIRST_CLEAR);
stringFormatter.displaySuccessMessage(this.player, MiniGameMessage.SUCCESS_ARENA_FIRST_CLEAR);
RewardHelper.grantRewards(this.player, this.arena.getRewards(RewardCondition.FIRST_WIN));
}
MiniGames.getInstance().getStringFormatter().displaySuccessMessage(this.player,
MiniGameMessage.SUCCESS_ARENA_WIN);
stringFormatter.displaySuccessMessage(this.player, MiniGameMessage.SUCCESS_ARENA_WIN);
RewardHelper.grantRewards(this.player, this.arena.getRewards(RewardCondition.WIN));
// Teleport the player out of the arena
teleportToExit(false);

View File

@ -51,6 +51,11 @@ public enum ParkourArenaStorageKey {
* The hey for this arena's data
*/
DATA("arenaData"),
/**
* The key for this arena's rewards
*/
REWARDS("rewards"),
;
private final @NotNull String key;

View File

@ -0,0 +1,83 @@
package net.knarcraft.minigames.arena.reward;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* The condition for granting a reward
*/
public enum RewardCondition implements ConfigurationSerializable {
/**
* The reward is granted each time the player wins/clears the arena
*/
WIN,
/**
* The reward is granted the first time the player wins/clears the arena
*/
FIRST_WIN,
/**
* The reward is granted if the player beats their personal least deaths record
*/
PERSONAL_DEATH_RECORD,
/**
* The reward is granted if the player beats their personal least time record
*/
PERSONAL_TIME_RECORD,
/**
* The reward is granted if the player beats the global least deaths record
*/
GLOBAL_DEATH_RECORD,
/**
* The reward is granted if the player beats the global least time record
*/
GLOBAL_TIME_RECORD,
;
/**
* Gets a reward condition from the given string
*
* @param condition <p>The string specifying a reward condition</p>
* @return <p>The matching reward condition, or null if not found</p>
*/
public static @Nullable RewardCondition getFromString(@NotNull String condition) {
for (RewardCondition rewardCondition : RewardCondition.values()) {
if (rewardCondition.name().equalsIgnoreCase(condition.replace("-", "_"))) {
return rewardCondition;
}
}
return null;
}
@NotNull
@Override
public Map<String, Object> serialize() {
Map<String, Object> data = new HashMap<>();
data.put("condition", this.name());
return data;
}
/**
* Deserializes a reward condition from the given data
*
* @param data <p>The data to deserialize</p>
* @return <p>The deserialized reward condition</p>
*/
@SuppressWarnings({"unused"})
public static @NotNull RewardCondition deserialize(@NotNull Map<String, Object> data) {
RewardCondition rewardCondition = getFromString(String.valueOf(data.get("condition")));
return Objects.requireNonNullElse(rewardCondition, RewardCondition.FIRST_WIN);
}
}

View File

@ -0,0 +1,70 @@
package net.knarcraft.minigames.arena.reward;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* The type of a specific reward
*/
public enum RewardType {
/**
* A command reward
*/
COMMAND(CommandReward.class),
/**
* An economy reward
*/
ECONOMY(EconomyReward.class),
/**
* An item reward
*/
ITEM(ItemReward.class),
/**
* A permission reward
*/
PERMISSION(PermissionReward.class),
;
private final Class<?> classType;
RewardType(Class<?> classType) {
this.classType = classType;
}
/**
* Gets the type of reward the given object represents
*
* @param object <p>A reward object</p>
* @return <p>The reward type of the given object, or null if not recognized</p>
*/
public static <K extends Reward> @Nullable RewardType getFromObject(@NotNull K object) {
for (RewardType rewardType : RewardType.values()) {
if (object.getClass() == rewardType.classType) {
return rewardType;
}
}
return null;
}
/**
* Gets a reward type from the given string
*
* @param condition <p>The string specifying a reward type</p>
* @return <p>The matching reward type, or null if not found</p>
*/
public static RewardType getFromString(@NotNull String condition) {
for (RewardType rewardType : RewardType.values()) {
if (rewardType.name().equalsIgnoreCase(condition.replace("-", "_"))) {
return rewardType;
}
}
return null;
}
}

View File

@ -0,0 +1,90 @@
package net.knarcraft.minigames.command;
import net.knarcraft.minigames.MiniGames;
import net.knarcraft.minigames.arena.Arena;
import net.knarcraft.minigames.arena.reward.Reward;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import net.knarcraft.minigames.config.MiniGameMessage;
import net.knarcraft.minigames.util.RewardHelper;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
/**
* The command used for setting arena rewards
*/
public class SetArenaRewardCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
@NotNull String[] arguments) {
if (!(commandSender instanceof Player player)) {
MiniGames.getInstance().getStringFormatter().displayErrorMessage(commandSender,
MiniGameMessage.ERROR_PLAYER_ONLY);
return false;
}
if (arguments.length < 4) {
return false;
}
/*
/MiniGamesReward add dropper <name> <condition> <type> [data]
/MiniGamesReward add parkour <name> <condition> <type> [data]
/MiniGamesReward clear dropper <name> <condition>
/MiniGamesReward clear parkour <name> <condition>
*/
Arena arena = null;
if (arguments[1].equalsIgnoreCase("dropper")) {
arena = MiniGames.getInstance().getDropperArenaHandler().getArena(arguments[2]);
} else if (arguments[1].equalsIgnoreCase("parkour")) {
arena = MiniGames.getInstance().getParkourArenaHandler().getArena(arguments[2]);
}
if (arena == null) {
MiniGames.getInstance().getStringFormatter().displayErrorMessage(commandSender,
MiniGameMessage.ERROR_ARENA_NOT_FOUND);
return false;
}
RewardCondition condition = RewardCondition.getFromString(arguments[3]);
if (condition == null) {
MiniGames.getInstance().getStringFormatter().displayErrorMessage(player,
MiniGameMessage.ERROR_REWARD_CONDITION_INVALID);
return false;
}
if (arguments[0].equalsIgnoreCase("clear")) {
arena.clearRewards(condition);
MiniGames.getInstance().getStringFormatter().displaySuccessMessage(player,
MiniGameMessage.SUCCESS_REWARDS_CLEARED);
return true;
}
if (!arguments[0].equalsIgnoreCase("add") || arguments.length < 5) {
return false;
}
String firstArgument = arguments.length > 5 ? arguments[5] : null;
String secondArgument = arguments.length > 6 ? arguments[6] : null;
Reward reward = RewardHelper.parseRewardInput(player, arguments[4], firstArgument, secondArgument,
Arrays.copyOfRange(arguments, 5, arguments.length));
if (reward != null) {
arena.addReward(condition, reward);
MiniGames.getInstance().getStringFormatter().displaySuccessMessage(player,
MiniGameMessage.SUCCESS_REWARD_ADDED);
return true;
} else {
return false;
}
}
}

View File

@ -0,0 +1,23 @@
package net.knarcraft.minigames.command;
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.List;
/**
* The tab completer for the reward setting command
*/
public class SetArenaRewardTabCompleter implements TabCompleter {
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
@NotNull String[] strings) {
return null;
}
}

View File

@ -135,6 +135,36 @@ public enum MiniGameMessage implements TranslatableMessage {
*/
ERROR_HARDCORE_NO_CHECKPOINTS,
/**
* The message displayed if a user specifies an invalid material
*/
ERROR_INVALID_MATERIAL,
/**
* The message displayed if a user specifies an invalid world
*/
ERROR_INVALID_WORLD,
/**
* The message displayed if a user specifies an invalid number
*/
ERROR_INVALID_NUMBER,
/**
* The message displayed if a user specifies an invalid command (for a command reward)
*/
ERROR_INVALID_COMMAND_STRING,
/**
* The message displayed if a user specified an invalid reward type
*/
ERROR_REWARD_TYPE_INVALID,
/**
* The message displayed if a user specified an invalid reward condition
*/
ERROR_REWARD_CONDITION_INVALID,
/* **************** *
* Success messages *
* **************** */
@ -253,6 +283,16 @@ public enum MiniGameMessage implements TranslatableMessage {
* The message displayed when a player is rewarded with an amount of currency
*/
SUCCESS_ECONOMY_REWARDED,
/**
* The message displayed when an arena reward has been successfully added
*/
SUCCESS_REWARD_ADDED,
/**
* The message displayed when arena rewards have been cleared
*/
SUCCESS_REWARDS_CLEARED,
;
@Override

View File

@ -9,6 +9,8 @@ import net.knarcraft.minigames.arena.dropper.DropperArenaGameMode;
import net.knarcraft.minigames.arena.dropper.DropperArenaGroup;
import net.knarcraft.minigames.arena.dropper.DropperArenaRecordsRegistry;
import net.knarcraft.minigames.arena.dropper.DropperArenaStorageKey;
import net.knarcraft.minigames.arena.reward.Reward;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import net.knarcraft.minigames.config.MiniGameMessage;
import net.knarcraft.minigames.container.SerializableMaterial;
import net.knarcraft.minigames.container.SerializableUUID;
@ -105,6 +107,7 @@ public final class DropperArenaStorageHelper {
configSection.set(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey(), arena.getPlayerVerticalVelocity());
configSection.set(DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey(), arena.getPlayerHorizontalVelocity());
configSection.set(DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
RewardStorageHelper.saveRewards(arena, configSection, DropperArenaStorageKey.REWARDS.getKey());
saveDropperArenaData(arena.getData());
}
configuration.save(dropperArenaFile);
@ -169,6 +172,9 @@ public final class DropperArenaStorageHelper {
winBlockType = new SerializableMaterial(Material.WATER);
}
Map<RewardCondition, Set<Reward>> rewards = RewardStorageHelper.loadRewards(configurationSection,
DropperArenaStorageKey.REWARDS.getKey());
// Generate new, empty arena data if not available
DropperArenaData arenaData = loadDropperArenaData(arenaId);
if (arenaData == null) {
@ -178,7 +184,7 @@ public final class DropperArenaStorageHelper {
}
return new DropperArena(arenaId, arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity,
winBlockType.getRawValue(), arenaData, MiniGames.getInstance().getDropperArenaHandler());
winBlockType.getRawValue(), rewards, arenaData, MiniGames.getInstance().getDropperArenaHandler());
}
/**

View File

@ -9,6 +9,8 @@ import net.knarcraft.minigames.arena.parkour.ParkourArenaGameMode;
import net.knarcraft.minigames.arena.parkour.ParkourArenaGroup;
import net.knarcraft.minigames.arena.parkour.ParkourArenaRecordsRegistry;
import net.knarcraft.minigames.arena.parkour.ParkourArenaStorageKey;
import net.knarcraft.minigames.arena.reward.Reward;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import net.knarcraft.minigames.config.MiniGameMessage;
import net.knarcraft.minigames.container.SerializableMaterial;
import net.knarcraft.minigames.container.SerializableUUID;
@ -108,6 +110,7 @@ public final class ParkourArenaStorageHelper {
configSection.set(ParkourArenaStorageKey.WIN_LOCATION.getKey(), arena.getWinLocation());
configSection.set(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey(), arena.getKillPlaneBlockNames());
configSection.set(ParkourArenaStorageKey.CHECKPOINTS.getKey(), arena.getCheckpoints());
RewardStorageHelper.saveRewards(arena, configSection, ParkourArenaStorageKey.REWARDS.getKey());
saveParkourArenaData(arena.getData());
}
configuration.save(parkourArenaFile);
@ -163,6 +166,9 @@ public final class ParkourArenaStorageHelper {
List<?> killPlaneBlockNames = configurationSection.getList(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey());
List<Location> checkpoints = (List<Location>) configurationSection.get(ParkourArenaStorageKey.CHECKPOINTS.getKey());
Map<RewardCondition, Set<Reward>> rewards = RewardStorageHelper.loadRewards(configurationSection,
ParkourArenaStorageKey.REWARDS.getKey());
// The arena name and spawn location must be present
if (arenaName == null || spawnLocation == null) {
MiniGames.log(Level.SEVERE, MiniGames.getInstance().getStringFormatter().replacePlaceholders(
@ -189,7 +195,8 @@ public final class ParkourArenaStorageHelper {
}
return new ParkourArena(arenaId, arenaName, spawnLocation, exitLocation, winBlockType.getRawValue(), winLocation,
(Set<String>) killPlaneBlockNames, checkpoints, arenaData, MiniGames.getInstance().getParkourArenaHandler());
(Set<String>) killPlaneBlockNames, checkpoints, rewards, arenaData,
MiniGames.getInstance().getParkourArenaHandler());
}
/**

View File

@ -0,0 +1,189 @@
package net.knarcraft.minigames.util;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.util.MaterialHelper;
import net.knarcraft.minigames.MiniGames;
import net.knarcraft.minigames.arena.reward.CommandReward;
import net.knarcraft.minigames.arena.reward.EconomyReward;
import net.knarcraft.minigames.arena.reward.ItemReward;
import net.knarcraft.minigames.arena.reward.PermissionReward;
import net.knarcraft.minigames.arena.reward.Reward;
import net.knarcraft.minigames.arena.reward.RewardType;
import net.knarcraft.minigames.config.MiniGameMessage;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.UUID;
/**
* A helopr class for getting the reward specified in user input
*/
public final class RewardHelper {
private RewardHelper() {
}
/**
* Grants the given rewards to the given player
*
* @param player <p>The player to reward</p>
* @param rewards <p>The rewards to give</p>
*/
public static void grantRewards(@NotNull Player player, @NotNull Collection<Reward> rewards) {
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
for (Reward reward : rewards) {
boolean granted = reward.grant(player);
if (granted) {
stringFormatter.displaySuccessMessage(player, reward.getGrantMessage());
}
}
}
/**
* Parses input describing a reward
*
* @param player <p>The player that specified the reward</p>
* @param typeString <p>The string given to specify the reward type</p>
* @param firstArgument <p>The first reward argument given by the player, or null</p>
* @param secondArgument <p>The second reward argument given by the player, or null</p>
* @param allArguments <p>A list of all the reward arguments, in case the reward is a command reward</p>
* @return <p>The parsed reward, or null if some input was invalid</p>
*/
public static @Nullable Reward parseRewardInput(@NotNull Player player,
@NotNull String typeString,
@Nullable String firstArgument,
@Nullable String secondArgument,
@NotNull String[] allArguments) {
RewardType rewardType = RewardType.getFromString(typeString);
if (rewardType == null) {
MiniGames.getInstance().getStringFormatter().displayErrorMessage(player,
MiniGameMessage.ERROR_REWARD_TYPE_INVALID);
return null;
}
if (rewardType != RewardType.ITEM && firstArgument == null) {
return null;
}
try {
return switch (rewardType) {
case COMMAND -> new CommandReward(getArrayAsString(allArguments));
case ECONOMY -> new EconomyReward(getDouble(firstArgument));
case PERMISSION -> new PermissionReward(getWorld(secondArgument), firstArgument);
case ITEM -> new ItemReward(getItem(player, firstArgument, secondArgument));
};
} catch (IllegalArgumentException exception) {
MiniGames.getInstance().getStringFormatter().displayErrorMessage(player, exception.getMessage());
return null;
}
}
/**
* Gets a double from the given input
*
* @param input <p>The input representing a double</p>
* @return <p>The double specified</p>
* @throws IllegalArgumentException <p>If the input is not a number or is not positive</p>
*/
private static double getDouble(@NotNull String input) throws IllegalArgumentException {
IllegalArgumentException invalidException = new IllegalArgumentException(
MiniGames.getInstance().getTranslator().getTranslatedMessage(MiniGameMessage.ERROR_INVALID_NUMBER));
try {
double number = Double.parseDouble(input);
if (number <= 0) {
throw invalidException;
}
return number;
} catch (NumberFormatException exception) {
throw invalidException;
}
}
/**
* Gets the world specified in the given identifier
*
* @param worldIdentifier <p>A world UUID or name</p>
* @return <p>The world, or null if no such world exists</p>
*/
private static @Nullable World getWorld(@Nullable String worldIdentifier) {
if (worldIdentifier == null || worldIdentifier.isBlank()) {
return null;
}
World world;
try {
UUID worldId = UUID.fromString(worldIdentifier);
world = Bukkit.getWorld(worldId);
} catch (IllegalArgumentException exception) {
world = Bukkit.getWorld(worldIdentifier);
}
if (world != null) {
return world;
} else {
throw new IllegalArgumentException(MiniGames.getInstance().getTranslator().getTranslatedMessage(
MiniGameMessage.ERROR_INVALID_WORLD));
}
}
/**
* Gets an item stack according to the given input
*
* @param player <p>The player that caused this method to execute</p>
* @param argument1 <p>The first argument given by the player, or null</p>
* @param argument2 <p>The second argument given by the player, or null</p>
* @return <p>An item stack as described, or the player's held item</p>
* @throws IllegalArgumentException <p>If an invalid material was specified</p>
*/
private static @NotNull ItemStack getItem(@NotNull Player player, @Nullable String argument1,
@Nullable String argument2) throws IllegalArgumentException {
if (argument1 != null) {
Material material = MaterialHelper.loadMaterialString(argument1, MiniGames.getInstance().getLogger());
int amount;
try {
if (argument2 != null) {
amount = Integer.parseInt(argument2);
} else {
amount = 1;
}
} catch (NumberFormatException exception) {
amount = 1;
}
if (material == null || material.isAir()) {
throw new IllegalArgumentException(MiniGames.getInstance().getTranslator().getTranslatedMessage(
MiniGameMessage.ERROR_INVALID_MATERIAL));
}
return new ItemStack(material, amount);
} else {
ItemStack inHand = player.getInventory().getItemInMainHand();
if (!inHand.getType().isAir()) {
return inHand;
} else {
throw new IllegalArgumentException(MiniGames.getInstance().getTranslator().getTranslatedMessage(
MiniGameMessage.ERROR_INVALID_MATERIAL));
}
}
}
/**
* Gets the string array as a space separated string
*
* @param array <p>The array to get as a string</p>
* @return <p>The array as a string</p>
*/
private static String getArrayAsString(@NotNull String[] array) {
String output = String.join(" ", array);
if (output.isBlank()) {
throw new IllegalArgumentException(MiniGames.getInstance().getTranslator().getTranslatedMessage(
MiniGameMessage.ERROR_INVALID_COMMAND_STRING));
} else {
return output;
}
}
}

View File

@ -0,0 +1,67 @@
package net.knarcraft.minigames.util;
import net.knarcraft.minigames.arena.Arena;
import net.knarcraft.minigames.arena.reward.Reward;
import net.knarcraft.minigames.arena.reward.RewardCondition;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A helper class for loading and storing rewards
*/
public class RewardStorageHelper {
/**
* Loads the rewards contained at the given path
*
* @param configurationSection <p>The configuration section containing the reward</p>
* @param key <p>The section key to search</p>
* @return <p>The loaded rewards</p>
*/
public static Map<RewardCondition, Set<Reward>> loadRewards(@NotNull ConfigurationSection configurationSection,
@NotNull String key) {
Map<RewardCondition, Set<Reward>> rewards = new HashMap<>();
if (!configurationSection.contains(key)) {
return rewards;
}
for (RewardCondition condition : RewardCondition.values()) {
String section = key + "." + condition.name();
if (!configurationSection.contains(section)) {
continue;
}
Set<Reward> rewardSet = new HashSet<>();
List<?> rewardList = configurationSection.getList(section, new ArrayList<>());
for (Object object : rewardList) {
if (object instanceof Reward reward) {
rewardSet.add(reward);
}
}
rewards.put(condition, rewardSet);
}
return rewards;
}
/**
* Saves rewards for the given arena
*
* @param arena <p>The arena to save rewards for</p>
* @param configurationSection <p>The configuration section to save the rewards at</p>
* @param key <p>The section key to save at</p>
*/
public static void saveRewards(@NotNull Arena arena, @NotNull ConfigurationSection configurationSection,
@NotNull String key) {
for (RewardCondition condition : RewardCondition.values()) {
configurationSection.set(key + "." + condition.name(),
new ArrayList<>(arena.getRewards(condition)));
}
}
}

View File

@ -28,6 +28,12 @@ commands:
- mmenu
usage: /<command>
description: Used to display an actions menu while in an arena
miniGamesReward:
aliases:
- mreward
usage: /<command> <add|clear> <dropper|parkour> <name> <condition> <type> [value] [value] ...
description: Used to set rewards for arenas
permission: minigames.edit
dropperGroupSet:
aliases:
- dgset

View File

@ -23,6 +23,12 @@ en:
ERROR_SWAP_DIFFERENT_GROUPS: "You cannot swap arenas in different groups!"
ERROR_ILLEGAL_COMMAND: "You cannot use that command while in an arena!"
ERROR_HARDCORE_NO_CHECKPOINTS: "This arena cannot be played in hardcore mode as it has no checkpoints!"
ERROR_INVALID_MATERIAL: "You specified an invalid material"
ERROR_INVALID_WORLD: "You specified an invalid world"
ERROR_INVALID_NUMBER: "You specified an invalid number"
ERROR_INVALID_COMMAND_STRING: "You specified an invalid command. Make sure you don't add a slash in front of the command definition."
ERROR_REWARD_TYPE_INVALID: "You have specified an invalid reward type"
ERROR_REWARD_CONDITION_INVALID: "You have specified an invalid reward condition"
SUCCESS_ARENA_GROUP_UPDATED: "The arena's group has been updated"
SUCCESS_PLUGIN_RELOADED: "Plugin reloaded!"
SUCCESS_ARENA_CREATED: "The arena was successfully created!"
@ -45,4 +51,6 @@ en:
SUCCESS_PERMISSION_REWARDED: "You have been granted the permission: {permission}"
SUCCESS_PERMISSION_REWARDED_WORLD: "You have been granted the permission: {permission} in world: {world}"
SUCCESS_COMMAND_REWARDED: "The command `{command}` has been run as your reward."
SUCCESS_ECONOMY_REWARDED: "You have been granted {currency}"
SUCCESS_ECONOMY_REWARDED: "You have been granted {currency}"
SUCCESS_REWARD_ADDED: "The reward was added."
SUCCESS_REWARDS_CLEARED: "Rewards cleared."