mirror of
https://github.com/SunNetservers/MiniGames.git
synced 2025-04-02 09:46:26 +02:00
Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
d7e950c53e | |||
c8fbdec64f | |||
09f29e5f67 | |||
7213bd0c70 | |||
a23d0c769f | |||
142cd5339b | |||
b063bd1088 | |||
310802b42d | |||
fc6bd33e87 | |||
ccf43060dc | |||
a498e9bad0 | |||
d8bf77d317 | |||
162aff0c1f | |||
a7cfe36c72 | |||
407acf0ea2 | |||
b6bf22d1c7 | |||
67144fec06 | |||
e52732433a | |||
776fc5a757 | |||
1e7cdf02fc | |||
f3d8be8be2 |
22
README.md
22
README.md
@ -99,7 +99,9 @@ This reward requires an argument which is the permission string you want to gran
|
||||
###### Command
|
||||
|
||||
The reward requires the command as an argument. Type the full command with spaces and everything, but omit the `/` at
|
||||
the beginning of the command.
|
||||
the beginning of the command. Use %player_name% or anything that matches the
|
||||
RegEx `[<%(\\[{]player[_\\-]?(name)?[>%)\\]}]` (\<player>. \<player-name>, %player_name%, {player}, etc.) as the
|
||||
placeholder for the rewarded player's name.
|
||||
|
||||
###### Item
|
||||
|
||||
@ -211,16 +213,17 @@ These are all the options that can be changed for an arena.
|
||||
| winLocation | The location players must reach to win the arena (see spawnLocation for valid values). If set, this overrides, and is used instead of, the win block type. |
|
||||
| checkpointAdd | Adds a new checkpoint to the arena's checkpoints (see spawnLocation for valid values). |
|
||||
| checkpointClear | Clears all current checkpoints. Give any value to execute. If not given a value, current checkpoints are shown. |
|
||||
| killPlaneBlocks | A comma-separated list of materials which will force a loss on hit. +WOOL and other [material tags](#notes-about-material-tags) are supported as well. |
|
||||
| killPlaneBlocks | A comma-separated list of materials which will force a loss when stepped on. +WOOL and other [material tags](#notes-about-material-tags) are supported as well. |
|
||||
| obstacleBlocks | A comma-separated list of materials which will force a loss when touched from any direction. +WOOL and other [material tags](#notes-about-material-tags) are supported as well. |
|
||||
|
||||
## Configuration options
|
||||
|
||||
### Shared
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|-----------------------------------|---------------------|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| liquidHitBoxDepth | -1 < decimal < 0 | -0.8 | This decides how far inside a non-solid block the player must go before detection triggers (-1, 0). The closer to -1 it is, the more accurate it will seem to the player, but the likelihood of not detecting the hit increases. |
|
||||
| solidHitBoxDistance | 0 < decimal < 1 | 0.2 | This decides the distance the player must be from a block below them before a hit triggers (0, 1). If too low, the likelihood of detecting the hit decreases, but it won't look like the player hit the block without being near. |
|
||||
| Name | Type | Default | Description |
|
||||
|---------------------|------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| liquidHitBoxDepth | -1 < decimal < 0 | -0.8 | This decides how far inside a non-solid block the player must go before detection triggers (-1, 0). The closer to -1 it is, the more accurate it will seem to the player, but the likelihood of not detecting the hit increases. |
|
||||
| solidHitBoxDistance | 0 < decimal < 1 | 0.2 | This decides the distance the player must be from a block below them before a hit triggers (0, 1). If too low, the likelihood of detecting the hit decreases, but it won't look like the player hit the block without being near. |
|
||||
|
||||
### Dropper
|
||||
|
||||
@ -246,6 +249,7 @@ These are all the options that can be changed for an arena.
|
||||
| mustDoGroupedInSequence | true/false | true | Whether grouped dropper arenas must be played in the correct sequence |
|
||||
| ignoreRecordsUntilGroupBeatenOnce | true/false | false | Whether records won't be registered unless the player has already beaten all arenas in a group. That means players are required to do a second play-through to register a record for a grouped arena. |
|
||||
| killPlaneBlocks | list | [see this](#killplaneblocks-default) | The types of blocks compromising parkour arenas' kill planes. Add any materials you want to use for the "bottom" of your parkour arenas. +WOOL and other [material tags](#notes-about-material-tags) are supported. |
|
||||
| obstacleBlocks | list | [see this](#obstacleblocks-default) | The types of blocks treated as obstacles in every direction. +WOOL and other [material tags](#notes-about-material-tags) are supported. |
|
||||
|
||||
#### blockWhitelist default:
|
||||
|
||||
@ -267,6 +271,12 @@ These are all the options that can be changed for an arena.
|
||||
- LAVA
|
||||
- MAGMA_BLOCK
|
||||
|
||||
#### obstacleBlocks default:
|
||||
|
||||
- END_ROD
|
||||
- LIGHTNING_ROD
|
||||
- CHAIN
|
||||
|
||||
## Record placeholders
|
||||
|
||||
Player records can be displayed on a leaderboard by using PlaceholderAPI. If you want to display a sign-based
|
||||
|
8
pom.xml
8
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>net.knarcraft</groupId>
|
||||
<artifactId>MiniGames</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>MiniGames</name>
|
||||
@ -105,12 +105,6 @@
|
||||
<version>24.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.9.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
|
@ -104,7 +104,7 @@ public abstract class AbstractArenaPlayerRegistry<K extends Arena> implements Ar
|
||||
for (PlayerEntryState entryState : entryStates) {
|
||||
this.entryStates.put(entryState.getPlayerId(), entryState);
|
||||
}
|
||||
if (this.entryStates.size() > 0) {
|
||||
if (!this.entryStates.isEmpty()) {
|
||||
MiniGames.log(Level.WARNING, entryStates.size() + " un-exited sessions found. This happens if " +
|
||||
"players leave in the middle of a game, or if the server crashes. MiniGames will do its best " +
|
||||
"to fix the players' states.");
|
||||
|
@ -38,6 +38,11 @@ public enum EditablePropertyType {
|
||||
/**
|
||||
* The property is a comma-separated list of materials
|
||||
*/
|
||||
MATERIAL_LIST
|
||||
MATERIAL_LIST,
|
||||
|
||||
/**
|
||||
* The property is any double value
|
||||
*/
|
||||
DOUBLE,
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static net.knarcraft.minigames.util.InputValidationHelper.isInvalid;
|
||||
|
||||
@ -167,13 +168,13 @@ public class DropperArena implements Arena {
|
||||
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();
|
||||
this.saveArena();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRewards(@NotNull RewardCondition rewardCondition) {
|
||||
this.rewards.remove(rewardCondition);
|
||||
this.dropperArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -267,7 +268,7 @@ public class DropperArena implements Arena {
|
||||
return false;
|
||||
} else {
|
||||
this.spawnLocation = newLocation;
|
||||
this.dropperArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -283,7 +284,7 @@ public class DropperArena implements Arena {
|
||||
return false;
|
||||
} else {
|
||||
this.exitLocation = newLocation;
|
||||
this.dropperArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -300,7 +301,7 @@ public class DropperArena implements Arena {
|
||||
this.arenaName = arenaName;
|
||||
// Update the arena lookup map to make sure the new name can be used immediately
|
||||
this.dropperArenaHandler.updateLookupName(oldName, this.getArenaNameSanitized());
|
||||
this.dropperArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -320,7 +321,7 @@ public class DropperArena implements Arena {
|
||||
return false;
|
||||
} else {
|
||||
this.winBlockType = material;
|
||||
this.dropperArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -338,7 +339,7 @@ public class DropperArena implements Arena {
|
||||
return false;
|
||||
} else {
|
||||
this.playerHorizontalVelocity = horizontalVelocity;
|
||||
this.dropperArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -354,11 +355,24 @@ public class DropperArena implements Arena {
|
||||
return false;
|
||||
} else {
|
||||
this.playerVerticalVelocity = verticalVelocity;
|
||||
this.dropperArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this arena to disk
|
||||
*/
|
||||
public void saveArena() {
|
||||
try {
|
||||
DropperArenaStorageHelper.saveSingleDropperArena(this);
|
||||
} catch (IOException exception) {
|
||||
MiniGames.log(Level.SEVERE, "Unable to save arena! " +
|
||||
"Data loss can occur!");
|
||||
MiniGames.log(Level.SEVERE, exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof DropperArena otherArena)) {
|
||||
|
@ -34,11 +34,11 @@ public enum DropperArenaGameMode implements ConfigurationSerializable, ArenaGame
|
||||
* @param gameMode <p>The game-mode string to match</p>
|
||||
* @return <p>The specified arena game-mode</p>
|
||||
*/
|
||||
public static @NotNull DropperArenaGameMode matchGamemode(@NotNull String gameMode) {
|
||||
public static @NotNull DropperArenaGameMode matchGameMode(@NotNull String gameMode) {
|
||||
String sanitized = gameMode.trim().toLowerCase();
|
||||
if (sanitized.matches("(invert(ed)?|inverse)")) {
|
||||
return DropperArenaGameMode.INVERTED;
|
||||
} else if (sanitized.matches("rand(om)?")) {
|
||||
} else if (sanitized.matches("rand(om)?_?(inverted)?")) {
|
||||
return DropperArenaGameMode.RANDOM_INVERTED;
|
||||
} else {
|
||||
return DropperArenaGameMode.DEFAULT;
|
||||
|
@ -23,6 +23,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static net.knarcraft.minigames.util.InputValidationHelper.isInvalid;
|
||||
|
||||
@ -72,6 +73,16 @@ public class ParkourArena implements Arena {
|
||||
*/
|
||||
private @Nullable Set<Material> killPlaneBlocks;
|
||||
|
||||
/**
|
||||
* The names of the block types serving as obstacles for this arena
|
||||
*/
|
||||
private @Nullable Set<String> obstacleBlockNames;
|
||||
|
||||
/**
|
||||
* The block types serving as obstacles for this arena
|
||||
*/
|
||||
private @Nullable Set<Material> obstacleBlocks;
|
||||
|
||||
/**
|
||||
* The checkpoints for this arena. Entering a checkpoint overrides the player's spawn location.
|
||||
*/
|
||||
@ -95,7 +106,8 @@ public class ParkourArena implements Arena {
|
||||
* @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 killPlaneBlockNames <p>The names of the types of blocks that trigger a loss when stepped on</p>
|
||||
* @param obstacleBlockNames <p>The names of the types of blocks that trigger a loss when touched</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>
|
||||
@ -103,7 +115,8 @@ 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<String> killPlaneBlockNames, @NotNull List<Location> checkpoints,
|
||||
@Nullable Set<String> killPlaneBlockNames, @Nullable Set<String> obstacleBlockNames,
|
||||
@NotNull List<Location> checkpoints,
|
||||
@NotNull Map<RewardCondition, Set<Reward>> rewards,
|
||||
@NotNull ParkourArenaData parkourArenaData, @NotNull ParkourArenaHandler arenaHandler) {
|
||||
this.arenaId = arenaId;
|
||||
@ -115,6 +128,9 @@ public class ParkourArena implements Arena {
|
||||
this.killPlaneBlockNames = killPlaneBlockNames;
|
||||
this.killPlaneBlocks = this.killPlaneBlockNames == null ? null : MaterialHelper.loadMaterialList(
|
||||
new ArrayList<>(killPlaneBlockNames), "+", MiniGames.getInstance().getLogger());
|
||||
this.obstacleBlockNames = obstacleBlockNames;
|
||||
this.obstacleBlocks = this.obstacleBlockNames == null ? null : MaterialHelper.loadMaterialList(
|
||||
new ArrayList<>(obstacleBlockNames), "+", MiniGames.getInstance().getLogger());
|
||||
this.checkpoints = checkpoints;
|
||||
this.parkourArenaData = parkourArenaData;
|
||||
this.parkourArenaHandler = arenaHandler;
|
||||
@ -147,6 +163,7 @@ public class ParkourArena implements Arena {
|
||||
this.parkourArenaData = new ParkourArenaData(this.arenaId, recordRegistries, new HashMap<>());
|
||||
this.winBlockType = Material.EMERALD_BLOCK;
|
||||
this.killPlaneBlocks = null;
|
||||
this.obstacleBlocks = null;
|
||||
this.checkpoints = new ArrayList<>();
|
||||
this.parkourArenaHandler = arenaHandler;
|
||||
}
|
||||
@ -180,13 +197,13 @@ public class ParkourArena implements Arena {
|
||||
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();
|
||||
this.saveArena();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRewards(@NotNull RewardCondition rewardCondition) {
|
||||
this.rewards.remove(rewardCondition);
|
||||
this.parkourArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -240,6 +257,28 @@ public class ParkourArena implements Arena {
|
||||
return this.killPlaneBlockNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block types used for this parkour arena's obstacle blocks
|
||||
*
|
||||
* @return <p>The types of blocks used as obstacles</p>
|
||||
*/
|
||||
public @NotNull Set<Material> getObstacleBlocks() {
|
||||
if (this.obstacleBlocks != null) {
|
||||
return new HashSet<>(this.obstacleBlocks);
|
||||
} else {
|
||||
return MiniGames.getInstance().getParkourConfiguration().getObstacleBlocks();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of the blocks used as this arena's obstacle blocks
|
||||
*
|
||||
* @return <p>The names of the blocks used as this arena's obstacle blocks</p>
|
||||
*/
|
||||
public @Nullable Set<String> getObstacleBlockNames() {
|
||||
return this.obstacleBlockNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all checkpoint locations for this arena
|
||||
*
|
||||
@ -294,7 +333,7 @@ public class ParkourArena implements Arena {
|
||||
|
||||
@Override
|
||||
public boolean willCauseLoss(Block block) {
|
||||
return this.getKillPlaneBlocks().contains(block.getType());
|
||||
return this.getKillPlaneBlocks().contains(block.getType()) || this.getObstacleBlocks().contains(block.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -314,7 +353,7 @@ public class ParkourArena implements Arena {
|
||||
return false;
|
||||
} else {
|
||||
this.spawnLocation = newLocation;
|
||||
this.parkourArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -330,7 +369,7 @@ public class ParkourArena implements Arena {
|
||||
return false;
|
||||
} else {
|
||||
this.exitLocation = newLocation;
|
||||
this.parkourArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -347,7 +386,7 @@ public class ParkourArena implements Arena {
|
||||
this.arenaName = arenaName;
|
||||
// Update the arena lookup map to make sure the new name can be used immediately
|
||||
this.parkourArenaHandler.updateLookupName(oldName, this.getArenaNameSanitized());
|
||||
this.parkourArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -367,7 +406,7 @@ public class ParkourArena implements Arena {
|
||||
return false;
|
||||
} else {
|
||||
this.winBlockType = material;
|
||||
this.parkourArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -383,7 +422,7 @@ public class ParkourArena implements Arena {
|
||||
return false;
|
||||
} else {
|
||||
this.winLocation = newLocation.clone();
|
||||
this.parkourArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -395,6 +434,7 @@ public class ParkourArena implements Arena {
|
||||
*/
|
||||
public boolean setKillPlaneBlocks(@NotNull Set<String> killPlaneBlockNames) {
|
||||
if (killPlaneBlockNames.isEmpty()) {
|
||||
this.killPlaneBlockNames = null;
|
||||
this.killPlaneBlocks = null;
|
||||
} else {
|
||||
Set<Material> parsed = MaterialHelper.loadMaterialList(new ArrayList<>(killPlaneBlockNames), "+",
|
||||
@ -402,9 +442,32 @@ public class ParkourArena implements Arena {
|
||||
if (parsed.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
this.killPlaneBlockNames = killPlaneBlockNames;
|
||||
this.killPlaneBlocks = parsed;
|
||||
}
|
||||
this.parkourArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of blocks used as obstacle blocks
|
||||
*
|
||||
* @param obstacleBlockNames <p>The names of the obstacle blocks</p>
|
||||
*/
|
||||
public boolean setObstacleBlocks(@NotNull Set<String> obstacleBlockNames) {
|
||||
if (obstacleBlockNames.isEmpty()) {
|
||||
this.obstacleBlockNames = null;
|
||||
this.obstacleBlocks = null;
|
||||
} else {
|
||||
Set<Material> parsed = MaterialHelper.loadMaterialList(new ArrayList<>(obstacleBlockNames), "+",
|
||||
MiniGames.getInstance().getLogger());
|
||||
if (parsed.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
this.obstacleBlockNames = obstacleBlockNames;
|
||||
this.obstacleBlocks = parsed;
|
||||
}
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -420,7 +483,7 @@ public class ParkourArena implements Arena {
|
||||
}
|
||||
|
||||
this.checkpoints.add(checkpoint.clone());
|
||||
this.parkourArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -435,10 +498,23 @@ public class ParkourArena implements Arena {
|
||||
}
|
||||
|
||||
this.checkpoints.clear();
|
||||
this.parkourArenaHandler.saveArenas();
|
||||
this.saveArena();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this arena to disk
|
||||
*/
|
||||
public void saveArena() {
|
||||
try {
|
||||
ParkourArenaStorageHelper.saveSingleParkourArena(this);
|
||||
} catch (IOException exception) {
|
||||
MiniGames.log(Level.SEVERE, "Unable to save arena! " +
|
||||
"Data loss can occur!");
|
||||
MiniGames.log(Level.SEVERE, exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof ParkourArena otherArena)) {
|
||||
|
@ -62,6 +62,13 @@ public enum ParkourArenaEditableProperty {
|
||||
*/
|
||||
KILL_PLANE_BLOCKS("killPlaneBlocks", (arena) -> String.valueOf(arena.getKillPlaneBlockNames()),
|
||||
EditablePropertyType.MATERIAL_LIST),
|
||||
|
||||
/**
|
||||
* The blocks used as this arena's obstacle blocks
|
||||
*/
|
||||
OBSTACLE_BLOCKS("obstacleBlocks", (arena) -> String.valueOf(arena.getObstacleBlockNames()),
|
||||
EditablePropertyType.MATERIAL_LIST),
|
||||
|
||||
;
|
||||
|
||||
private final @NotNull String argumentString;
|
||||
|
@ -42,6 +42,11 @@ public enum ParkourArenaStorageKey {
|
||||
*/
|
||||
KILL_PLANE_BLOCKS("killPlaneBlocks"),
|
||||
|
||||
/**
|
||||
* The key for this arena's obstacle blocks (overrides the config)
|
||||
*/
|
||||
OBSTACLE_BLOCKS("obstacleBlocks"),
|
||||
|
||||
/**
|
||||
* The key for this arena's checkpoint locations
|
||||
*/
|
||||
|
@ -44,6 +44,13 @@ public abstract class ArenaRecord<K extends Comparable<K>> implements Comparable
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this as a string that should be printed on a sign
|
||||
*
|
||||
* @return <p>This as a string</p>
|
||||
*/
|
||||
public abstract String getAsString();
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return other instanceof ArenaRecord<?> && userId.equals(((ArenaRecord<?>) other).userId);
|
||||
@ -70,7 +77,7 @@ public abstract class ArenaRecord<K extends Comparable<K>> implements Comparable
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return userId + ": " + record;
|
||||
return userId + ":" + record;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,11 @@ public class IntegerRecord extends SummableArenaRecord<Integer> {
|
||||
super(userId, record);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
return String.valueOf(this.getRecord());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SummableArenaRecord<Integer> sum(Integer value) {
|
||||
return new IntegerRecord(this.getUserId(), this.getRecord() + value);
|
||||
|
@ -7,7 +7,7 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A record storing a Long
|
||||
* A record storing a Long time
|
||||
*/
|
||||
public class LongRecord extends SummableArenaRecord<Long> {
|
||||
|
||||
@ -29,6 +29,22 @@ public class LongRecord extends SummableArenaRecord<Long> {
|
||||
return new LongRecord(this.getUserId(), this.getRecord() + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
int seconds = (int) Math.floor(getRecord() / 1000.0);
|
||||
int minutes = 0;
|
||||
if (seconds > 60) {
|
||||
minutes = (int) Math.floor(seconds / 60.0);
|
||||
seconds = seconds % 60;
|
||||
}
|
||||
|
||||
if (minutes > 0) {
|
||||
return minutes + "m" + seconds + "s";
|
||||
} else {
|
||||
return seconds + "s";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the saved arena record
|
||||
*
|
||||
|
@ -39,7 +39,6 @@ public class CreateDropperArenaCommand implements CommandExecutor {
|
||||
}
|
||||
|
||||
DropperArenaHandler arenaHandler = MiniGames.getInstance().getDropperArenaHandler();
|
||||
|
||||
DropperArena existingArena = arenaHandler.getArena(arenaName);
|
||||
if (existingArena != null) {
|
||||
MiniGames.getInstance().getStringFormatter().displayErrorMessage(commandSender,
|
||||
|
@ -38,7 +38,7 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
||||
// Disallow joining if the player is already in a mini-game arena
|
||||
if (MiniGames.getInstance().getSession(player.getUniqueId()) != null) {
|
||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_ALREADY_PLAYING);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make sure the arena exists
|
||||
@ -51,10 +51,11 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
||||
// Deny vehicles as allowing this is tricky, and will cause problems in some cases
|
||||
if (player.isInsideVehicle() || !player.getPassengers().isEmpty()) {
|
||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_JOIN_IN_VEHICLE_OR_PASSENGER);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return joinArena(specifiedArena, player, arguments);
|
||||
joinArena(specifiedArena, player, arguments);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,13 +64,12 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
||||
* @param specifiedArena <p>The arena the player wants to join</p>
|
||||
* @param player <p>The player joining the arena</p>
|
||||
* @param arguments <p>The arguments given</p>
|
||||
* @return <p>Whether the arena was joined successfully</p>
|
||||
*/
|
||||
private boolean joinArena(DropperArena specifiedArena, Player player, String[] arguments) {
|
||||
private void joinArena(DropperArena specifiedArena, Player player, String[] arguments) {
|
||||
// Find the specified game-mode
|
||||
DropperArenaGameMode gameMode;
|
||||
if (arguments.length > 1) {
|
||||
gameMode = DropperArenaGameMode.matchGamemode(arguments[1]);
|
||||
gameMode = DropperArenaGameMode.matchGameMode(arguments[1]);
|
||||
} else {
|
||||
gameMode = DropperArenaGameMode.DEFAULT;
|
||||
}
|
||||
@ -77,7 +77,7 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
||||
// Make sure the player has beaten the necessary levels
|
||||
DropperArenaGroup arenaGroup = MiniGames.getInstance().getDropperArenaHandler().getGroup(specifiedArena.getArenaId());
|
||||
if (arenaGroup != null && !doGroupChecks(specifiedArena, arenaGroup, gameMode, player)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
|
||||
@ -87,7 +87,7 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
||||
gameMode != DropperArenaGameMode.DEFAULT &&
|
||||
specifiedArena.getData().hasNotCompleted(DropperArenaGameMode.DEFAULT, player)) {
|
||||
stringFormatter.displayErrorMessage(player, MiniGameMessage.ERROR_NORMAL_MODE_REQUIRED);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the player's session
|
||||
@ -103,14 +103,12 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
||||
if (!teleported) {
|
||||
stringFormatter.displayErrorMessage(player, MiniGameMessage.ERROR_ARENA_TELEPORT_FAILED);
|
||||
newSession.triggerQuit(false, true);
|
||||
return false;
|
||||
} else {
|
||||
// Update the player's state to follow the arena's rules
|
||||
newSession.getEntryState().setArenaState();
|
||||
|
||||
player.getInventory().addItem(GUIHelper.getGUIOpenItem());
|
||||
stringFormatter.displaySuccessMessage(player, MiniGameMessage.SUCCESS_ARENA_JOINED);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@ public class CreateParkourArenaCommand implements CommandExecutor {
|
||||
}
|
||||
|
||||
ParkourArenaHandler arenaHandler = MiniGames.getInstance().getParkourArenaHandler();
|
||||
|
||||
ParkourArena existingArena = arenaHandler.getArena(arenaName);
|
||||
if (existingArena != null) {
|
||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_ARENA_NAME_COLLISION);
|
||||
|
@ -60,7 +60,12 @@ public class EditParkourArenaCommand implements CommandExecutor {
|
||||
new String[]{editableProperty.getArgumentString(), value}));
|
||||
return true;
|
||||
} else {
|
||||
boolean successful = changeValue(specifiedArena, editableProperty, arguments[2], player);
|
||||
boolean successful;
|
||||
try {
|
||||
successful = changeValue(specifiedArena, editableProperty, arguments[2], player);
|
||||
} catch (NumberFormatException exception) {
|
||||
successful = false;
|
||||
}
|
||||
if (successful) {
|
||||
stringFormatter.displaySuccessMessage(player, stringFormatter.replacePlaceholder(
|
||||
MiniGameMessage.SUCCESS_PROPERTY_CHANGED, "{property}",
|
||||
@ -80,9 +85,10 @@ public class EditParkourArenaCommand implements CommandExecutor {
|
||||
* @param value <p>The new value of the property</p>
|
||||
* @param player <p>The player trying to change the value</p>
|
||||
* @return <p>True if the value was successfully changed</p>
|
||||
* @throws NumberFormatException <p>If unable to parse a given numeric value</p>
|
||||
*/
|
||||
private boolean changeValue(@NotNull ParkourArena arena, @NotNull ParkourArenaEditableProperty property,
|
||||
@NotNull String value, @NotNull Player player) {
|
||||
@NotNull String value, @NotNull Player player) throws NumberFormatException {
|
||||
return switch (property) {
|
||||
case WIN_BLOCK_TYPE -> arena.setWinBlockType(parseMaterial(value));
|
||||
case SPAWN_LOCATION -> arena.setSpawnLocation(parseLocation(player, value));
|
||||
@ -92,6 +98,7 @@ public class EditParkourArenaCommand implements CommandExecutor {
|
||||
case CHECKPOINT_ADD -> arena.addCheckpoint(parseLocation(player, value));
|
||||
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(","))));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
||||
// Disallow joining if the player is already in a mini-game arena
|
||||
if (MiniGames.getInstance().getSession(player.getUniqueId()) != null) {
|
||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_ALREADY_PLAYING);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make sure the arena exists
|
||||
@ -51,10 +51,11 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
||||
// Deny vehicles as allowing this is tricky, and will cause problems in some cases
|
||||
if (player.isInsideVehicle() || !player.getPassengers().isEmpty()) {
|
||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_JOIN_IN_VEHICLE_OR_PASSENGER);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return joinArena(specifiedArena, player, arguments);
|
||||
joinArena(specifiedArena, player, arguments);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,9 +64,8 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
||||
* @param specifiedArena <p>The arena the player wants to join</p>
|
||||
* @param player <p>The player joining the arena</p>
|
||||
* @param arguments <p>The arguments given</p>
|
||||
* @return <p>Whether the arena was joined successfully</p>
|
||||
*/
|
||||
private boolean joinArena(ParkourArena specifiedArena, Player player, String[] arguments) {
|
||||
private void joinArena(ParkourArena specifiedArena, Player player, String[] arguments) {
|
||||
// Find the specified game-mode
|
||||
ParkourArenaGameMode gameMode;
|
||||
if (arguments.length > 1) {
|
||||
@ -78,13 +78,13 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
||||
if (specifiedArena.hasNoCheckpoints() && gameMode == ParkourArenaGameMode.HARDCORE) {
|
||||
MiniGames.getInstance().getStringFormatter().displayErrorMessage(player,
|
||||
MiniGameMessage.ERROR_HARDCORE_NO_CHECKPOINTS);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the player has beaten the necessary levels
|
||||
ParkourArenaGroup arenaGroup = MiniGames.getInstance().getParkourArenaHandler().getGroup(specifiedArena.getArenaId());
|
||||
if (arenaGroup != null && !doGroupChecks(specifiedArena, arenaGroup, gameMode, player)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the player's session
|
||||
@ -101,7 +101,6 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
||||
MiniGames.getInstance().getStringFormatter().displayErrorMessage(player,
|
||||
MiniGameMessage.ERROR_ARENA_TELEPORT_FAILED);
|
||||
newSession.triggerQuit(false, true);
|
||||
return false;
|
||||
} else {
|
||||
// Update the player's state to follow the arena's rules
|
||||
newSession.getEntryState().setArenaState();
|
||||
@ -109,7 +108,6 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
||||
player.getInventory().addItem(GUIHelper.getGUIOpenItem());
|
||||
MiniGames.getInstance().getStringFormatter().displaySuccessMessage(player,
|
||||
MiniGameMessage.SUCCESS_ARENA_JOINED);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ public class ParkourConfiguration extends MiniGameConfiguration {
|
||||
private boolean mustDoGroupedInSequence;
|
||||
private boolean ignoreRecordsUntilGroupBeatenOnce;
|
||||
private Set<Material> killPlaneBlocks;
|
||||
private Set<Material> obstacleBlocks;
|
||||
|
||||
/**
|
||||
* Instantiates a new dropper configuration
|
||||
@ -63,12 +64,22 @@ public class ParkourConfiguration extends MiniGameConfiguration {
|
||||
return new HashSet<>(this.killPlaneBlocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all types of blocks constituting parkour arena's obstacle blocks
|
||||
*
|
||||
* @return <p>The types of blocks constituting parkour arena's obstacle blocks</p>
|
||||
*/
|
||||
public Set<Material> getObstacleBlocks() {
|
||||
return new HashSet<>(this.obstacleBlocks);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load() {
|
||||
this.enforceCheckpointOrder = configuration.getBoolean(rootNode + "enforceCheckpointOrder", false);
|
||||
this.mustDoGroupedInSequence = configuration.getBoolean(rootNode + "mustDoGroupedInSequence", true);
|
||||
this.ignoreRecordsUntilGroupBeatenOnce = configuration.getBoolean(rootNode + "ignoreRecordsUntilGroupBeatenOnce", false);
|
||||
this.killPlaneBlocks = loadMaterialList(rootNode + "killPlaneBlocks");
|
||||
this.obstacleBlocks = loadMaterialList(rootNode + "obstacleBlocks");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -82,6 +93,10 @@ public class ParkourConfiguration extends MiniGameConfiguration {
|
||||
for (Material material : killPlaneBlocks) {
|
||||
builder.append("\n - ").append(material.name());
|
||||
}
|
||||
builder.append("\n" + "Obstacle blocks: ");
|
||||
for (Material material : obstacleBlocks) {
|
||||
builder.append("\n - ").append(material.name());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package net.knarcraft.minigames.listener;
|
||||
import net.knarcraft.minigames.MiniGames;
|
||||
import net.knarcraft.minigames.arena.Arena;
|
||||
import net.knarcraft.minigames.arena.ArenaSession;
|
||||
import net.knarcraft.minigames.arena.dropper.DropperArena;
|
||||
import net.knarcraft.minigames.arena.dropper.DropperArenaGameMode;
|
||||
import net.knarcraft.minigames.arena.dropper.DropperArenaSession;
|
||||
import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
||||
@ -14,11 +15,13 @@ import net.knarcraft.minigames.config.ParkourConfiguration;
|
||||
import net.knarcraft.minigames.config.SharedConfiguration;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -32,6 +35,8 @@ import java.util.Set;
|
||||
*/
|
||||
public class MoveListener implements Listener {
|
||||
|
||||
private static final BoundingBox fullBlockBox = new BoundingBox(0, 0, 0, 1, 1, 1);
|
||||
|
||||
private final DropperConfiguration dropperConfiguration;
|
||||
private final ParkourConfiguration parkourConfiguration;
|
||||
|
||||
@ -49,12 +54,15 @@ public class MoveListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
// Ignore if no actual movement is happening
|
||||
if (event.getFrom().equals(event.getTo()) || event.getTo() == null) {
|
||||
if (event.getTo() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArenaSession session = MiniGames.getInstance().getSession(event.getPlayer().getUniqueId());
|
||||
if (session instanceof DropperArenaSession dropperSession) {
|
||||
if (event.getFrom().equals(event.getTo())) {
|
||||
return;
|
||||
}
|
||||
doDropperArenaChecks(event, dropperSession);
|
||||
} else if (session instanceof ParkourArenaSession parkourSession) {
|
||||
doParkourArenaChecks(event, parkourSession);
|
||||
@ -68,8 +76,7 @@ public class MoveListener implements Listener {
|
||||
* @param arenaSession <p>The dropper session of the player triggering the event</p>
|
||||
*/
|
||||
private void doParkourArenaChecks(@NotNull PlayerMoveEvent event, ParkourArenaSession arenaSession) {
|
||||
// Ignore movement which won't cause the player's block to change
|
||||
if (event.getTo() == null || event.getFrom().getBlock() == event.getTo().getBlock()) {
|
||||
if (event.getTo() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -189,30 +196,140 @@ public class MoveListener implements Listener {
|
||||
* @param toLocation <p>The location the player's session is about to hit</p>
|
||||
* @return <p>True if a special block has been hit</p>
|
||||
*/
|
||||
private boolean checkForSpecialBlock(ArenaSession arenaSession, Location toLocation) {
|
||||
private boolean checkForSpecialBlock(@NotNull ArenaSession arenaSession, @NotNull Location toLocation) {
|
||||
SharedConfiguration sharedConfiguration = MiniGames.getInstance().getSharedConfiguration();
|
||||
double liquidDepth = sharedConfiguration.getLiquidHitBoxDepth();
|
||||
double solidDepth = sharedConfiguration.getSolidHitBoxDistance();
|
||||
|
||||
double liquidDepth = sharedConfiguration.getLiquidHitBoxDepth();
|
||||
Arena arena = arenaSession.getArena();
|
||||
|
||||
// For water, only trigger when the player enters the water, but trigger earlier for everything else
|
||||
double depth = arena.winLocationIsSolid() ? solidDepth : liquidDepth;
|
||||
for (Block block : getBlocksBeneathLocation(toLocation, depth)) {
|
||||
Set<Block> potentialWinTriggerBlocks;
|
||||
if (arena.winLocationIsSolid()) {
|
||||
potentialWinTriggerBlocks = getBlocksBeneathLocation(toLocation, solidDepth);
|
||||
} else {
|
||||
potentialWinTriggerBlocks = getBlocksBeneathLocation(toLocation, liquidDepth);
|
||||
}
|
||||
for (Block block : potentialWinTriggerBlocks) {
|
||||
if (arena.willCauseWin(block)) {
|
||||
arenaSession.triggerWin();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the player is about to hit a non-air and non-liquid block
|
||||
for (Block block : getBlocksBeneathLocation(toLocation, solidDepth)) {
|
||||
if (!block.getType().isAir() && arena.willCauseLoss(block)) {
|
||||
if (arena instanceof DropperArena) {
|
||||
// Check if the player is about to hit a non-air and non-liquid block
|
||||
for (Block block : getBlocksBeneathLocation(toLocation, solidDepth)) {
|
||||
if (!block.getType().isAir() && !block.isLiquid() && arena.willCauseLoss(block)) {
|
||||
arenaSession.triggerLoss();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the player has entered a liquid that causes a loss
|
||||
for (Block block : getBlocksBeneathLocation(toLocation, liquidDepth)) {
|
||||
if (block.isLiquid() && arena.willCauseLoss(block)) {
|
||||
arenaSession.triggerLoss();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (arena instanceof ParkourArena) {
|
||||
return checkParkourDeathBlock((ParkourArenaSession) arenaSession, toLocation);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a player is moving onto a block part of the parkour death plane
|
||||
*
|
||||
* @param arenaSession <p>The player's arena session</p>
|
||||
* @param toLocation <p>The location the player is moving to</p>
|
||||
* @return <p>True if the player hit a death block</p>
|
||||
*/
|
||||
private boolean checkParkourDeathBlock(@NotNull ParkourArenaSession arenaSession,
|
||||
@NotNull Location toLocation) {
|
||||
// A simple check, only for kill blocks
|
||||
if (isOnKillBlock(arenaSession, toLocation)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// As the check for obstacle blocks is extensive, it's skipped if possible
|
||||
Set<Material> obstacleBlocks = arenaSession.getArena().getObstacleBlocks();
|
||||
if (obstacleBlocks.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a hit-box approximate to the player's real hit-box
|
||||
double playerHeight = 1.8;
|
||||
Player player = Bukkit.getPlayer(arenaSession.getEntryState().getPlayerId());
|
||||
if (player != null && player.isSneaking()) {
|
||||
playerHeight = 1.5;
|
||||
}
|
||||
BoundingBox playerBox = new BoundingBox(-0.05, -0.05, -0.05,
|
||||
0.6 + 0.05, playerHeight + 0.05, 0.6 + 0.05).shift(
|
||||
toLocation).shift(-0.3, -0.05, -0.3);
|
||||
BoundingBox playerPassableBox = new BoundingBox(0.2, 0.5, 0.2,
|
||||
0.4, playerHeight - 0.5, 0.4).shift(
|
||||
toLocation).shift(-0.3, 0, -0.3);
|
||||
Set<Block> possiblyHitBlocks = new HashSet<>();
|
||||
possiblyHitBlocks.addAll(getBlocksBeneathLocation(toLocation, 0, 0.01));
|
||||
possiblyHitBlocks.addAll(getBlocksBeneathLocation(toLocation, 1, 0.01));
|
||||
possiblyHitBlocks.addAll(getBlocksBeneathLocation(toLocation, -1, 0.01));
|
||||
possiblyHitBlocks.addAll(getBlocksBeneathLocation(toLocation, -2, 0.01));
|
||||
|
||||
for (Block block : possiblyHitBlocks) {
|
||||
if (!obstacleBlocks.contains(block.getType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// For liquids, or anything without a proper collision shape, trigger collision if the player is partly
|
||||
// inside when treated as a full block
|
||||
if (block.isLiquid() || block.getCollisionShape().getBoundingBoxes().isEmpty()) {
|
||||
if (playerPassableBox.overlaps(fullBlockBox.clone().shift(block.getLocation()))) {
|
||||
arenaSession.triggerLoss();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the player's actual hit-box is intersecting with a block
|
||||
for (BoundingBox boundingBox : block.getCollisionShape().getBoundingBoxes()) {
|
||||
// A collision shape's bounding box is relative to 0,0 and therefore must be adjusted to the block's
|
||||
// location. Then overlap is checked by the player's collision box and the shifted bounding box.
|
||||
if (playerBox.overlaps(boundingBox.clone().shift(block.getLocation()))) {
|
||||
arenaSession.triggerLoss();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* As simple check for whether a player is moving on top of a kill block
|
||||
*
|
||||
* @param arenaSession <p>The arena session the player is in</p>
|
||||
* @param toLocation <p>The location the player is moving to</p>
|
||||
* @return <p>True if the player is on a kill block, and a loss has been triggered</p>
|
||||
*/
|
||||
private boolean isOnKillBlock(ParkourArenaSession arenaSession, Location toLocation) {
|
||||
// If the player is standing on a non-full block, event.getTo will give the correct block, but if not, the
|
||||
// block below has to be checked instead.
|
||||
Set<Block> blocksBelow = getBlocksBeneathLocation(toLocation, 0);
|
||||
Set<Material> killPlaneBlocks = arenaSession.getArena().getKillPlaneBlocks();
|
||||
for (Block block : blocksBelow) {
|
||||
if (block.getType().isAir()) {
|
||||
block = block.getLocation().clone().subtract(0, 0.2, 0).getBlock();
|
||||
// Only trigger hit detection for passable blocks if the player is in the block
|
||||
if (block.isPassable()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (killPlaneBlocks.contains(block.getType())) {
|
||||
arenaSession.triggerLoss();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -223,12 +340,31 @@ public class MoveListener implements Listener {
|
||||
* @return <p>The blocks beneath the player</p>
|
||||
*/
|
||||
private Set<Block> getBlocksBeneathLocation(Location location, double depth) {
|
||||
return getBlocksBeneathLocation(location, depth, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blocks at the given location that will be affected by the player's hit-box
|
||||
*
|
||||
* @param location <p>The location to check</p>
|
||||
* @param extraRange <p>Extra range of the square used for finding blocks</p>
|
||||
* @return <p>The blocks beneath the player</p>
|
||||
*/
|
||||
private Set<Block> getBlocksBeneathLocation(Location location, double depth, double extraRange) {
|
||||
Set<Block> blocksBeneath = new HashSet<>();
|
||||
double halfPlayerWidth = 0.3;
|
||||
double halfPlayerWidth = 0.3 + extraRange;
|
||||
blocksBeneath.add(location.clone().subtract(halfPlayerWidth, depth, halfPlayerWidth).getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(-halfPlayerWidth, depth, halfPlayerWidth).getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(halfPlayerWidth, depth, -halfPlayerWidth).getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(-halfPlayerWidth, depth, -halfPlayerWidth).getBlock());
|
||||
// Once a certain size is reached, if the player is in the centre of a block, 9 must be accounted for
|
||||
if (halfPlayerWidth > 0.5) {
|
||||
blocksBeneath.add(location.getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(halfPlayerWidth, depth, 0).getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(-halfPlayerWidth, depth, 0).getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(0, depth, -halfPlayerWidth).getBlock());
|
||||
blocksBeneath.add(location.clone().subtract(0, depth, halfPlayerWidth).getBlock());
|
||||
}
|
||||
return blocksBeneath;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ public class DropperRecordExpansion extends RecordExpansion {
|
||||
|
||||
@Override
|
||||
protected @NotNull ArenaGameMode parseGameMode(@NotNull String gameMode) {
|
||||
return DropperArenaGameMode.matchGamemode(gameMode);
|
||||
return DropperArenaGameMode.matchGameMode(gameMode);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -313,8 +313,8 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
||||
private String getRecordData(@NotNull InfoType infoType, @NotNull ArenaRecord<?> arenaRecord) {
|
||||
return switch (infoType) {
|
||||
case PLAYER -> getPlayerName(arenaRecord.getUserId());
|
||||
case VALUE -> arenaRecord.getRecord().toString();
|
||||
case COMBINED -> getPlayerName(arenaRecord.getUserId()) + ": " + arenaRecord.getRecord().toString();
|
||||
case VALUE -> arenaRecord.getAsString();
|
||||
case COMBINED -> getPlayerName(arenaRecord.getUserId()) + ": " + arenaRecord.getAsString();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -97,22 +98,49 @@ public final class DropperArenaStorageHelper {
|
||||
YamlConfiguration configuration = new YamlConfiguration();
|
||||
ConfigurationSection arenaSection = configuration.createSection(dropperArenasConfigurationSection);
|
||||
for (DropperArena arena : arenas.values()) {
|
||||
//Note: While the arena name is used as the key, as the key has to be sanitized, the un-sanitized arena name
|
||||
// must be stored as well
|
||||
@NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString());
|
||||
configSection.set(DropperArenaStorageKey.ID.getKey(), new SerializableUUID(arena.getArenaId()));
|
||||
configSection.set(DropperArenaStorageKey.NAME.getKey(), arena.getArenaName());
|
||||
configSection.set(DropperArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation());
|
||||
configSection.set(DropperArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation());
|
||||
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());
|
||||
saveDropperArena(arenaSection, arena);
|
||||
}
|
||||
configuration.save(dropperArenaFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a single arena
|
||||
*
|
||||
* @param arena <p>The arena to save</p>
|
||||
* @throws IOException <p>If unable to write to the file</p>
|
||||
*/
|
||||
public static void saveSingleDropperArena(DropperArena arena) throws IOException {
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(dropperArenaFile);
|
||||
ConfigurationSection arenaSection = configuration.getConfigurationSection(dropperArenasConfigurationSection);
|
||||
if (arenaSection == null) {
|
||||
arenaSection = configuration.createSection(dropperArenasConfigurationSection);
|
||||
}
|
||||
saveDropperArena(arenaSection, arena);
|
||||
configuration.save(dropperArenaFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given configuration section with the arena's data, and stores arena data for the arena
|
||||
*
|
||||
* @param arenaSection <p>The configuration section to update</p>
|
||||
* @param arena <p>The arena to save</p>
|
||||
* @throws IOException <p>If unable to save the arena data</p>
|
||||
*/
|
||||
private static void saveDropperArena(ConfigurationSection arenaSection, DropperArena arena) throws IOException {
|
||||
//Note: While the arena name is used as the key, as the key has to be sanitized, the un-sanitized arena name
|
||||
// must be stored as well
|
||||
@NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString());
|
||||
configSection.set(DropperArenaStorageKey.ID.getKey(), new SerializableUUID(arena.getArenaId()));
|
||||
configSection.set(DropperArenaStorageKey.NAME.getKey(), arena.getArenaName());
|
||||
configSection.set(DropperArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation());
|
||||
configSection.set(DropperArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation());
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all arenas
|
||||
*
|
||||
@ -222,9 +250,14 @@ public final class DropperArenaStorageHelper {
|
||||
* @return <p>The loaded arena data</p>
|
||||
*/
|
||||
private static @Nullable DropperArenaData loadDropperArenaData(@NotNull UUID arenaId) {
|
||||
File arenaDataFile = getDropperArenaDataFile(arenaId);
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile);
|
||||
return (DropperArenaData) configuration.get(DropperArenaStorageKey.DATA.getKey());
|
||||
try {
|
||||
File arenaDataFile = getDropperArenaDataFile(arenaId);
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile);
|
||||
return (DropperArenaData) configuration.get(DropperArenaStorageKey.DATA.getKey());
|
||||
} catch (YAMLException exception) {
|
||||
MiniGames.log(Level.SEVERE, "Unable to load arena data from arena " + arenaId);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,23 +99,79 @@ public final class ParkourArenaStorageHelper {
|
||||
YamlConfiguration configuration = new YamlConfiguration();
|
||||
ConfigurationSection arenaSection = configuration.createSection(parkourArenasConfigurationSection);
|
||||
for (ParkourArena arena : arenas.values()) {
|
||||
//Note: While the arena name is used as the key, as the key has to be sanitized, the un-sanitized arena name
|
||||
// must be stored as well
|
||||
@NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString());
|
||||
configSection.set(ParkourArenaStorageKey.ID.getKey(), new SerializableUUID(arena.getArenaId()));
|
||||
configSection.set(ParkourArenaStorageKey.NAME.getKey(), arena.getArenaName());
|
||||
configSection.set(ParkourArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation());
|
||||
configSection.set(ParkourArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation());
|
||||
configSection.set(ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
|
||||
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());
|
||||
saveParkourArena(arenaSection, arena);
|
||||
}
|
||||
configuration.save(parkourArenaFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a single arena
|
||||
*
|
||||
* @param arena <p>The arena to save</p>
|
||||
* @throws IOException <p>If unable to write to the file</p>
|
||||
*/
|
||||
public static void saveSingleParkourArena(ParkourArena arena) throws IOException {
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(parkourArenaFile);
|
||||
ConfigurationSection arenaSection = configuration.getConfigurationSection(parkourArenasConfigurationSection);
|
||||
if (arenaSection == null) {
|
||||
arenaSection = configuration.createSection(parkourArenasConfigurationSection);
|
||||
}
|
||||
saveParkourArena(arenaSection, arena);
|
||||
configuration.save(parkourArenaFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given configuration section with the arena's data, and stores arena data for the arena
|
||||
*
|
||||
* @param arenaSection <p>The configuration section to update</p>
|
||||
* @param arena <p>The arena to save</p>
|
||||
* @throws IOException <p>If unable to save the arena data</p>
|
||||
*/
|
||||
private static void saveParkourArena(ConfigurationSection arenaSection, ParkourArena arena) throws IOException {
|
||||
//Note: While the arena name is used as the key, as the key has to be sanitized, the un-sanitized arena name
|
||||
// must be stored as well
|
||||
@NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString());
|
||||
configSection.set(ParkourArenaStorageKey.ID.getKey(), new SerializableUUID(arena.getArenaId()));
|
||||
configSection.set(ParkourArenaStorageKey.NAME.getKey(), arena.getArenaName());
|
||||
configSection.set(ParkourArenaStorageKey.SPAWN_LOCATION.getKey(), arena.getSpawnLocation());
|
||||
configSection.set(ParkourArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation());
|
||||
configSection.set(ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
|
||||
configSection.set(ParkourArenaStorageKey.WIN_LOCATION.getKey(), arena.getWinLocation());
|
||||
configSection.set(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey(), getKillPlaneBlocks(arena));
|
||||
configSection.set(ParkourArenaStorageKey.OBSTACLE_BLOCKS.getKey(), getObstacleBlocks(arena));
|
||||
configSection.set(ParkourArenaStorageKey.CHECKPOINTS.getKey(), arena.getCheckpoints());
|
||||
RewardStorageHelper.saveRewards(arena, configSection, ParkourArenaStorageKey.REWARDS.getKey());
|
||||
saveParkourArenaData(arena.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of the kill plane blocks for the given arena
|
||||
*
|
||||
* @param arena <p>The arena to get kill plane blocks for</p>
|
||||
* @return <p>The kill plane blocks</p>
|
||||
*/
|
||||
private static List<String> getKillPlaneBlocks(ParkourArena arena) {
|
||||
if (arena.getKillPlaneBlockNames() == null) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
return new ArrayList<>(arena.getKillPlaneBlockNames());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of the obstacle blocks for the given arena
|
||||
*
|
||||
* @param arena <p>The arena to get obstacle blocks for</p>
|
||||
* @return <p>The obstacle blocks</p>
|
||||
*/
|
||||
private static List<String> getObstacleBlocks(ParkourArena arena) {
|
||||
if (arena.getObstacleBlockNames() == null) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
return new ArrayList<>(arena.getObstacleBlockNames());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all arenas
|
||||
*
|
||||
@ -163,7 +219,20 @@ public final class ParkourArenaStorageHelper {
|
||||
Location winLocation = (Location) configurationSection.get(ParkourArenaStorageKey.WIN_LOCATION.getKey());
|
||||
SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get(
|
||||
ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey());
|
||||
List<?> killPlaneBlockNames = configurationSection.getList(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey());
|
||||
List<?> killPlaneBlockNamesList = configurationSection.getList(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey());
|
||||
Set<String> killPlaneBlockNames;
|
||||
if (killPlaneBlockNamesList == null) {
|
||||
killPlaneBlockNames = null;
|
||||
} else {
|
||||
killPlaneBlockNames = new HashSet<>((List<String>) killPlaneBlockNamesList);
|
||||
}
|
||||
List<?> obstacleBlockNamesList = configurationSection.getList(ParkourArenaStorageKey.OBSTACLE_BLOCKS.getKey());
|
||||
Set<String> obstacleBlockNames;
|
||||
if (obstacleBlockNamesList == null) {
|
||||
obstacleBlockNames = null;
|
||||
} else {
|
||||
obstacleBlockNames = new HashSet<>((List<String>) obstacleBlockNamesList);
|
||||
}
|
||||
List<Location> checkpoints = (List<Location>) configurationSection.get(ParkourArenaStorageKey.CHECKPOINTS.getKey());
|
||||
|
||||
Map<RewardCondition, Set<Reward>> rewards = RewardStorageHelper.loadRewards(configurationSection,
|
||||
@ -195,7 +264,7 @@ public final class ParkourArenaStorageHelper {
|
||||
}
|
||||
|
||||
return new ParkourArena(arenaId, arenaName, spawnLocation, exitLocation, winBlockType.getRawValue(), winLocation,
|
||||
(Set<String>) killPlaneBlockNames, checkpoints, rewards, arenaData,
|
||||
killPlaneBlockNames, obstacleBlockNames, checkpoints, rewards, arenaData,
|
||||
MiniGames.getInstance().getParkourArenaHandler());
|
||||
}
|
||||
|
||||
|
@ -104,11 +104,30 @@ public final class TabCompleteHelper {
|
||||
tabCompleteSuggestions.put(EditablePropertyType.BLOCK_TYPE, getBlockTypeSuggestions());
|
||||
tabCompleteSuggestions.put(EditablePropertyType.CHECKPOINT_CLEAR, getCheckpointClearSuggestions());
|
||||
tabCompleteSuggestions.put(EditablePropertyType.MATERIAL_LIST, getMaterialListSuggestions());
|
||||
tabCompleteSuggestions.put(EditablePropertyType.DOUBLE, getDoubleSuggestions());
|
||||
}
|
||||
|
||||
return tabCompleteSuggestions.get(propertyType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets suggestions for double values
|
||||
*
|
||||
* @return <p>A list of suggestions</p>
|
||||
*/
|
||||
private static List<String> getDoubleSuggestions() {
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
suggestions.add("0");
|
||||
suggestions.add("0.01");
|
||||
suggestions.add("0.1");
|
||||
suggestions.add("0.2");
|
||||
suggestions.add("0.3");
|
||||
suggestions.add("0.4");
|
||||
suggestions.add("0.5");
|
||||
suggestions.add("1");
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets suggestions for a list of materials
|
||||
*
|
||||
@ -118,6 +137,7 @@ public final class TabCompleteHelper {
|
||||
List<String> suggestions = new ArrayList<>();
|
||||
suggestions.add("LAVA,MAGMA_BLOCK");
|
||||
suggestions.add("WATER,MAGMA_BLOCK,LAVA,+BUTTONS,+CORALS");
|
||||
suggestions.add("CHAIN,END_ROD,LIGHTNING_ROD");
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,12 @@ parkour:
|
||||
killPlaneBlocks:
|
||||
- LAVA
|
||||
- MAGMA_BLOCK
|
||||
|
||||
# The blocks treated as obstacles in a parkour arena, which will trigger a loss in any direction
|
||||
obstacleBlocks:
|
||||
- END_ROD
|
||||
- LIGHTNING_ROD
|
||||
- CHAIN
|
||||
dropper:
|
||||
# Whether to block using the shift key to drop faster than the intended drop speed
|
||||
blockSneaking: true
|
||||
@ -63,6 +69,7 @@ dropper:
|
||||
- +BUTTONS
|
||||
- +CORALS
|
||||
- +WALL_CORALS
|
||||
- LIGHT
|
||||
shared:
|
||||
# This decides how far inside a non-solid block the player must go before detection triggers (-1, 0). The closer to -1
|
||||
# it is, the more accurate it will seem to the player, but the likelihood of not detecting the hit increases.
|
||||
|
@ -82,15 +82,15 @@ commands:
|
||||
aliases:
|
||||
- dcreate
|
||||
permission: minigames.create.dropper
|
||||
usage: |
|
||||
/<command> <arena> <property> [new value]
|
||||
- Valid properties: name, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity, winBlockType
|
||||
usage: /<command> <arena>
|
||||
description: Used to create a new dropper arena
|
||||
dropperEdit:
|
||||
aliases:
|
||||
- dedit
|
||||
permission: minigames.edit.dropper
|
||||
usage: /<command> (Details not finalized)
|
||||
usage: |
|
||||
/<command> <arena> <property> [new value]
|
||||
- Valid properties: name, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity, winBlockType
|
||||
description: Used to edit an existing dropper arena
|
||||
dropperRemove:
|
||||
aliases:
|
||||
@ -143,19 +143,19 @@ commands:
|
||||
aliases:
|
||||
- pcreate
|
||||
permission: minigames.create.parkour
|
||||
usage: |
|
||||
/<command> <arena> <property> [new value]
|
||||
- Valid properties: name, spawnLocation, exitLocation, winBlockType, winLocation, checkpointAdd, checkpointClear, killPlaneBlocks
|
||||
usage: /<command> <arena>
|
||||
description: Used to create a new parkour arena
|
||||
parkourEdit:
|
||||
aliases:
|
||||
- pedit
|
||||
permission: minigames.edit.parkour
|
||||
usage: /<command> (Details not finalized)
|
||||
usage: |
|
||||
/<command> <arena> <property> [new value]
|
||||
- Valid properties: name, spawnLocation, exitLocation, winBlockType, winLocation, checkpointAdd, checkpointClear, killPlaneBlocks
|
||||
description: Used to edit an existing parkour arena
|
||||
parkourRemove:
|
||||
aliases:
|
||||
- dremove
|
||||
- premove
|
||||
permission: minigames.remove.parkour
|
||||
usage: /<command> <arena>
|
||||
description: Used to remove an existing parkour arena
|
||||
|
@ -1,51 +0,0 @@
|
||||
package net.knarcraft.minigames.arena;
|
||||
|
||||
import net.knarcraft.minigames.arena.dropper.DropperArenaGroup;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Tests for arena dropper groups
|
||||
*/
|
||||
public class MiniGamesArenaGroupTest {
|
||||
|
||||
@Test
|
||||
public void swapTest() {
|
||||
/*
|
||||
This test makes sure the order of arenas is as expected when the arenas are added to a group. It also makes
|
||||
sure that swapping two items works as expected.
|
||||
*/
|
||||
|
||||
DropperArenaGroup arenaGroup = new DropperArenaGroup("test");
|
||||
UUID arena1Id = UUID.randomUUID();
|
||||
UUID arena2Id = UUID.randomUUID();
|
||||
UUID arena3Id = UUID.randomUUID();
|
||||
UUID arena4Id = UUID.randomUUID();
|
||||
|
||||
arenaGroup.addArena(arena1Id);
|
||||
arenaGroup.addArena(arena2Id);
|
||||
arenaGroup.addArena(arena3Id);
|
||||
arenaGroup.addArena(arena4Id);
|
||||
|
||||
List<UUID> initialOrder = new ArrayList<>();
|
||||
initialOrder.add(arena1Id);
|
||||
initialOrder.add(arena2Id);
|
||||
initialOrder.add(arena3Id);
|
||||
initialOrder.add(arena4Id);
|
||||
Assertions.assertEquals(initialOrder, arenaGroup.getArenas());
|
||||
|
||||
arenaGroup.swapArenas(1, 3);
|
||||
|
||||
List<UUID> swapped = new ArrayList<>();
|
||||
swapped.add(arena1Id);
|
||||
swapped.add(arena4Id);
|
||||
swapped.add(arena3Id);
|
||||
swapped.add(arena2Id);
|
||||
Assertions.assertEquals(swapped, arenaGroup.getArenas());
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user