diff --git a/README.md b/README.md index b2e76be..d0a579c 100644 --- a/README.md +++ b/README.md @@ -314,13 +314,23 @@ format for the built-in placeholders is as follows: | Variable | Values | Description | |-----------------|----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------| | gameMode | dropper / parkour | A selection of which game-mode you are getting a record for | -| players_playing | | This must be as-is. It's a selector in case placeholders are added for more than playing players. | +| players_playing | | This must be as-is. | | gameModeType | default / inverted / random / hardcore / all | Selects the game-mode to get the players for. Note that "all" combines players for all game-modes. | | identifierType | arena / group | The type of thing the following identifier points to (an arena or an arena group). | | identifier | ? | An identifier (the name or UUID) for an arena or a group (whichever was chosen as identifierType). | | playerInfoType | player / count | The type of info to get. Player gets the player name, and count gets the total number of players. | | playerNumber | 1 / 2 / 3 / ... | The player number to get the name of. Players are numbered after their sorted names. This argument is not used when getting the player count. | +### Max Players Placeholder + +`%gameMode_players_max_arenaName%` + +| Variable | Values | Description | +|-----------------|-------------------|-------------------------------------------------------------| +| gameMode | dropper / parkour | A selection of which game-mode you are getting a record for | +| players_maximum | | This must be as-is. | +| arenaName | ? | An identifier (the name or UUID) for an arena. | + ## Notes about material tags Where a list of material is allowed, this plugin supports using material tags that specify a set of blocks. This makes diff --git a/src/main/java/net/knarcraft/minigames/arena/Arena.java b/src/main/java/net/knarcraft/minigames/arena/Arena.java index 6a3c4ab..e5b7083 100644 --- a/src/main/java/net/knarcraft/minigames/arena/Arena.java +++ b/src/main/java/net/knarcraft/minigames/arena/Arena.java @@ -3,6 +3,7 @@ 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.Material; import org.bukkit.block.Block; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -13,6 +14,7 @@ import java.util.UUID; /** * An interface describing an arena */ +@SuppressWarnings("unused") public interface Arena { /** @@ -23,6 +25,14 @@ public interface Arena { @NotNull String getArenaName(); + /** + * Sets the name of this arena + * + * @param arenaName

The new name

+ * @return

True if successfully updated

+ */ + boolean setName(@NotNull String arenaName); + /** * Gets the data stored for this arena * @@ -61,6 +71,24 @@ public interface Arena { */ boolean saveData(); + /** + * Gets the type of block a player has to hit to win this arena + * + * @return

The kind of block players must hit

+ */ + @NotNull + Material getWinBlockType(); + + /** + * Sets the material of the win block type + * + *

The win block type is the type of block a player must hit to win in this arena

+ * + * @param material

The material to set for the win block type

+ * @return

True if successfully updated

+ */ + boolean setWinBlockType(@NotNull Material material); + /** * Gets whether standing on the given block should cause a win * @@ -92,6 +120,14 @@ public interface Arena { @NotNull Location getSpawnLocation(); + /** + * Sets the spawn location for this arena + * + * @param newLocation

The new spawn location

+ * @return

True if successfully updated

+ */ + boolean setSpawnLocation(@Nullable Location newLocation); + /** * Gets this arena's exit location * @@ -100,6 +136,14 @@ public interface Arena { @Nullable Location getExitLocation(); + /** + * Sets the exit location for this arena + * + * @param newLocation

The new exit location

+ * @return

True if successfully updated

+ */ + boolean setExitLocation(@Nullable Location newLocation); + /** * Adds a reward to this arena * @@ -124,4 +168,18 @@ public interface Arena { @NotNull Set getRewards(RewardCondition rewardCondition); + /** + * Gets the maximum amount of players that can join this arena at once + * + * @return

The maximum amount of players

+ */ + int getMaxPlayers(); + + /** + * Sets the maximum amount of players that can join this arena at once + * + * @param newValue

The new maximum amount of players

+ */ + boolean setMaxPlayers(int newValue); + } diff --git a/src/main/java/net/knarcraft/minigames/arena/ArenaHandler.java b/src/main/java/net/knarcraft/minigames/arena/ArenaHandler.java index 6c37279..f55338b 100644 --- a/src/main/java/net/knarcraft/minigames/arena/ArenaHandler.java +++ b/src/main/java/net/knarcraft/minigames/arena/ArenaHandler.java @@ -151,7 +151,11 @@ public abstract class ArenaHandler> * @return

The arena with the given name, or null if not found

*/ public @Nullable K getArena(@NotNull String arenaName) { - return this.arenas.get(this.arenaNameLookup.get(StringSanitizer.sanitizeArenaName(arenaName))); + try { + return this.arenas.get(UUID.fromString(arenaName)); + } catch (IllegalArgumentException exception) { + return this.arenas.get(this.arenaNameLookup.get(StringSanitizer.sanitizeArenaName(arenaName))); + } } /** diff --git a/src/main/java/net/knarcraft/minigames/arena/EditablePropertyType.java b/src/main/java/net/knarcraft/minigames/arena/EditablePropertyType.java index f919176..f8e9369 100644 --- a/src/main/java/net/knarcraft/minigames/arena/EditablePropertyType.java +++ b/src/main/java/net/knarcraft/minigames/arena/EditablePropertyType.java @@ -45,4 +45,9 @@ public enum EditablePropertyType { */ DOUBLE, + /** + * The property is an integer with no particular restrictions + */ + INTEGER, + } diff --git a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java index 32d245e..5ad86de 100644 --- a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java +++ b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java @@ -63,6 +63,11 @@ public class DropperArena implements Arena { */ private float playerHorizontalVelocity; + /** + * The maximum amount of players able to join this arena at any time + */ + private int maxPlayers = -1; + /** * The material of the block players have to hit to win this dropper arena */ @@ -89,14 +94,16 @@ public class DropperArena implements Arena { * @param playerVerticalVelocity

The velocity to use for players' vertical velocity

* @param playerHorizontalVelocity

The velocity to use for players' horizontal velocity (-1 to 1)

* @param winBlockType

The material of the block players have to hit to win this dropper arena

+ * @param maxPlayers

The maximum amount of players able to join this arena at once

* @param rewards

The rewards given by this arena

* @param dropperArenaData

The arena data keeping track of which players have done what in this arena

* @param arenaHandler

The arena handler used for saving any changes

*/ public DropperArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation, @Nullable Location exitLocation, double playerVerticalVelocity, float playerHorizontalVelocity, - @NotNull Material winBlockType, @NotNull Map> rewards, - @NotNull DropperArenaData dropperArenaData, @NotNull DropperArenaHandler arenaHandler) { + @NotNull Material winBlockType, int maxPlayers, + @NotNull Map> rewards, @NotNull DropperArenaData dropperArenaData, + @NotNull DropperArenaHandler arenaHandler) { this.arenaId = arenaId; this.arenaName = arenaName; this.spawnLocation = spawnLocation; @@ -107,6 +114,7 @@ public class DropperArena implements Arena { this.dropperArenaData = dropperArenaData; this.dropperArenaHandler = arenaHandler; this.rewards = rewards; + this.maxPlayers = maxPlayers; } /** @@ -186,44 +194,27 @@ public class DropperArena implements Arena { } } - /** - * Gets the vertical velocity for players in this arena - * - *

This velocity will be set on the negative y-axis, for all players in this arena.

- * - * @return

Players' velocity in this arena

- */ - public double getPlayerVerticalVelocity() { - return this.playerVerticalVelocity; + @Override + public int getMaxPlayers() { + return this.maxPlayers; } - - /** - * Gets the horizontal for players in this arena - * - *

This will be used for players' fly-speed in this arena

- * - * @return

Players' velocity in this arena

- */ - public float getPlayerHorizontalVelocity() { - return this.playerHorizontalVelocity; + @Override + public boolean setMaxPlayers(int newValue) { + this.maxPlayers = newValue; + this.saveArena(); + return true; } - /** - * Gets the type of block a player has to hit to win this arena - * - * @return

The kind of block players must hit

- */ - public @NotNull Material getWinBlockType() { + @Override + @NotNull + public Material getWinBlockType() { return this.winBlockType; } - /** - * Gets this arena's sanitized name - * - * @return

This arena's sanitized name

- */ - public @NotNull String getArenaNameSanitized() { + @Override + @NotNull + public String getArenaNameSanitized() { return StringSanitizer.sanitizeArenaName(this.getArenaName()); } @@ -257,12 +248,7 @@ public class DropperArena implements Arena { return winBlockType.isSolid(); } - /** - * Sets the spawn location for this arena - * - * @param newLocation

The new spawn location

- * @return

True if successfully updated

- */ + @Override public boolean setSpawnLocation(@Nullable Location newLocation) { if (isInvalid(newLocation)) { return false; @@ -273,12 +259,7 @@ public class DropperArena implements Arena { } } - /** - * Sets the exit location for this arena - * - * @param newLocation

The new exit location

- * @return

True if successfully updated

- */ + @Override public boolean setExitLocation(@Nullable Location newLocation) { if (isInvalid(newLocation)) { return false; @@ -289,12 +270,7 @@ public class DropperArena implements Arena { } } - /** - * Sets the name of this arena - * - * @param arenaName

The new name

- * @return

True if successfully updated

- */ + @Override public boolean setName(@NotNull String arenaName) { if (!arenaName.isBlank()) { String oldName = this.getArenaNameSanitized(); @@ -309,13 +285,29 @@ public class DropperArena implements Arena { } /** - * Sets the material of the win block type + * Gets the vertical velocity for players in this arena * - *

The win block type is the type of block a player must hit to win in this arena

+ *

This velocity will be set on the negative y-axis, for all players in this arena.

* - * @param material

The material to set for the win block type

- * @return

True if successfully updated

+ * @return

Players' velocity in this arena

*/ + public double getPlayerVerticalVelocity() { + return this.playerVerticalVelocity; + } + + + /** + * Gets the horizontal for players in this arena + * + *

This will be used for players' fly-speed in this arena

+ * + * @return

Players' velocity in this arena

+ */ + public float getPlayerHorizontalVelocity() { + return this.playerHorizontalVelocity; + } + + @Override public boolean setWinBlockType(@NotNull Material material) { if (material.isAir() || !material.isBlock()) { return false; diff --git a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaEditableProperty.java b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaEditableProperty.java index 8dc6b5e..082835b 100644 --- a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaEditableProperty.java +++ b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaEditableProperty.java @@ -45,6 +45,12 @@ public enum DropperArenaEditableProperty { */ WIN_BLOCK_TYPE("winBlockType", (arena) -> arena.getWinBlockType().toString(), EditablePropertyType.BLOCK_TYPE), + + /** + * The arena's max players + */ + MAX_PLAYERS("maxPlayers", (arena) -> String.valueOf(arena.getMaxPlayers()), + EditablePropertyType.INTEGER), ; private final @NotNull String argumentString; diff --git a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaStorageKey.java b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaStorageKey.java index b79db3e..566a43f 100644 --- a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaStorageKey.java +++ b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArenaStorageKey.java @@ -51,6 +51,11 @@ public enum DropperArenaStorageKey { * The key for this arena's rewards */ REWARDS("rewards"), + + /** + * The key for this arena's maximum players + */ + MAX_PLAYERS("maxPlayers"), ; private final @NotNull String key; diff --git a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java index 74a432f..785441a 100644 --- a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java +++ b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java @@ -84,6 +84,11 @@ public class ParkourArena implements Arena { */ private @Nullable Set obstacleBlocks; + /** + * The maximum amount of players able to join this arena at any time + */ + private int maxPlayers; + /** * The checkpoints for this arena. Entering a checkpoint overrides the player's spawn location. */ @@ -110,6 +115,7 @@ public class ParkourArena implements Arena { * @param killPlaneBlockNames

The names of the types of blocks that trigger a loss when stepped on

* @param obstacleBlockNames

The names of the types of blocks that trigger a loss when touched

* @param checkpoints

The checkpoints set for this arena

+ * @param maxPlayers

The maximum amount of players able to join this arena at once

* @param rewards

The rewards given by this arena

* @param parkourArenaData

The arena data keeping track of which players have done what in this arena

* @param arenaHandler

The arena handler used for saving any changes

@@ -117,7 +123,7 @@ public class ParkourArena implements Arena { public ParkourArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation, @Nullable Location exitLocation, @NotNull Material winBlockType, @Nullable Location winLocation, @Nullable Set killPlaneBlockNames, @Nullable Set obstacleBlockNames, - @NotNull List checkpoints, + @NotNull List checkpoints, int maxPlayers, @NotNull Map> rewards, @NotNull ParkourArenaData parkourArenaData, @NotNull ParkourArenaHandler arenaHandler) { this.arenaId = arenaId; @@ -136,6 +142,7 @@ public class ParkourArena implements Arena { this.parkourArenaData = parkourArenaData; this.parkourArenaHandler = arenaHandler; this.rewards = rewards; + this.maxPlayers = maxPlayers; } /** @@ -167,6 +174,7 @@ public class ParkourArena implements Arena { this.obstacleBlocks = null; this.checkpoints = new ArrayList<>(); this.parkourArenaHandler = arenaHandler; + this.maxPlayers = -1; } @Override @@ -216,12 +224,25 @@ public class ParkourArena implements Arena { } } - /** - * Gets the type of block a player has to hit to win this arena - * - * @return

The kind of block players must hit

- */ - public @NotNull Material getWinBlockType() { + @Override + public int getMaxPlayers() { + return this.maxPlayers; + } + + @Override + public boolean setMaxPlayers(int newValue) { + if (newValue < -1) { + return false; + } + + this.maxPlayers = newValue; + this.saveArena(); + return true; + } + + @Override + @NotNull + public Material getWinBlockType() { return this.winBlockType; } @@ -302,12 +323,9 @@ public class ParkourArena implements Arena { return this.checkpoints.isEmpty(); } - /** - * Gets this arena's sanitized name - * - * @return

This arena's sanitized name

- */ - public @NotNull String getArenaNameSanitized() { + @Override + @NotNull + public String getArenaNameSanitized() { return StringSanitizer.sanitizeArenaName(this.getArenaName()); } @@ -350,12 +368,7 @@ public class ParkourArena implements Arena { this.winBlockType.isSolid(); } - /** - * Sets the spawn location for this arena - * - * @param newLocation

The new spawn location

- * @return

True if successfully updated

- */ + @Override public boolean setSpawnLocation(@Nullable Location newLocation) { if (isInvalid(newLocation)) { return false; @@ -366,12 +379,7 @@ public class ParkourArena implements Arena { } } - /** - * Sets the exit location for this arena - * - * @param newLocation

The new exit location

- * @return

True if successfully updated

- */ + @Override public boolean setExitLocation(@Nullable Location newLocation) { if (isInvalid(newLocation)) { return false; @@ -382,12 +390,7 @@ public class ParkourArena implements Arena { } } - /** - * Sets the name of this arena - * - * @param arenaName

The new name

- * @return

True if successfully updated

- */ + @Override public boolean setName(@NotNull String arenaName) { if (!arenaName.isBlank()) { String oldName = this.getArenaNameSanitized(); @@ -401,14 +404,7 @@ public class ParkourArena implements Arena { } } - /** - * Sets the material of the win block type - * - *

The win block type is the type of block a player must hit to win in this arena

- * - * @param material

The material to set for the win block type

- * @return

True if successfully updated

- */ + @Override public boolean setWinBlockType(@NotNull Material material) { if (material.isAir() || !material.isBlock()) { return false; diff --git a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaEditableProperty.java b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaEditableProperty.java index 247727e..2f068e3 100644 --- a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaEditableProperty.java +++ b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaEditableProperty.java @@ -69,6 +69,11 @@ public enum ParkourArenaEditableProperty { OBSTACLE_BLOCKS("obstacleBlocks", (arena) -> String.valueOf(arena.getObstacleBlockNames()), EditablePropertyType.MATERIAL_LIST), + /** + * The arena's max players + */ + MAX_PLAYERS("maxPlayers", (arena) -> String.valueOf(arena.getMaxPlayers()), + EditablePropertyType.INTEGER), ; private final @NotNull String argumentString; diff --git a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaGameMode.java b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaGameMode.java index 7a5240c..1f0aceb 100644 --- a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaGameMode.java +++ b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaGameMode.java @@ -29,7 +29,7 @@ public enum ParkourArenaGameMode implements ConfigurationSerializable, ArenaGame * @param gameMode

The game-mode string to match

* @return

The specified arena game-mode

*/ - public static @NotNull ParkourArenaGameMode matchGamemode(@NotNull String gameMode) { + public static @NotNull ParkourArenaGameMode matchGameMode(@NotNull String gameMode) { try { return ParkourArenaGameMode.valueOf(gameMode.toUpperCase()); } catch (IllegalArgumentException exception) { diff --git a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaStorageKey.java b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaStorageKey.java index 9923ebf..bc40581 100644 --- a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaStorageKey.java +++ b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaStorageKey.java @@ -61,6 +61,11 @@ public enum ParkourArenaStorageKey { * The key for this arena's rewards */ REWARDS("rewards"), + + /** + * The key for this arena's maximum players + */ + MAX_PLAYERS("maxPlayers"), ; private final @NotNull String key; diff --git a/src/main/java/net/knarcraft/minigames/command/EditArenaCommand.java b/src/main/java/net/knarcraft/minigames/command/EditArenaCommand.java new file mode 100644 index 0000000..cbd2861 --- /dev/null +++ b/src/main/java/net/knarcraft/minigames/command/EditArenaCommand.java @@ -0,0 +1,113 @@ +package net.knarcraft.minigames.command; + +import net.knarcraft.minigames.config.DropperConfiguration; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.command.CommandExecutor; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +/** + * An abstract arena edit command, implementing input validation + */ +public abstract class EditArenaCommand implements CommandExecutor { + + private final DropperConfiguration configuration; + + /** + * Instantiates a new edit arena command + * + * @param configuration

The configuration to use

+ */ + public EditArenaCommand(DropperConfiguration configuration) { + this.configuration = configuration; + } + + /** + * Parses the specified max players + * + * @param maxPlayers

The max players string to parse

+ * @return

The parsed value, or -1 if not parse-able

+ */ + protected int parseMaxPlayers(@NotNull String maxPlayers) { + try { + return Integer.parseInt(maxPlayers); + } catch (NumberFormatException exception) { + return -1; + } + } + + /** + * Sanitizes the player's specified vertical velocity + * + * @param velocityString

The string to parse into a velocity

+ * @return

The parsed velocity, defaulting to 0.5 if not parse-able

+ */ + protected double sanitizeVerticalVelocity(@NotNull String velocityString) { + // Vertical velocity should not be negative, as it would make the player go upwards. There is technically not a + // max speed limit, but setting it too high makes the arena unplayable + double velocity; + try { + velocity = Double.parseDouble(velocityString); + } catch (NumberFormatException exception) { + velocity = configuration.getVerticalVelocity(); + } + + // Require at least speed of 0.001, and at most 75 blocks/s + return Math.min(Math.max(velocity, 0.001), 75); + } + + /** + * Sanitizes the user's specified horizontal velocity + * + * @param velocityString

The string to parse into a velocity

+ * @return

The parsed velocity, defaulting to 1 if not parse-able

+ */ + protected float sanitizeHorizontalVelocity(@NotNull String velocityString) { + // Horizontal velocity is valid between -1 and 1, where negative values swaps directions + float velocity; + try { + velocity = Float.parseFloat(velocityString); + } catch (NumberFormatException exception) { + velocity = configuration.getHorizontalVelocity(); + } + + // If outside bonds, choose the most extreme value + return Math.min(Math.max(0.1f, velocity), 1); + } + + /** + * Parses the given location string + * + * @param player

The player changing a location

+ * @param locationString

The location string to parse

+ * @return

The parsed location, or the player's location if not parse-able

+ */ + protected @NotNull Location parseLocation(Player player, String locationString) { + if ((locationString.trim() + ",").matches("([0-9]+.?[0-9]*,){3}")) { + String[] parts = locationString.split(","); + Location newLocation = player.getLocation().clone(); + newLocation.setX(Double.parseDouble(parts[0].trim())); + newLocation.setY(Double.parseDouble(parts[1].trim())); + newLocation.setZ(Double.parseDouble(parts[2].trim())); + return newLocation; + } else { + return player.getLocation().clone(); + } + } + + /** + * Parses the given material name + * + * @param materialName

The material name to parse

+ * @return

The parsed material, or AIR if not valid

+ */ + protected @NotNull Material parseMaterial(String materialName) { + Material material = Material.matchMaterial(materialName); + if (material == null) { + material = Material.AIR; + } + return material; + } + +} diff --git a/src/main/java/net/knarcraft/minigames/command/SetArenaRewardCommand.java b/src/main/java/net/knarcraft/minigames/command/SetArenaRewardCommand.java index 10fe008..3350ba9 100644 --- a/src/main/java/net/knarcraft/minigames/command/SetArenaRewardCommand.java +++ b/src/main/java/net/knarcraft/minigames/command/SetArenaRewardCommand.java @@ -5,6 +5,7 @@ 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.InputValidationHelper; import net.knarcraft.minigames.util.RewardHelper; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -60,7 +61,7 @@ public class SetArenaRewardCommand implements CommandExecutor { return false; } - if (arguments[0].equalsIgnoreCase("clear")) { + if (InputValidationHelper.isEmptyValue(arguments[0])) { arena.clearRewards(condition); MiniGames.getInstance().getStringFormatter().displaySuccessMessage(player, MiniGameMessage.SUCCESS_REWARDS_CLEARED); diff --git a/src/main/java/net/knarcraft/minigames/command/SetArenaRewardTabCompleter.java b/src/main/java/net/knarcraft/minigames/command/SetArenaRewardTabCompleter.java index e96a50a..545abdc 100644 --- a/src/main/java/net/knarcraft/minigames/command/SetArenaRewardTabCompleter.java +++ b/src/main/java/net/knarcraft/minigames/command/SetArenaRewardTabCompleter.java @@ -6,6 +6,7 @@ import net.knarcraft.minigames.MiniGames; import net.knarcraft.minigames.arena.Arena; import net.knarcraft.minigames.arena.reward.RewardCondition; import net.knarcraft.minigames.arena.reward.RewardType; +import net.knarcraft.minigames.util.InputValidationHelper; import net.knarcraft.minigames.util.TabCompleteHelper; import org.bukkit.Material; import org.bukkit.command.Command; @@ -40,7 +41,7 @@ public class SetArenaRewardTabCompleter implements TabCompleter { } if (arguments.length >= 2) { // If the first argument is invalid, stop further tab completion - if (!arguments[0].equalsIgnoreCase("add") && !arguments[0].equalsIgnoreCase("clear")) { + if (!arguments[0].equalsIgnoreCase("add") && !InputValidationHelper.isEmptyValue(arguments[0])) { return new ArrayList<>(); } } @@ -73,8 +74,7 @@ public class SetArenaRewardTabCompleter implements TabCompleter { } if (arguments.length >= 5) { // If the condition is invalid, or it's the clear action, stop tab-completion - if (RewardCondition.getFromString(arguments[3]) == null || - arguments[0].equalsIgnoreCase("clear")) { + if (RewardCondition.getFromString(arguments[3]) == null || InputValidationHelper.isEmptyValue(arguments[0])) { return new ArrayList<>(); } } diff --git a/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSetCommand.java b/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSetCommand.java index db67695..3f007c1 100644 --- a/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSetCommand.java +++ b/src/main/java/net/knarcraft/minigames/command/dropper/DropperGroupSetCommand.java @@ -5,6 +5,7 @@ import net.knarcraft.minigames.arena.dropper.DropperArena; import net.knarcraft.minigames.arena.dropper.DropperArenaGroup; import net.knarcraft.minigames.arena.dropper.DropperArenaHandler; import net.knarcraft.minigames.config.MiniGameMessage; +import net.knarcraft.minigames.util.InputValidationHelper; import net.knarcraft.minigames.util.StringSanitizer; import net.knarcraft.minigames.util.TabCompleteHelper; import org.bukkit.command.Command; @@ -46,7 +47,7 @@ public class DropperGroupSetCommand implements TabExecutor { } DropperArenaGroup arenaGroup; - if (groupName.equalsIgnoreCase("null") || groupName.equalsIgnoreCase("none")) { + if (InputValidationHelper.isEmptyValue(groupName)) { arenaGroup = null; } else { arenaGroup = arenaHandler.getGroup(groupName); diff --git a/src/main/java/net/knarcraft/minigames/command/dropper/EditDropperArenaCommand.java b/src/main/java/net/knarcraft/minigames/command/dropper/EditDropperArenaCommand.java index 0172cda..2a43451 100644 --- a/src/main/java/net/knarcraft/minigames/command/dropper/EditDropperArenaCommand.java +++ b/src/main/java/net/knarcraft/minigames/command/dropper/EditDropperArenaCommand.java @@ -4,12 +4,10 @@ import net.knarcraft.knarlib.formatting.StringFormatter; import net.knarcraft.minigames.MiniGames; import net.knarcraft.minigames.arena.dropper.DropperArena; import net.knarcraft.minigames.arena.dropper.DropperArenaEditableProperty; +import net.knarcraft.minigames.command.EditArenaCommand; import net.knarcraft.minigames.config.DropperConfiguration; import net.knarcraft.minigames.config.MiniGameMessage; -import org.bukkit.Location; -import org.bukkit.Material; 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; @@ -17,9 +15,7 @@ import org.jetbrains.annotations.NotNull; /** * The command for editing an existing dropper arena */ -public class EditDropperArenaCommand implements CommandExecutor { - - private final DropperConfiguration configuration; +public class EditDropperArenaCommand extends EditArenaCommand { /** * Instantiates a new edit arena command @@ -27,7 +23,7 @@ public class EditDropperArenaCommand implements CommandExecutor { * @param configuration

The configuration to use

*/ public EditDropperArenaCommand(DropperConfiguration configuration) { - this.configuration = configuration; + super(configuration); } @Override @@ -93,80 +89,8 @@ public class EditDropperArenaCommand implements CommandExecutor { case SPAWN_LOCATION -> arena.setSpawnLocation(parseLocation(player, value)); case NAME -> arena.setName(value); case EXIT_LOCATION -> arena.setExitLocation(parseLocation(player, value)); + case MAX_PLAYERS -> arena.setMaxPlayers(parseMaxPlayers(value)); }; } - /** - * Sanitizes the player's specified vertical velocity - * - * @param velocityString

The string to parse into a velocity

- * @return

The parsed velocity, defaulting to 0.5 if not parse-able

- */ - private double sanitizeVerticalVelocity(@NotNull String velocityString) { - // Vertical velocity should not be negative, as it would make the player go upwards. There is technically not a - // max speed limit, but setting it too high makes the arena unplayable - double velocity; - try { - velocity = Double.parseDouble(velocityString); - } catch (NumberFormatException exception) { - velocity = configuration.getVerticalVelocity(); - } - - // Require at least speed of 0.001, and at most 75 blocks/s - return Math.min(Math.max(velocity, 0.001), 75); - } - - /** - * Sanitizes the user's specified horizontal velocity - * - * @param velocityString

The string to parse into a velocity

- * @return

The parsed velocity, defaulting to 1 if not parse-able

- */ - private float sanitizeHorizontalVelocity(@NotNull String velocityString) { - // Horizontal velocity is valid between -1 and 1, where negative values swaps directions - float velocity; - try { - velocity = Float.parseFloat(velocityString); - } catch (NumberFormatException exception) { - velocity = configuration.getHorizontalVelocity(); - } - - // If outside bonds, choose the most extreme value - return Math.min(Math.max(0.1f, velocity), 1); - } - - /** - * Parses the given location string - * - * @param player

The player changing a location

- * @param locationString

The location string to parse

- * @return

The parsed location, or the player's location if not parse-able

- */ - private @NotNull Location parseLocation(Player player, String locationString) { - if ((locationString.trim() + ",").matches("([0-9]+.?[0-9]*,){3}")) { - String[] parts = locationString.split(","); - Location newLocation = player.getLocation().clone(); - newLocation.setX(Double.parseDouble(parts[0].trim())); - newLocation.setY(Double.parseDouble(parts[1].trim())); - newLocation.setZ(Double.parseDouble(parts[2].trim())); - return newLocation; - } else { - return player.getLocation().clone(); - } - } - - /** - * Parses the given material name - * - * @param materialName

The material name to parse

- * @return

The parsed material, or AIR if not valid

- */ - private @NotNull Material parseMaterial(String materialName) { - Material material = Material.matchMaterial(materialName); - if (material == null) { - material = Material.AIR; - } - return material; - } - } diff --git a/src/main/java/net/knarcraft/minigames/command/dropper/JoinDropperArenaCommand.java b/src/main/java/net/knarcraft/minigames/command/dropper/JoinDropperArenaCommand.java index 58b920e..b18c87f 100644 --- a/src/main/java/net/knarcraft/minigames/command/dropper/JoinDropperArenaCommand.java +++ b/src/main/java/net/knarcraft/minigames/command/dropper/JoinDropperArenaCommand.java @@ -60,6 +60,13 @@ public class JoinDropperArenaCommand implements CommandExecutor { return true; } + // Deny joining full arenas + int playingNow = MiniGames.getInstance().getDropperArenaPlayerRegistry().getPlayingPlayers(specifiedArena).size(); + if (specifiedArena.getMaxPlayers() > 0 && playingNow >= specifiedArena.getMaxPlayers()) { + stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_JOIN_ARENA_FULL); + return true; + } + joinArena(specifiedArena, player, arguments); return true; } diff --git a/src/main/java/net/knarcraft/minigames/command/parkour/EditParkourArenaCommand.java b/src/main/java/net/knarcraft/minigames/command/parkour/EditParkourArenaCommand.java index 95524f0..2900756 100644 --- a/src/main/java/net/knarcraft/minigames/command/parkour/EditParkourArenaCommand.java +++ b/src/main/java/net/knarcraft/minigames/command/parkour/EditParkourArenaCommand.java @@ -4,16 +4,12 @@ import net.knarcraft.knarlib.formatting.StringFormatter; import net.knarcraft.minigames.MiniGames; import net.knarcraft.minigames.arena.parkour.ParkourArena; import net.knarcraft.minigames.arena.parkour.ParkourArenaEditableProperty; +import net.knarcraft.minigames.command.EditArenaCommand; import net.knarcraft.minigames.config.MiniGameMessage; -import net.knarcraft.minigames.util.InputValidationHelper; -import org.bukkit.Location; -import org.bukkit.Material; 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 org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.List; @@ -21,12 +17,13 @@ import java.util.List; /** * The command for editing an existing dropper arena */ -public class EditParkourArenaCommand implements CommandExecutor { +public class EditParkourArenaCommand extends EditArenaCommand { /** * Instantiates a new edit arena command */ public EditParkourArenaCommand() { + super(null); } @Override @@ -101,43 +98,8 @@ public class EditParkourArenaCommand implements CommandExecutor { case CHECKPOINT_CLEAR -> arena.clearCheckpoints(); case KILL_PLANE_BLOCKS -> arena.setKillPlaneBlocks(new HashSet<>(List.of(value.split(",")))); case OBSTACLE_BLOCKS -> arena.setObstacleBlocks(new HashSet<>(List.of(value.split(",")))); + case MAX_PLAYERS -> arena.setMaxPlayers(parseMaxPlayers(value)); }; } - /** - * Parses the given location string - * - * @param player

The player changing a location

- * @param locationString

The location string to parse

- * @return

The parsed location, or the player's location if not parse-able

- */ - private @Nullable Location parseLocation(Player player, String locationString) { - if ((locationString.trim() + ",").matches("([0-9]+.?[0-9]*,){3}")) { - String[] parts = locationString.split(","); - Location newLocation = player.getLocation().clone(); - newLocation.setX(Double.parseDouble(parts[0].trim())); - newLocation.setY(Double.parseDouble(parts[1].trim())); - newLocation.setZ(Double.parseDouble(parts[2].trim())); - return newLocation; - } else if (InputValidationHelper.isEmptyValue(locationString)) { - return null; - } else { - return player.getLocation().clone(); - } - } - - /** - * Parses the given material name - * - * @param materialName

The material name to parse

- * @return

The parsed material, or AIR if not valid

- */ - private @NotNull Material parseMaterial(String materialName) { - Material material = Material.matchMaterial(materialName); - if (material == null) { - material = Material.AIR; - } - return material; - } - } diff --git a/src/main/java/net/knarcraft/minigames/command/parkour/JoinParkourArenaCommand.java b/src/main/java/net/knarcraft/minigames/command/parkour/JoinParkourArenaCommand.java index e39d5d2..fb1c4ee 100644 --- a/src/main/java/net/knarcraft/minigames/command/parkour/JoinParkourArenaCommand.java +++ b/src/main/java/net/knarcraft/minigames/command/parkour/JoinParkourArenaCommand.java @@ -54,6 +54,13 @@ public class JoinParkourArenaCommand implements CommandExecutor { return true; } + // Deny joining full arenas + int playingNow = MiniGames.getInstance().getParkourArenaPlayerRegistry().getPlayingPlayers(specifiedArena).size(); + if (specifiedArena.getMaxPlayers() > 0 && playingNow >= specifiedArena.getMaxPlayers()) { + stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_JOIN_ARENA_FULL); + return true; + } + joinArena(specifiedArena, player, arguments); return true; } @@ -69,7 +76,7 @@ public class JoinParkourArenaCommand implements CommandExecutor { // Find the specified game-mode ParkourArenaGameMode gameMode; if (arguments.length > 1) { - gameMode = ParkourArenaGameMode.matchGamemode(arguments[1]); + gameMode = ParkourArenaGameMode.matchGameMode(arguments[1]); } else { gameMode = ParkourArenaGameMode.DEFAULT; } diff --git a/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSetCommand.java b/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSetCommand.java index 81dc3ae..c2fc0bf 100644 --- a/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSetCommand.java +++ b/src/main/java/net/knarcraft/minigames/command/parkour/ParkourGroupSetCommand.java @@ -6,6 +6,7 @@ import net.knarcraft.minigames.arena.parkour.ParkourArena; import net.knarcraft.minigames.arena.parkour.ParkourArenaGroup; import net.knarcraft.minigames.arena.parkour.ParkourArenaHandler; import net.knarcraft.minigames.config.MiniGameMessage; +import net.knarcraft.minigames.util.InputValidationHelper; import net.knarcraft.minigames.util.StringSanitizer; import net.knarcraft.minigames.util.TabCompleteHelper; import org.bukkit.command.Command; @@ -47,7 +48,7 @@ public class ParkourGroupSetCommand implements TabExecutor { } ParkourArenaGroup arenaGroup; - if (groupName.equalsIgnoreCase("null") || groupName.equalsIgnoreCase("none")) { + if (InputValidationHelper.isEmptyValue(groupName)) { arenaGroup = null; } else { arenaGroup = arenaHandler.getGroup(groupName); diff --git a/src/main/java/net/knarcraft/minigames/config/MiniGameMessage.java b/src/main/java/net/knarcraft/minigames/config/MiniGameMessage.java index 5748ea7..83bc117 100644 --- a/src/main/java/net/knarcraft/minigames/config/MiniGameMessage.java +++ b/src/main/java/net/knarcraft/minigames/config/MiniGameMessage.java @@ -170,6 +170,11 @@ public enum MiniGameMessage implements TranslatableMessage { */ ERROR_GEYSER_DROPPER, + /** + * The message displayed when a player attempts to join a full arena + */ + ERROR_JOIN_ARENA_FULL, + /* **************** * * Success messages * * **************** */ diff --git a/src/main/java/net/knarcraft/minigames/placeholder/DropperExpansion.java b/src/main/java/net/knarcraft/minigames/placeholder/DropperExpansion.java index b668a24..064dba8 100644 --- a/src/main/java/net/knarcraft/minigames/placeholder/DropperExpansion.java +++ b/src/main/java/net/knarcraft/minigames/placeholder/DropperExpansion.java @@ -9,6 +9,7 @@ import net.knarcraft.minigames.placeholder.parsing.PlayerPlaceholderParser; import net.knarcraft.minigames.placeholder.parsing.RecordPlaceholderParser; import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * A placeholderAPI expansion for Dropper-related placeholders @@ -58,13 +59,14 @@ public class DropperExpansion extends PlaceholderExpansion { } @Override + @Nullable public String onRequest(OfflinePlayer player, String parameters) { String[] parts = parameters.split("_"); // Record is used as the prefix for all record placeholders in case more placeholder types are added if (parts[0].equalsIgnoreCase("record") && parts.length >= 7) { - return recordPlaceholderParser.onRequest(parameters, parts); + return recordPlaceholderParser.onRequest(parts); } else if (parts[0].equalsIgnoreCase("players")) { - return this.playerPlaceholderParser.onRequest(parameters, parts); + return this.playerPlaceholderParser.onRequest(parts); } else { return parameters; } diff --git a/src/main/java/net/knarcraft/minigames/placeholder/ParkourExpansion.java b/src/main/java/net/knarcraft/minigames/placeholder/ParkourExpansion.java index ba9ba60..05723e3 100644 --- a/src/main/java/net/knarcraft/minigames/placeholder/ParkourExpansion.java +++ b/src/main/java/net/knarcraft/minigames/placeholder/ParkourExpansion.java @@ -9,6 +9,7 @@ import net.knarcraft.minigames.placeholder.parsing.PlayerPlaceholderParser; import net.knarcraft.minigames.placeholder.parsing.RecordPlaceholderParser; import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * A placeholderAPI expansion for Parkour-related placeholders @@ -25,8 +26,8 @@ public class ParkourExpansion extends PlaceholderExpansion { */ public ParkourExpansion(@NotNull MiniGames plugin) { ParkourArenaHandler arenaHandler = plugin.getParkourArenaHandler(); - this.recordPlaceholderParser = new RecordPlaceholderParser(arenaHandler, ParkourArenaGameMode::matchGamemode); - this.playerPlaceholderParser = new PlayerPlaceholderParser<>(arenaHandler, ParkourArenaGameMode::matchGamemode, + this.recordPlaceholderParser = new RecordPlaceholderParser(arenaHandler, ParkourArenaGameMode::matchGameMode); + this.playerPlaceholderParser = new PlayerPlaceholderParser<>(arenaHandler, ParkourArenaGameMode::matchGameMode, plugin.getParkourArenaPlayerRegistry()); } @@ -58,13 +59,14 @@ public class ParkourExpansion extends PlaceholderExpansion { } @Override + @Nullable public String onRequest(OfflinePlayer player, String parameters) { String[] parts = parameters.split("_"); // Record is used as the prefix for all record placeholders in case more placeholder types are added if (parts[0].equalsIgnoreCase("record") && parts.length >= 7) { - return recordPlaceholderParser.onRequest(parameters, parts); + return recordPlaceholderParser.onRequest(parts); } else if (parts[0].equalsIgnoreCase("players")) { - return this.playerPlaceholderParser.onRequest(parameters, parts); + return this.playerPlaceholderParser.onRequest(parts); } else { return parameters; } diff --git a/src/main/java/net/knarcraft/minigames/placeholder/parsing/PlayerPlaceholderParser.java b/src/main/java/net/knarcraft/minigames/placeholder/parsing/PlayerPlaceholderParser.java index 7870fe6..515d251 100644 --- a/src/main/java/net/knarcraft/minigames/placeholder/parsing/PlayerPlaceholderParser.java +++ b/src/main/java/net/knarcraft/minigames/placeholder/parsing/PlayerPlaceholderParser.java @@ -16,7 +16,6 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.HashSet; import java.util.List; -import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.function.Function; @@ -49,16 +48,49 @@ public class PlayerPlaceholderParser { /** * The method to run when parsing a record placeholder request * - * @param parameters

The parameters specified

+ * @param parts

The split parameters, without irrelevant info

* @return

The resulting string

*/ - @NotNull - public String onRequest(@NotNull String parameters, @NotNull String[] parts) { - if (parts.length < 6) { - return parameters; + @Nullable + public String onRequest(@NotNull String[] parts) { + if (parts.length < 2) { + return null; } - // String selector = parts[1]; // The selector for which aspect of players to get. Playing is the only one available yet. + String selector = parts[1]; + if (parts.length >= 6 && selector.equalsIgnoreCase("playing")) { + return getPlayingPlayersInfo(parts); + } else if (parts.length >= 3 && selector.equalsIgnoreCase("maximum")) { + return getMaxPlayersInfo(parts); + } else { + return null; + } + } + + /** + * Gets placeholder info about max players + * + * @param parts

The split parameters, without irrelevant info

+ * @return

The resulting string

+ */ + @Nullable + private String getMaxPlayersInfo(@NotNull String[] parts) { + String info = null; + K arena = arenaHandler.getArena(parts[2]); + if (arena != null) { + info = String.valueOf(arena.getMaxPlayers()); + } + return info; + } + + /** + * Gets placeholder info about playing players + * + * @param parts

The split parameters, without irrelevant info

+ * @return

The resulting string

+ */ + @Nullable + private String getPlayingPlayersInfo(@NotNull String[] parts) { String gameModeName = parts[2]; ArenaGameMode gameMode = gameModeParser.apply(gameModeName); if (gameModeName.equalsIgnoreCase("combined") || gameModeName.equalsIgnoreCase("all")) { @@ -71,7 +103,7 @@ public class PlayerPlaceholderParser { // The type of info to get. Either count (number of players) or player_position (a named player). PlayerInfoType infoType = PlayerInfoType.getFromString(parts[5]); if (infoType == null) { - return parameters; + return null; } String info = null; @@ -84,7 +116,7 @@ public class PlayerPlaceholderParser { info = getArenaInfo(identifier, gameMode, infoType, parts); } - return Objects.requireNonNullElse(info, parameters); + return info; } /** diff --git a/src/main/java/net/knarcraft/minigames/placeholder/parsing/RecordPlaceholderParser.java b/src/main/java/net/knarcraft/minigames/placeholder/parsing/RecordPlaceholderParser.java index 20692ed..21219f7 100644 --- a/src/main/java/net/knarcraft/minigames/placeholder/parsing/RecordPlaceholderParser.java +++ b/src/main/java/net/knarcraft/minigames/placeholder/parsing/RecordPlaceholderParser.java @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.function.Function; @@ -51,13 +50,13 @@ public class RecordPlaceholderParser { /** * The method to run when parsing a record placeholder request * - * @param parameters

The parameters specified

+ * @param parts

All parts of the placeholder

* @return

The resulting string

*/ - @NotNull - public String onRequest(@NotNull String parameters, @NotNull String[] parts) { + @Nullable + public String onRequest(@NotNull String[] parts) { if (parts.length < 7) { - return parameters; + return null; } RecordType recordType = RecordType.getFromString(parts[1]); @@ -70,12 +69,12 @@ public class RecordPlaceholderParser { } catch (NumberFormatException exception) { MiniGames.log(Level.WARNING, "Invalid placeholder given. " + parts[5] + " supplied instead of record position."); - return parameters; + return null; } InfoType infoType = InfoType.getFromString(parts[6]); if (recordType == null || infoType == null) { - return parameters; + return null; } String info = null; @@ -85,7 +84,7 @@ public class RecordPlaceholderParser { info = getArenaRecord(arenaHandler, identifier, gameMode, recordType, recordNumber, infoType); } - return Objects.requireNonNullElse(info, parameters); + return info; } /** diff --git a/src/main/java/net/knarcraft/minigames/util/DropperArenaStorageHelper.java b/src/main/java/net/knarcraft/minigames/util/DropperArenaStorageHelper.java index c4421bc..9053df0 100644 --- a/src/main/java/net/knarcraft/minigames/util/DropperArenaStorageHelper.java +++ b/src/main/java/net/knarcraft/minigames/util/DropperArenaStorageHelper.java @@ -137,6 +137,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())); + configSection.set(DropperArenaStorageKey.MAX_PLAYERS.getKey(), arena.getMaxPlayers()); RewardStorageHelper.saveRewards(arena, configSection, DropperArenaStorageKey.REWARDS.getKey()); saveDropperArenaData(arena.getData()); } @@ -187,6 +188,7 @@ public final class DropperArenaStorageHelper { double verticalVelocity = configurationSection.getDouble(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey()); float horizontalVelocity = sanitizeHorizontalVelocity((float) configurationSection.getDouble( DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey())); + int maxPlayers = configurationSection.getInt(DropperArenaStorageKey.MAX_PLAYERS.getKey(), -1); SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get( DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey()); @@ -212,7 +214,7 @@ public final class DropperArenaStorageHelper { } return new DropperArena(arenaId, arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity, - winBlockType.getRawValue(), rewards, arenaData, MiniGames.getInstance().getDropperArenaHandler()); + winBlockType.getRawValue(), maxPlayers, rewards, arenaData, MiniGames.getInstance().getDropperArenaHandler()); } /** diff --git a/src/main/java/net/knarcraft/minigames/util/InputValidationHelper.java b/src/main/java/net/knarcraft/minigames/util/InputValidationHelper.java index ee841ca..0714a0e 100644 --- a/src/main/java/net/knarcraft/minigames/util/InputValidationHelper.java +++ b/src/main/java/net/knarcraft/minigames/util/InputValidationHelper.java @@ -35,8 +35,8 @@ public final class InputValidationHelper { * @return

True if the value can be considered as empty

*/ public static boolean isEmptyValue(@NotNull String value) { - return value.equalsIgnoreCase("null") || value.equalsIgnoreCase("0") || - value.equalsIgnoreCase("clear") || value.equalsIgnoreCase("none"); + return value.equalsIgnoreCase("null") || value.equalsIgnoreCase("clear") || + value.equalsIgnoreCase("none"); } } diff --git a/src/main/java/net/knarcraft/minigames/util/ParkourArenaStorageHelper.java b/src/main/java/net/knarcraft/minigames/util/ParkourArenaStorageHelper.java index 37998a4..34b77e5 100644 --- a/src/main/java/net/knarcraft/minigames/util/ParkourArenaStorageHelper.java +++ b/src/main/java/net/knarcraft/minigames/util/ParkourArenaStorageHelper.java @@ -140,6 +140,7 @@ public final class ParkourArenaStorageHelper { configSection.set(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey(), getKillPlaneBlocks(arena)); configSection.set(ParkourArenaStorageKey.OBSTACLE_BLOCKS.getKey(), getObstacleBlocks(arena)); configSection.set(ParkourArenaStorageKey.CHECKPOINTS.getKey(), arena.getCheckpoints()); + configSection.set(ParkourArenaStorageKey.MAX_PLAYERS.getKey(), arena.getMaxPlayers()); RewardStorageHelper.saveRewards(arena, configSection, ParkourArenaStorageKey.REWARDS.getKey()); saveParkourArenaData(arena.getData()); } @@ -217,6 +218,7 @@ public final class ParkourArenaStorageHelper { Location spawnLocation = (Location) configurationSection.get(ParkourArenaStorageKey.SPAWN_LOCATION.getKey()); Location exitLocation = (Location) configurationSection.get(ParkourArenaStorageKey.EXIT_LOCATION.getKey()); Location winLocation = (Location) configurationSection.get(ParkourArenaStorageKey.WIN_LOCATION.getKey()); + int maxPlayers = configurationSection.getInt(ParkourArenaStorageKey.MAX_PLAYERS.getKey(), -1); SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get( ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey()); List killPlaneBlockNamesList = configurationSection.getList(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey()); @@ -264,7 +266,7 @@ public final class ParkourArenaStorageHelper { } return new ParkourArena(arenaId, arenaName, spawnLocation, exitLocation, winBlockType.getRawValue(), winLocation, - killPlaneBlockNames, obstacleBlockNames, checkpoints, rewards, arenaData, + killPlaneBlockNames, obstacleBlockNames, checkpoints, maxPlayers, rewards, arenaData, MiniGames.getInstance().getParkourArenaHandler()); } diff --git a/src/main/java/net/knarcraft/minigames/util/RewardHelper.java b/src/main/java/net/knarcraft/minigames/util/RewardHelper.java index bffd1ed..5fdcb30 100644 --- a/src/main/java/net/knarcraft/minigames/util/RewardHelper.java +++ b/src/main/java/net/knarcraft/minigames/util/RewardHelper.java @@ -22,7 +22,7 @@ import java.util.Collection; import java.util.UUID; /** - * A helopr class for getting the reward specified in user input + * A helper class for getting the reward specified in user input */ public final class RewardHelper { diff --git a/src/main/java/net/knarcraft/minigames/util/TabCompleteHelper.java b/src/main/java/net/knarcraft/minigames/util/TabCompleteHelper.java index 9d46c0b..7ff28d5 100644 --- a/src/main/java/net/knarcraft/minigames/util/TabCompleteHelper.java +++ b/src/main/java/net/knarcraft/minigames/util/TabCompleteHelper.java @@ -111,11 +111,25 @@ public final class TabCompleteHelper { tabCompleteSuggestions.put(EditablePropertyType.CHECKPOINT_CLEAR, getCheckpointClearSuggestions()); tabCompleteSuggestions.put(EditablePropertyType.MATERIAL_LIST, getMaterialListSuggestions()); tabCompleteSuggestions.put(EditablePropertyType.DOUBLE, getDoubleSuggestions()); + tabCompleteSuggestions.put(EditablePropertyType.INTEGER, getIntegerSuggestions()); } return tabCompleteSuggestions.get(propertyType); } + private static List getIntegerSuggestions() { + List suggestions = new ArrayList<>(); + suggestions.add("-1"); + suggestions.add("1"); + suggestions.add("2"); + suggestions.add("3"); + suggestions.add("4"); + suggestions.add("5"); + suggestions.add("6"); + suggestions.add("7"); + return suggestions; + } + /** * Gets suggestions for double values * diff --git a/src/main/resources/strings.yml b/src/main/resources/strings.yml index e755f98..36d090f 100644 --- a/src/main/resources/strings.yml +++ b/src/main/resources/strings.yml @@ -30,6 +30,7 @@ en: ERROR_REWARD_TYPE_INVALID: "You have specified an invalid reward type" ERROR_REWARD_CONDITION_INVALID: "You have specified an invalid reward condition" ERROR_GEYSER_DROPPER: "Because of version differences, droppers don't work properly using the Bedrock client. Please use Minecraft Java Edition instead." + ERROR_JOIN_ARENA_FULL: "The maximum amount of players are already in the arena" SUCCESS_ARENA_GROUP_UPDATED: "The arena's group has been updated" SUCCESS_PLUGIN_RELOADED: "Plugin reloaded!" SUCCESS_ARENA_CREATED: "The arena was successfully created!"