mirror of
https://github.com/SunNetservers/MiniGames.git
synced 2025-07-07 16:44:46 +02:00
Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
430f340fd4 | |||
f09dcbe7ff | |||
901b052b25 | |||
2ec15c69c7 | |||
d101c7ed02 | |||
bfc0eb7334 | |||
eceb7fc6d2 | |||
fb68c18fe6 | |||
98b5ea5abe | |||
87788e60a3 | |||
3a68d30044 | |||
fdd6d94102 | |||
a1f76bcfc2 | |||
d124c0948b | |||
8574dfebbb | |||
f2328ecfa3 | |||
a632de5b1f | |||
aa39243232 | |||
0360ada849 | |||
81e652b4ff | |||
d7e950c53e | |||
c8fbdec64f | |||
09f29e5f67 | |||
7213bd0c70 | |||
a23d0c769f | |||
142cd5339b | |||
b063bd1088 | |||
310802b42d | |||
fc6bd33e87 | |||
ccf43060dc | |||
a498e9bad0 | |||
d8bf77d317 | |||
162aff0c1f | |||
a7cfe36c72 | |||
407acf0ea2 | |||
b6bf22d1c7 | |||
67144fec06 | |||
e52732433a | |||
776fc5a757 | |||
1e7cdf02fc | |||
f3d8be8be2 |
71
README.md
71
README.md
@ -13,6 +13,11 @@ playing, simply use `/parkourjoin <name>`, where \<name> is the same as you spec
|
|||||||
To modify the arena, use `/parkouredit <name> <property> <value>`. Use `/parkouredit checkpointAdd here` to add a
|
To modify the arena, use `/parkouredit <name> <property> <value>`. Use `/parkouredit checkpointAdd here` to add a
|
||||||
checkpoint at your current location.
|
checkpoint at your current location.
|
||||||
|
|
||||||
|
Special Parkour behavior: If a lever is toggled while in a parkour arena, that lever is saved, and automatically turned
|
||||||
|
off once the last arena player leaves, or the last arena player restarts. This allows parkour arenas where lever toggles
|
||||||
|
are required for progression. It is however possible to cheat by having one player go first, toggling required levers,
|
||||||
|
and then going through much faster.
|
||||||
|
|
||||||
## Permissions
|
## Permissions
|
||||||
|
|
||||||
The only permission normal players will need is `minigames.join` which is set to true by default.
|
The only permission normal players will need is `minigames.join` which is set to true by default.
|
||||||
@ -99,7 +104,9 @@ This reward requires an argument which is the permission string you want to gran
|
|||||||
###### Command
|
###### Command
|
||||||
|
|
||||||
The reward requires the command as an argument. Type the full command with spaces and everything, but omit the `/` at
|
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
|
###### Item
|
||||||
|
|
||||||
@ -135,13 +142,15 @@ This command allows editing the specified property for the specified dropper are
|
|||||||
These are all the options that can be changed for an arena.
|
These are all the options that can be changed for an arena.
|
||||||
|
|
||||||
| Option | Details |
|
| Option | Details |
|
||||||
|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| name | The name of the arena. Used mainly to select the arena in commands. |
|
| name | The name of the arena. Used mainly to select the arena in commands. |
|
||||||
| spawnLocation | The spawn location of any player joining the arena. Use `56.546,64.0,44.45` to specify coordinates, or `here`, `this` or any other string to select your current location. |
|
| spawnLocation | The spawn location of any player joining the arena. Use `56.546,64.0,44.45` to specify coordinates, or `here`, `this` or any other string to select your current location. |
|
||||||
| exitLocation | The location players will be sent to when exiting the arena. If not set, the player will be sent to where they joined from. Valid values are the same as for spawnLocation. |
|
| exitLocation | The location players will be sent to when exiting the arena. If not set, the player will be sent to where they joined from. Valid values are the same as for spawnLocation. |
|
||||||
| verticalVelocity | The vertical velocity set for players in the arena (basically their falling speed). It must be greater than 0, but max 75. `12.565` and other decimals are allowed. |
|
| verticalVelocity | The vertical velocity set for players in the arena (basically their falling speed). It must be greater than 0, but max 75. `12.565` and other decimals are allowed. |
|
||||||
| horizontalVelocity | The horizontal velocity (technically fly speed) set for players in the arena. It must be between 0 and 1, and cannot be 0. Decimals are allowed. |
|
| horizontalVelocity | The horizontal velocity (technically fly speed) set for players in the arena. It must be between 0 and 1, and cannot be 0. Decimals are allowed. |
|
||||||
| winBlockType | The type of block players must hit to win the arena. It can be any material as long as it's a block, and not a type of air. |
|
| winBlockType | The type of block players must hit to win the arena. It can be any material as long as it's a block, and not a type of air. |
|
||||||
|
| allowedDamageCauses | A list of damage causes that can affect players in the arena. The damage is simulated, rather than real damage. Reaching 0 health triggers a loss. Note: Fall damage cannot be allowed. |
|
||||||
|
| lossTriggerDamageCauses | A list of damage causes that will trigger a loss for the arena. Useful for arenas where players need to dodge arrows or similar. Note: Fall damage already causes a loss. |
|
||||||
|
|
||||||
#### /dropperGroupSet
|
#### /dropperGroupSet
|
||||||
|
|
||||||
@ -203,7 +212,7 @@ This command allows editing the specified property for the specified parkour are
|
|||||||
These are all the options that can be changed for an arena.
|
These are all the options that can be changed for an arena.
|
||||||
|
|
||||||
| Option | Details |
|
| Option | Details |
|
||||||
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| name | The name of the arena. Used mainly to select the arena in commands. Note that underscore (_) cannot be used if you want to utilize placeholders, as it's used to split placeholder arguments. |
|
| name | The name of the arena. Used mainly to select the arena in commands. Note that underscore (_) cannot be used if you want to utilize placeholders, as it's used to split placeholder arguments. |
|
||||||
| spawnLocation | The spawn location of any player joining the arena. Use `56.546,64.0,44.45` to specify coordinates, or `here`, `this` or any other string to select your current location. |
|
| spawnLocation | The spawn location of any player joining the arena. Use `56.546,64.0,44.45` to specify coordinates, or `here`, `this` or any other string to select your current location. |
|
||||||
| exitLocation | The location players will be sent to when exiting the arena. If not set, the player will be sent to where they joined from. Valid values are the same as for spawnLocation. |
|
| exitLocation | The location players will be sent to when exiting the arena. If not set, the player will be sent to where they joined from. Valid values are the same as for spawnLocation. |
|
||||||
@ -211,14 +220,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. |
|
| 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). |
|
| 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. |
|
| 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. |
|
||||||
|
| allowedDamageCauses | A list of damage causes that can affect players in the arena. The damage is simulated, rather than real damage. Reaching 0 health triggers a loss. |
|
||||||
|
| lossTriggerDamageCauses | A list of damage causes that will trigger a loss for the arena. Useful for arenas where players need to dodge arrows or similar. |
|
||||||
|
|
||||||
## Configuration options
|
## Configuration options
|
||||||
|
|
||||||
### Shared
|
### Shared
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| 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. |
|
| 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. |
|
| 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. |
|
||||||
|
|
||||||
@ -246,6 +258,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 |
|
| 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. |
|
| 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. |
|
| 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:
|
#### blockWhitelist default:
|
||||||
|
|
||||||
@ -267,25 +280,61 @@ These are all the options that can be changed for an arena.
|
|||||||
- LAVA
|
- LAVA
|
||||||
- MAGMA_BLOCK
|
- MAGMA_BLOCK
|
||||||
|
|
||||||
## Record placeholders
|
#### obstacleBlocks default:
|
||||||
|
|
||||||
|
- END_ROD
|
||||||
|
- LIGHTNING_ROD
|
||||||
|
- CHAIN
|
||||||
|
|
||||||
|
## Placeholders
|
||||||
|
|
||||||
|
### Record Placeholders
|
||||||
|
|
||||||
Player records can be displayed on a leaderboard by using PlaceholderAPI. If you want to display a sign-based
|
Player records can be displayed on a leaderboard by using PlaceholderAPI. If you want to display a sign-based
|
||||||
leaderboard, you can use the [Placeholder Signs](https://git.knarcraft.net/EpicKnarvik97/PlaceholderSigns) plugin. The
|
leaderboard, you can use the [Placeholder Signs](https://git.knarcraft.net/EpicKnarvik97/PlaceholderSigns) plugin. The
|
||||||
format for the built-in placeholders is as follows:
|
format for the built-in placeholders is as follows:
|
||||||
|
|
||||||
`%gameMode_record_recordType_gameModeType_identifierType_identifier_recordPlacing_infoType%`
|
`%gameMode_record_recordType_gameModeType_identifierType_identifier_recordPosition_infoType%`
|
||||||
|
|
||||||
| Variable | Values | Description |
|
| Variable | Values | Description |
|
||||||
|----------------|-----------------------------|------------------------------------------------------------------------------------------------------------------------------------|
|
|----------------|----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| gameMode | dropper / parkour | A selection of which game-mode you are getting a record for |
|
| gameMode | dropper / parkour | A selection of which game-mode you are getting a record for |
|
||||||
| record | | This must be as-is. It's a selector in case placeholders are added for more than records. |
|
| record | | This must be as-is. It's a selector for the type of placeholder to get. |
|
||||||
| recordType | deaths / time | Selects the type of record to get (deaths or time). |
|
| recordType | deaths / time | Selects the type of record to get (deaths or time). |
|
||||||
| gameModeType | default / inverted / random | Selects the game-mode to get the record for. |
|
| gameModeType | default / inverted / random / hardcore | Selects the game-mode to get the record for. |
|
||||||
| identifierType | arena / group | The type of thing the following identifier points to (an arena or an arena group). |
|
| 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). |
|
| identifier | ? | An identifier (the name or UUID) for an arena or a group (whichever was chosen as identifierType). |
|
||||||
| recordPlacing | 1 / 2 / 3 / ... | The position of the record to get (1 = first place, 2 = second place, etc.). |
|
| recordPosition | 1 / 2 / 3 / ... | The position of the record to get (1 = first place, 2 = second place, etc.). |
|
||||||
| infoType | player / value / combined | The type of info to get. Player gets the player name, Value gets the value of the achieved record. Combined gets "Player: Record". |
|
| infoType | player / value / combined | The type of info to get. Player gets the player name, Value gets the value of the achieved record. Combined gets "Player: Record". |
|
||||||
|
|
||||||
|
### Player Placeholders
|
||||||
|
|
||||||
|
The number of currently playing players can be displayed using PlaceholderAPI. If you want to display a sign-based
|
||||||
|
leaderboard, you can use the [Placeholder Signs](https://git.knarcraft.net/EpicKnarvik97/PlaceholderSigns) plugin. The
|
||||||
|
format for the built-in placeholders is as follows:
|
||||||
|
|
||||||
|
`%gameMode_players_playing_gameModeType_identifierType_identifier_infoType_additionalSpecifier%`
|
||||||
|
|
||||||
|
| 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. |
|
||||||
|
| 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
|
## 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
|
Where a list of material is allowed, this plugin supports using material tags that specify a set of blocks. This makes
|
||||||
|
56
pom.xml
56
pom.xml
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>net.knarcraft</groupId>
|
<groupId>net.knarcraft</groupId>
|
||||||
<artifactId>MiniGames</artifactId>
|
<artifactId>MiniGames</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.3-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>MiniGames</name>
|
<name>MiniGames</name>
|
||||||
@ -31,7 +31,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.2.4</version>
|
<version>3.3.0</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
@ -40,6 +40,20 @@
|
|||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>net.knarcraft.knarlib</pattern>
|
||||||
|
<shadedPattern>net.knarcraft.minigames.lib.knarlib</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>net.knarcraft.knargui</pattern>
|
||||||
|
<shadedPattern>net.knarcraft.minigames.lib.knargui</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.jetbrains.annotations</pattern>
|
||||||
|
<shadedPattern>net.knarcraft.minigames.lib.annotations</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
<filters>
|
<filters>
|
||||||
<filter>
|
<filter>
|
||||||
<artifact>net.knarcraft:knarlib</artifact>
|
<artifact>net.knarcraft:knarlib</artifact>
|
||||||
@ -54,10 +68,10 @@
|
|||||||
</includes>
|
</includes>
|
||||||
</filter>
|
</filter>
|
||||||
<filter>
|
<filter>
|
||||||
<excludes>
|
<artifact>org.jetbrains:annotations</artifact>
|
||||||
<exclude>*.MF</exclude>
|
<includes>
|
||||||
<exclude>*.yml</exclude>
|
<include>org/jetbrains/annotations/**</include>
|
||||||
</excludes>
|
</includes>
|
||||||
</filter>
|
</filter>
|
||||||
</filters>
|
</filters>
|
||||||
</configuration>
|
</configuration>
|
||||||
@ -90,26 +104,24 @@
|
|||||||
<id>jitpack.io</id>
|
<id>jitpack.io</id>
|
||||||
<url>https://jitpack.io</url>
|
<url>https://jitpack.io</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>opencollab-snapshot</id>
|
||||||
|
<url>https://repo.opencollab.dev/main/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.spigotmc</groupId>
|
<groupId>org.spigotmc</groupId>
|
||||||
<artifactId>spigot-api</artifactId>
|
<artifactId>spigot-api</artifactId>
|
||||||
<version>1.20-R0.1-SNAPSHOT</version>
|
<version>1.21.4-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jetbrains</groupId>
|
<groupId>org.jetbrains</groupId>
|
||||||
<artifactId>annotations</artifactId>
|
<artifactId>annotations</artifactId>
|
||||||
<version>24.0.1</version>
|
<version>24.0.1</version>
|
||||||
<scope>provided</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.junit.jupiter</groupId>
|
|
||||||
<artifactId>junit-jupiter</artifactId>
|
|
||||||
<version>5.9.2</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.clip</groupId>
|
<groupId>me.clip</groupId>
|
||||||
@ -126,13 +138,25 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.knarcraft</groupId>
|
<groupId>net.knarcraft</groupId>
|
||||||
<artifactId>knarlib</artifactId>
|
<artifactId>knarlib</artifactId>
|
||||||
<version>1.2.3-SNAPSHOT</version>
|
<version>1.2.7</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.MilkBowl</groupId>
|
<groupId>com.github.MilkBowl</groupId>
|
||||||
<artifactId>VaultAPI</artifactId>
|
<artifactId>VaultAPI</artifactId>
|
||||||
<version>1.7</version>
|
<version>1.7.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.geysermc.geyser</groupId>
|
||||||
|
<artifactId>api</artifactId>
|
||||||
|
<version>2.2.0-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.geysermc.floodgate</groupId>
|
||||||
|
<artifactId>api</artifactId>
|
||||||
|
<version>2.2.2-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -70,8 +70,8 @@ import net.knarcraft.minigames.listener.MoveListener;
|
|||||||
import net.knarcraft.minigames.listener.PlayerStateChangeListener;
|
import net.knarcraft.minigames.listener.PlayerStateChangeListener;
|
||||||
import net.knarcraft.minigames.manager.EconomyManager;
|
import net.knarcraft.minigames.manager.EconomyManager;
|
||||||
import net.knarcraft.minigames.manager.PermissionManager;
|
import net.knarcraft.minigames.manager.PermissionManager;
|
||||||
import net.knarcraft.minigames.placeholder.DropperRecordExpansion;
|
import net.knarcraft.minigames.placeholder.DropperExpansion;
|
||||||
import net.knarcraft.minigames.placeholder.ParkourRecordExpansion;
|
import net.knarcraft.minigames.placeholder.ParkourExpansion;
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import net.milkbowl.vault.economy.Economy;
|
import net.milkbowl.vault.economy.Economy;
|
||||||
import net.milkbowl.vault.permission.Permission;
|
import net.milkbowl.vault.permission.Permission;
|
||||||
@ -102,8 +102,8 @@ public final class MiniGames extends JavaPlugin {
|
|||||||
private ParkourConfiguration parkourConfiguration;
|
private ParkourConfiguration parkourConfiguration;
|
||||||
private DropperArenaHandler dropperArenaHandler;
|
private DropperArenaHandler dropperArenaHandler;
|
||||||
private ArenaPlayerRegistry<DropperArena> dropperArenaPlayerRegistry;
|
private ArenaPlayerRegistry<DropperArena> dropperArenaPlayerRegistry;
|
||||||
private DropperRecordExpansion dropperRecordExpansion;
|
private DropperExpansion dropperExpansion;
|
||||||
private ParkourRecordExpansion parkourRecordExpansion;
|
private ParkourExpansion parkourExpansion;
|
||||||
private ParkourArenaHandler parkourArenaHandler;
|
private ParkourArenaHandler parkourArenaHandler;
|
||||||
private ArenaPlayerRegistry<ParkourArena> parkourArenaPlayerRegistry;
|
private ArenaPlayerRegistry<ParkourArena> parkourArenaPlayerRegistry;
|
||||||
private PlayerVisibilityManager playerVisibilityManager;
|
private PlayerVisibilityManager playerVisibilityManager;
|
||||||
@ -253,8 +253,8 @@ public final class MiniGames extends JavaPlugin {
|
|||||||
this.parkourConfiguration.load(this.getConfig());
|
this.parkourConfiguration.load(this.getConfig());
|
||||||
|
|
||||||
// Clear record caches
|
// Clear record caches
|
||||||
this.dropperRecordExpansion.clearCaches();
|
this.dropperExpansion.clearCaches();
|
||||||
this.parkourRecordExpansion.clearCaches();
|
this.parkourExpansion.clearCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -316,12 +316,12 @@ public final class MiniGames extends JavaPlugin {
|
|||||||
*/
|
*/
|
||||||
private void doPluginIntegration() {
|
private void doPluginIntegration() {
|
||||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||||
this.dropperRecordExpansion = new DropperRecordExpansion(this);
|
this.dropperExpansion = new DropperExpansion(this);
|
||||||
if (!this.dropperRecordExpansion.register()) {
|
if (!this.dropperExpansion.register()) {
|
||||||
log(Level.WARNING, "Unable to register PlaceholderAPI dropper expansion!");
|
log(Level.WARNING, "Unable to register PlaceholderAPI dropper expansion!");
|
||||||
}
|
}
|
||||||
this.parkourRecordExpansion = new ParkourRecordExpansion(this);
|
this.parkourExpansion = new ParkourExpansion(this);
|
||||||
if (!this.parkourRecordExpansion.register()) {
|
if (!this.parkourExpansion.register()) {
|
||||||
log(Level.WARNING, "Unable to register PlaceholderAPI parkour expansion!");
|
log(Level.WARNING, "Unable to register PlaceholderAPI parkour expansion!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,8 @@ import java.util.logging.Level;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractArenaPlayerRegistry<K extends Arena> implements ArenaPlayerRegistry<K> {
|
public abstract class AbstractArenaPlayerRegistry<K extends Arena> implements ArenaPlayerRegistry<K> {
|
||||||
|
|
||||||
private final Map<UUID, ArenaSession> arenaPlayers = new HashMap<>();
|
private final Map<Arena, Set<UUID>> arenaPlayers = new HashMap<>();
|
||||||
|
private final Map<UUID, ArenaSession> arenaSessions = new HashMap<>();
|
||||||
private final Map<UUID, PlayerEntryState> entryStates = new HashMap<>();
|
private final Map<UUID, PlayerEntryState> entryStates = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,19 +31,25 @@ public abstract class AbstractArenaPlayerRegistry<K extends Arena> implements Ar
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Set<UUID> getPlayingPlayers() {
|
@NotNull
|
||||||
return arenaPlayers.keySet();
|
public Set<UUID> getPlayingPlayers() {
|
||||||
|
return arenaSessions.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable PlayerEntryState getEntryState(@NotNull UUID playerId) {
|
@Nullable
|
||||||
|
public PlayerEntryState getEntryState(@NotNull UUID playerId) {
|
||||||
return this.entryStates.get(playerId);
|
return this.entryStates.get(playerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerPlayer(@NotNull UUID playerId, @NotNull ArenaSession arenaSession) {
|
public void registerPlayer(@NotNull UUID playerId, @NotNull ArenaSession arenaSession) {
|
||||||
this.arenaPlayers.put(playerId, arenaSession);
|
this.arenaSessions.put(playerId, arenaSession);
|
||||||
this.entryStates.put(playerId, arenaSession.getEntryState());
|
this.entryStates.put(playerId, arenaSession.getEntryState());
|
||||||
|
|
||||||
|
this.arenaPlayers.putIfAbsent(arenaSession.getArena(), new HashSet<>());
|
||||||
|
this.arenaPlayers.get(arenaSession.getArena()).add(playerId);
|
||||||
|
|
||||||
this.saveEntryStates();
|
this.saveEntryStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,25 +67,38 @@ public abstract class AbstractArenaPlayerRegistry<K extends Arena> implements Ar
|
|||||||
this.saveEntryStates();
|
this.saveEntryStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.arenaPlayers.remove(playerId) != null;
|
if (this.arenaSessions.containsKey(playerId)) {
|
||||||
|
this.arenaPlayers.get(this.arenaSessions.get(playerId).getArena()).remove(playerId);
|
||||||
|
}
|
||||||
|
return this.arenaSessions.remove(playerId) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable ArenaSession getArenaSession(@NotNull UUID playerId) {
|
public @Nullable ArenaSession getArenaSession(@NotNull UUID playerId) {
|
||||||
return this.arenaPlayers.getOrDefault(playerId, null);
|
return this.arenaSessions.getOrDefault(playerId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeForArena(K arena, boolean immediately) {
|
public void removeForArena(@NotNull K arena, boolean immediately) {
|
||||||
Set<UUID> removed = new HashSet<>();
|
Set<UUID> removed = new HashSet<>();
|
||||||
for (Map.Entry<UUID, ArenaSession> entry : this.arenaPlayers.entrySet()) {
|
for (Map.Entry<UUID, ArenaSession> entry : this.arenaSessions.entrySet()) {
|
||||||
if (entry.getValue().getArena() == arena) {
|
if (entry.getValue().getArena() == arena) {
|
||||||
// Kick the player gracefully
|
// Kick the player gracefully
|
||||||
entry.getValue().triggerQuit(immediately, false);
|
entry.getValue().triggerQuit(immediately, false);
|
||||||
removed.add(entry.getKey());
|
removed.add(entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removed.forEach(this.arenaPlayers::remove);
|
removed.forEach(this.arenaSessions::remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Set<UUID> getPlayingPlayers(@NotNull K arena) {
|
||||||
|
if (arenaPlayers.containsKey(arena)) {
|
||||||
|
return arenaPlayers.get(arena);
|
||||||
|
} else {
|
||||||
|
return new HashSet<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,7 +124,7 @@ public abstract class AbstractArenaPlayerRegistry<K extends Arena> implements Ar
|
|||||||
for (PlayerEntryState entryState : entryStates) {
|
for (PlayerEntryState entryState : entryStates) {
|
||||||
this.entryStates.put(entryState.getPlayerId(), entryState);
|
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 " +
|
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 " +
|
"players leave in the middle of a game, or if the server crashes. MiniGames will do its best " +
|
||||||
"to fix the players' states.");
|
"to fix the players' states.");
|
||||||
|
@ -11,8 +11,10 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -34,6 +36,9 @@ public abstract class AbstractPlayerEntryState implements PlayerEntryState {
|
|||||||
private final boolean originalInvulnerable;
|
private final boolean originalInvulnerable;
|
||||||
private final boolean originalIsSwimming;
|
private final boolean originalIsSwimming;
|
||||||
private final boolean originalCollideAble;
|
private final boolean originalCollideAble;
|
||||||
|
private final double originalHealth;
|
||||||
|
private final float originalSaturation;
|
||||||
|
private final Collection<PotionEffect> originalPotionEffects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new abstract player entry state
|
* Instantiates a new abstract player entry state
|
||||||
@ -49,6 +54,14 @@ public abstract class AbstractPlayerEntryState implements PlayerEntryState {
|
|||||||
this.originalInvulnerable = player.isInvulnerable();
|
this.originalInvulnerable = player.isInvulnerable();
|
||||||
this.originalIsSwimming = player.isSwimming();
|
this.originalIsSwimming = player.isSwimming();
|
||||||
this.originalCollideAble = player.isCollidable();
|
this.originalCollideAble = player.isCollidable();
|
||||||
|
this.originalHealth = player.getHealth();
|
||||||
|
this.originalSaturation = player.getSaturation();
|
||||||
|
|
||||||
|
// Store and clear potion effects
|
||||||
|
this.originalPotionEffects = getPlayer().getActivePotionEffects();
|
||||||
|
for (PotionEffect potionEffect : this.originalPotionEffects) {
|
||||||
|
player.removePotionEffect(potionEffect.getType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,11 +75,15 @@ public abstract class AbstractPlayerEntryState implements PlayerEntryState {
|
|||||||
* @param originalInvulnerable <p>Whether the player was invulnerable before entering the arena</p>
|
* @param originalInvulnerable <p>Whether the player was invulnerable before entering the arena</p>
|
||||||
* @param originalIsSwimming <p>Whether the player was swimming before entering the arena</p>
|
* @param originalIsSwimming <p>Whether the player was swimming before entering the arena</p>
|
||||||
* @param originalCollideAble <p>Whether the player was collide-able before entering the arena</p>
|
* @param originalCollideAble <p>Whether the player was collide-able before entering the arena</p>
|
||||||
|
* @param originalPotionEffects <p>The potion effects applied to the player when joining</p>
|
||||||
|
* @param originalHealth <p>The health of the player when joining the arena</p>
|
||||||
|
* @param originalSaturation <p>The saturation of the player when joining the arena</p>
|
||||||
*/
|
*/
|
||||||
public AbstractPlayerEntryState(@NotNull UUID playerId, Location entryLocation,
|
public AbstractPlayerEntryState(@NotNull UUID playerId, @NotNull Location entryLocation,
|
||||||
boolean originalIsFlying, GameMode originalGameMode, boolean originalAllowFlight,
|
boolean originalIsFlying, GameMode originalGameMode, boolean originalAllowFlight,
|
||||||
boolean originalInvulnerable, boolean originalIsSwimming,
|
boolean originalInvulnerable, boolean originalIsSwimming,
|
||||||
boolean originalCollideAble) {
|
boolean originalCollideAble, @NotNull Collection<PotionEffect> originalPotionEffects,
|
||||||
|
double originalHealth, float originalSaturation) {
|
||||||
this.playerId = playerId;
|
this.playerId = playerId;
|
||||||
this.entryLocation = entryLocation;
|
this.entryLocation = entryLocation;
|
||||||
this.originalIsFlying = originalIsFlying;
|
this.originalIsFlying = originalIsFlying;
|
||||||
@ -75,6 +92,9 @@ public abstract class AbstractPlayerEntryState implements PlayerEntryState {
|
|||||||
this.originalInvulnerable = originalInvulnerable;
|
this.originalInvulnerable = originalInvulnerable;
|
||||||
this.originalIsSwimming = originalIsSwimming;
|
this.originalIsSwimming = originalIsSwimming;
|
||||||
this.originalCollideAble = originalCollideAble;
|
this.originalCollideAble = originalCollideAble;
|
||||||
|
this.originalPotionEffects = originalPotionEffects;
|
||||||
|
this.originalHealth = originalHealth;
|
||||||
|
this.originalSaturation = originalSaturation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -100,7 +120,13 @@ public abstract class AbstractPlayerEntryState implements PlayerEntryState {
|
|||||||
player.setGameMode(this.originalGameMode);
|
player.setGameMode(this.originalGameMode);
|
||||||
player.setInvulnerable(this.originalInvulnerable);
|
player.setInvulnerable(this.originalInvulnerable);
|
||||||
player.setSwimming(this.originalIsSwimming);
|
player.setSwimming(this.originalIsSwimming);
|
||||||
|
for (PotionEffect potionEffect : originalPotionEffects) {
|
||||||
|
player.addPotionEffect(potionEffect);
|
||||||
|
}
|
||||||
removeMenuItem(player);
|
removeMenuItem(player);
|
||||||
|
player.setHealth(originalHealth);
|
||||||
|
player.setSaturation(originalSaturation);
|
||||||
|
player.setFallDistance(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,6 +160,9 @@ public abstract class AbstractPlayerEntryState implements PlayerEntryState {
|
|||||||
data.put("originalInvulnerable", this.originalInvulnerable);
|
data.put("originalInvulnerable", this.originalInvulnerable);
|
||||||
data.put("originalIsSwimming", this.originalIsSwimming);
|
data.put("originalIsSwimming", this.originalIsSwimming);
|
||||||
data.put("originalCollideAble", this.originalCollideAble);
|
data.put("originalCollideAble", this.originalCollideAble);
|
||||||
|
data.put("originalPotionEffects", this.originalPotionEffects);
|
||||||
|
data.put("originalHealth", this.originalHealth);
|
||||||
|
data.put("originalSaturation", this.originalSaturation);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,9 @@ package net.knarcraft.minigames.arena;
|
|||||||
import net.knarcraft.minigames.arena.reward.Reward;
|
import net.knarcraft.minigames.arena.reward.Reward;
|
||||||
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -13,6 +15,7 @@ import java.util.UUID;
|
|||||||
/**
|
/**
|
||||||
* An interface describing an arena
|
* An interface describing an arena
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public interface Arena {
|
public interface Arena {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,28 +23,40 @@ public interface Arena {
|
|||||||
*
|
*
|
||||||
* @return <p>The name of this arena</p>
|
* @return <p>The name of this arena</p>
|
||||||
*/
|
*/
|
||||||
@NotNull String getArenaName();
|
@NotNull
|
||||||
|
String getArenaName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name of this arena
|
||||||
|
*
|
||||||
|
* @param arenaName <p>The new name</p>
|
||||||
|
* @return <p>True if successfully updated</p>
|
||||||
|
*/
|
||||||
|
boolean setName(@NotNull String arenaName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the data stored for this arena
|
* Gets the data stored for this arena
|
||||||
*
|
*
|
||||||
* @return <p>The stored data</p>
|
* @return <p>The stored data</p>
|
||||||
*/
|
*/
|
||||||
@NotNull ArenaData getData();
|
@NotNull
|
||||||
|
ArenaData getData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the id of this arena
|
* Gets the id of this arena
|
||||||
*
|
*
|
||||||
* @return <p>This arena's identifier</p>
|
* @return <p>This arena's identifier</p>
|
||||||
*/
|
*/
|
||||||
@NotNull UUID getArenaId();
|
@NotNull
|
||||||
|
UUID getArenaId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets this arena's sanitized name
|
* Gets this arena's sanitized name
|
||||||
*
|
*
|
||||||
* @return <p>This arena's sanitized name</p>
|
* @return <p>This arena's sanitized name</p>
|
||||||
*/
|
*/
|
||||||
@NotNull String getArenaNameSanitized();
|
@NotNull
|
||||||
|
String getArenaNameSanitized();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the data file belonging to this arena
|
* Removes the data file belonging to this arena
|
||||||
@ -57,13 +72,31 @@ public interface Arena {
|
|||||||
*/
|
*/
|
||||||
boolean saveData();
|
boolean saveData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type of block a player has to hit to win this arena
|
||||||
|
*
|
||||||
|
* @return <p>The kind of block players must hit</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
Material getWinBlockType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the material of the win block type
|
||||||
|
*
|
||||||
|
* <p>The win block type is the type of block a player must hit to win in this arena</p>
|
||||||
|
*
|
||||||
|
* @param material <p>The material to set for the win block type</p>
|
||||||
|
* @return <p>True if successfully updated</p>
|
||||||
|
*/
|
||||||
|
boolean setWinBlockType(@NotNull Material material);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether standing on the given block should cause a win
|
* Gets whether standing on the given block should cause a win
|
||||||
*
|
*
|
||||||
* @param block <p>The block to check</p>
|
* @param block <p>The block to check</p>
|
||||||
* @return <p>True if standing on the block will cause a win</p>
|
* @return <p>True if standing on the block will cause a win</p>
|
||||||
*/
|
*/
|
||||||
boolean willCauseWin(Block block);
|
boolean willCauseWin(@NotNull Block block);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether standing on the given block should cause a loss
|
* Gets whether standing on the given block should cause a loss
|
||||||
@ -71,7 +104,7 @@ public interface Arena {
|
|||||||
* @param block <p>The block to check</p>
|
* @param block <p>The block to check</p>
|
||||||
* @return <p>True if standing on the block will cause a loss</p>
|
* @return <p>True if standing on the block will cause a loss</p>
|
||||||
*/
|
*/
|
||||||
boolean willCauseLoss(Block block);
|
boolean willCauseLoss(@NotNull Block block);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets whether the win location is a solid block
|
* Gets whether the win location is a solid block
|
||||||
@ -85,14 +118,32 @@ public interface Arena {
|
|||||||
*
|
*
|
||||||
* @return <p>This arena's spawn location</p>
|
* @return <p>This arena's spawn location</p>
|
||||||
*/
|
*/
|
||||||
@NotNull Location getSpawnLocation();
|
@NotNull
|
||||||
|
Location getSpawnLocation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the spawn location for this arena
|
||||||
|
*
|
||||||
|
* @param newLocation <p>The new spawn location</p>
|
||||||
|
* @return <p>True if successfully updated</p>
|
||||||
|
*/
|
||||||
|
boolean setSpawnLocation(@Nullable Location newLocation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets this arena's exit location
|
* Gets this arena's exit location
|
||||||
*
|
*
|
||||||
* @return <p>This arena's exit location, or null if no such location is set.</p>
|
* @return <p>This arena's exit location, or null if no such location is set.</p>
|
||||||
*/
|
*/
|
||||||
@Nullable Location getExitLocation();
|
@Nullable
|
||||||
|
Location getExitLocation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the exit location for this arena
|
||||||
|
*
|
||||||
|
* @param newLocation <p>The new exit location</p>
|
||||||
|
* @return <p>True if successfully updated</p>
|
||||||
|
*/
|
||||||
|
boolean setExitLocation(@Nullable Location newLocation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a reward to this arena
|
* Adds a reward to this arena
|
||||||
@ -115,6 +166,57 @@ public interface Arena {
|
|||||||
* @param rewardCondition <p>The condition to get the rewards for</p>
|
* @param rewardCondition <p>The condition to get the rewards for</p>
|
||||||
* @return <p>All rewards</p>
|
* @return <p>All rewards</p>
|
||||||
*/
|
*/
|
||||||
@NotNull Set<Reward> getRewards(RewardCondition rewardCondition);
|
@NotNull
|
||||||
|
Set<Reward> getRewards(RewardCondition rewardCondition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the maximum amount of players that can join this arena at once
|
||||||
|
*
|
||||||
|
* @return <p>The maximum amount of players</p>
|
||||||
|
*/
|
||||||
|
int getMaxPlayers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum amount of players that can join this arena at once
|
||||||
|
*
|
||||||
|
* @param newValue <p>The new maximum amount of players</p>
|
||||||
|
*/
|
||||||
|
boolean setMaxPlayers(int newValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the damage causes that won't be blocked for this arena
|
||||||
|
*
|
||||||
|
* <p>Receiving any damage of this type will be allowed, but if the damage is fatal, a loss will be triggered.</p>
|
||||||
|
*
|
||||||
|
* @return <p>The damage causes that won't be blocked</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
Set<EntityDamageEvent.DamageCause> getAllowedDamageCauses();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the damage causes that will trigger a loss for this arena
|
||||||
|
*
|
||||||
|
* <p>Receiving any damage of this type will immediately cause a loss to the player.</p>
|
||||||
|
*
|
||||||
|
* @return <p>The damage causes that will trigger a loss</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
Set<EntityDamageEvent.DamageCause> getLossTriggerDamageCauses();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the damage causes that are allowed for this arena
|
||||||
|
*
|
||||||
|
* @param causes <p>The allowed damage causes</p>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("SameReturnValue")
|
||||||
|
boolean setAllowedDamageCauses(@NotNull Set<EntityDamageEvent.DamageCause> causes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the damage causes that will trigger a loss for this arena
|
||||||
|
*
|
||||||
|
* @param causes <p>The causes that cause a loss</p>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("SameReturnValue")
|
||||||
|
boolean setLossTriggerDamageCauses(@NotNull Set<EntityDamageEvent.DamageCause> causes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,15 @@ public interface ArenaGameMode {
|
|||||||
*
|
*
|
||||||
* @return <p>The name of this game-mode</p>
|
* @return <p>The name of this game-mode</p>
|
||||||
*/
|
*/
|
||||||
@NotNull String name();
|
@NotNull
|
||||||
|
String name();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a set of all available arena game-modes in the type definition of this game-mode
|
* Gets a set of all available arena game-modes in the type definition of this game-mode
|
||||||
*
|
*
|
||||||
* @return <p>All game-modes in this game-mode's class</p>
|
* @return <p>All game-modes in this game-mode's class</p>
|
||||||
*/
|
*/
|
||||||
@NotNull ArenaGameMode[] getValues();
|
@NotNull
|
||||||
|
ArenaGameMode[] getValues();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -151,8 +151,12 @@ public abstract class ArenaHandler<K extends Arena, S extends ArenaGroup<K, S>>
|
|||||||
* @return <p>The arena with the given name, or null if not found</p>
|
* @return <p>The arena with the given name, or null if not found</p>
|
||||||
*/
|
*/
|
||||||
public @Nullable K getArena(@NotNull String arenaName) {
|
public @Nullable K getArena(@NotNull String arenaName) {
|
||||||
|
try {
|
||||||
|
return this.arenas.get(UUID.fromString(arenaName));
|
||||||
|
} catch (IllegalArgumentException exception) {
|
||||||
return this.arenas.get(this.arenaNameLookup.get(StringSanitizer.sanitizeArenaName(arenaName)));
|
return this.arenas.get(this.arenaNameLookup.get(StringSanitizer.sanitizeArenaName(arenaName)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all known arenas
|
* Gets all known arenas
|
||||||
|
@ -18,7 +18,17 @@ public interface ArenaPlayerRegistry<K extends Arena> {
|
|||||||
*
|
*
|
||||||
* @return <p>The ids of the playing players</p>
|
* @return <p>The ids of the playing players</p>
|
||||||
*/
|
*/
|
||||||
@NotNull Set<UUID> getPlayingPlayers();
|
@NotNull
|
||||||
|
Set<UUID> getPlayingPlayers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all players currently playing in the given arena
|
||||||
|
*
|
||||||
|
* @param arena <p>The arena to check</p>
|
||||||
|
* @return <p>All players currently in the arena</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
Set<UUID> getPlayingPlayers(@NotNull K arena);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current entry state for the given player
|
* Gets the current entry state for the given player
|
||||||
@ -26,7 +36,8 @@ public interface ArenaPlayerRegistry<K extends Arena> {
|
|||||||
* @param playerId <p>The id of the player to get an entry state for</p>
|
* @param playerId <p>The id of the player to get an entry state for</p>
|
||||||
* @return <p>The entry state of the player, or null if not found</p>
|
* @return <p>The entry state of the player, or null if not found</p>
|
||||||
*/
|
*/
|
||||||
@Nullable PlayerEntryState getEntryState(@NotNull UUID playerId);
|
@Nullable
|
||||||
|
PlayerEntryState getEntryState(@NotNull UUID playerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers that the given player has started playing the given dropper arena session
|
* Registers that the given player has started playing the given dropper arena session
|
||||||
@ -50,7 +61,8 @@ public interface ArenaPlayerRegistry<K extends Arena> {
|
|||||||
* @param playerId <p>The id of the player to get arena for</p>
|
* @param playerId <p>The id of the player to get arena for</p>
|
||||||
* @return <p>The player's active arena session, or null if not currently playing</p>
|
* @return <p>The player's active arena session, or null if not currently playing</p>
|
||||||
*/
|
*/
|
||||||
@Nullable ArenaSession getArenaSession(@NotNull UUID playerId);
|
@Nullable
|
||||||
|
ArenaSession getArenaSession(@NotNull UUID playerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all active sessions for the given arena
|
* Removes all active sessions for the given arena
|
||||||
@ -58,6 +70,6 @@ public interface ArenaPlayerRegistry<K extends Arena> {
|
|||||||
* @param arena <p>The arena to remove sessions for</p>
|
* @param arena <p>The arena to remove sessions for</p>
|
||||||
* @param immediately <p>Whether to immediately teleport the player</p>
|
* @param immediately <p>Whether to immediately teleport the player</p>
|
||||||
*/
|
*/
|
||||||
void removeForArena(K arena, boolean immediately);
|
void removeForArena(@NotNull K arena, boolean immediately);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@ public interface ArenaSession {
|
|||||||
*
|
*
|
||||||
* @return <p>The player's entry state</p>
|
* @return <p>The player's entry state</p>
|
||||||
*/
|
*/
|
||||||
@NotNull PlayerEntryState getEntryState();
|
@NotNull
|
||||||
|
PlayerEntryState getEntryState();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers a win for the player playing in this session
|
* Triggers a win for the player playing in this session
|
||||||
@ -38,18 +39,28 @@ public interface ArenaSession {
|
|||||||
*
|
*
|
||||||
* @return <p>The session's arena</p>
|
* @return <p>The session's arena</p>
|
||||||
*/
|
*/
|
||||||
@NotNull Arena getArena();
|
@NotNull
|
||||||
|
Arena getArena();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the GUI with this arena's options
|
* Gets the GUI with this arena's options
|
||||||
*
|
*
|
||||||
* @return <p>This arena's GUI</p>
|
* @return <p>This arena's GUI</p>
|
||||||
*/
|
*/
|
||||||
@NotNull ArenaGUI getGUI();
|
@NotNull
|
||||||
|
ArenaGUI getGUI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the session to allow a player to try again
|
* Resets the session to allow a player to try again
|
||||||
*/
|
*/
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the game-mode the player is playing
|
||||||
|
*
|
||||||
|
* @return <p>The game-mode the player is playing</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
ArenaGameMode getGameMode();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,21 @@ public enum EditablePropertyType {
|
|||||||
/**
|
/**
|
||||||
* The property is a comma-separated list of materials
|
* The property is a comma-separated list of materials
|
||||||
*/
|
*/
|
||||||
MATERIAL_LIST
|
MATERIAL_LIST,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property is any double value
|
||||||
|
*/
|
||||||
|
DOUBLE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property is an integer with no particular restrictions
|
||||||
|
*/
|
||||||
|
INTEGER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The property is a comma-separated list of damage causes
|
||||||
|
*/
|
||||||
|
DAMAGE_CAUSE_LIST,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ public class PlayerVisibilityManager {
|
|||||||
*
|
*
|
||||||
* @param player <p>The the player to update</p>
|
* @param player <p>The the player to update</p>
|
||||||
*/
|
*/
|
||||||
public void toggleHidePlayers(@NotNull ArenaPlayerRegistry<?> playerRegistry, @NotNull Player player) {
|
public void toggleHidePlayers(@Nullable ArenaPlayerRegistry<?> playerRegistry, @NotNull Player player) {
|
||||||
if (displayingEnabledFor.contains(player.getUniqueId())) {
|
if (displayingEnabledFor.contains(player.getUniqueId())) {
|
||||||
displayingEnabledFor.remove(player.getUniqueId());
|
displayingEnabledFor.remove(player.getUniqueId());
|
||||||
// Make all other players hidden
|
// Make all other players hidden
|
||||||
|
18
src/main/java/net/knarcraft/minigames/arena/StorageKey.java
Normal file
18
src/main/java/net/knarcraft/minigames/arena/StorageKey.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package net.knarcraft.minigames.arena;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A representation of each key used for storing arena data
|
||||||
|
*/
|
||||||
|
public interface StorageKey {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the configuration key this enum represents
|
||||||
|
*
|
||||||
|
* @return <p>The string key representation.</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
String getKey();
|
||||||
|
|
||||||
|
}
|
@ -8,10 +8,12 @@ import net.knarcraft.minigames.arena.reward.Reward;
|
|||||||
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
||||||
import net.knarcraft.minigames.config.DropperConfiguration;
|
import net.knarcraft.minigames.config.DropperConfiguration;
|
||||||
import net.knarcraft.minigames.util.DropperArenaStorageHelper;
|
import net.knarcraft.minigames.util.DropperArenaStorageHelper;
|
||||||
|
import net.knarcraft.minigames.util.InputValidationHelper;
|
||||||
import net.knarcraft.minigames.util.StringSanitizer;
|
import net.knarcraft.minigames.util.StringSanitizer;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -21,6 +23,7 @@ import java.util.HashSet;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import static net.knarcraft.minigames.util.InputValidationHelper.isInvalid;
|
import static net.knarcraft.minigames.util.InputValidationHelper.isInvalid;
|
||||||
|
|
||||||
@ -62,6 +65,21 @@ public class DropperArena implements Arena {
|
|||||||
*/
|
*/
|
||||||
private float playerHorizontalVelocity;
|
private float playerHorizontalVelocity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of players able to join this arena at any time
|
||||||
|
*/
|
||||||
|
private int maxPlayers = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of damage that won't be blocked in this arena
|
||||||
|
*/
|
||||||
|
private Set<EntityDamageEvent.DamageCause> allowedDamageCauses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of damage that will trigger a loss in this arena
|
||||||
|
*/
|
||||||
|
private Set<EntityDamageEvent.DamageCause> lossTriggerDamageCauses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The material of the block players have to hit to win this dropper arena
|
* The material of the block players have to hit to win this dropper arena
|
||||||
*/
|
*/
|
||||||
@ -88,14 +106,20 @@ public class DropperArena implements Arena {
|
|||||||
* @param playerVerticalVelocity <p>The velocity to use for players' vertical velocity</p>
|
* @param playerVerticalVelocity <p>The velocity to use for players' vertical velocity</p>
|
||||||
* @param playerHorizontalVelocity <p>The velocity to use for players' horizontal velocity (-1 to 1)</p>
|
* @param playerHorizontalVelocity <p>The velocity to use for players' horizontal velocity (-1 to 1)</p>
|
||||||
* @param winBlockType <p>The material of the block players have to hit to win this dropper arena</p>
|
* @param winBlockType <p>The material of the block players have to hit to win this dropper arena</p>
|
||||||
|
* @param maxPlayers <p>The maximum amount of players able to join this arena at once</p>
|
||||||
* @param rewards <p>The rewards given by this arena</p>
|
* @param rewards <p>The rewards given by this arena</p>
|
||||||
* @param dropperArenaData <p>The arena data keeping track of which players have done what in this arena</p>
|
* @param dropperArenaData <p>The arena data keeping track of which players have done what in this arena</p>
|
||||||
* @param arenaHandler <p>The arena handler used for saving any changes</p>
|
* @param arenaHandler <p>The arena handler used for saving any changes</p>
|
||||||
|
* @param allowedDamageCauses <p>The damage causes to not cancel. If the player received fatal damage, a loss is triggered.</p>
|
||||||
|
* @param lossTriggerDamageCauses <p>The damage causes that will trigger a loss (for arrow traps and similar)</p>
|
||||||
*/
|
*/
|
||||||
public DropperArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
|
public DropperArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
|
||||||
@Nullable Location exitLocation, double playerVerticalVelocity, float playerHorizontalVelocity,
|
@Nullable Location exitLocation, double playerVerticalVelocity, float playerHorizontalVelocity,
|
||||||
@NotNull Material winBlockType, @NotNull Map<RewardCondition, Set<Reward>> rewards,
|
@NotNull Material winBlockType, int maxPlayers,
|
||||||
@NotNull DropperArenaData dropperArenaData, @NotNull DropperArenaHandler arenaHandler) {
|
@NotNull Map<RewardCondition, Set<Reward>> rewards, @NotNull DropperArenaData dropperArenaData,
|
||||||
|
@NotNull DropperArenaHandler arenaHandler,
|
||||||
|
@Nullable Set<String> allowedDamageCauses,
|
||||||
|
@Nullable Set<String> lossTriggerDamageCauses) {
|
||||||
this.arenaId = arenaId;
|
this.arenaId = arenaId;
|
||||||
this.arenaName = arenaName;
|
this.arenaName = arenaName;
|
||||||
this.spawnLocation = spawnLocation;
|
this.spawnLocation = spawnLocation;
|
||||||
@ -106,6 +130,9 @@ public class DropperArena implements Arena {
|
|||||||
this.dropperArenaData = dropperArenaData;
|
this.dropperArenaData = dropperArenaData;
|
||||||
this.dropperArenaHandler = arenaHandler;
|
this.dropperArenaHandler = arenaHandler;
|
||||||
this.rewards = rewards;
|
this.rewards = rewards;
|
||||||
|
this.maxPlayers = maxPlayers;
|
||||||
|
this.allowedDamageCauses = InputValidationHelper.parseDamageCauses(allowedDamageCauses);
|
||||||
|
this.lossTriggerDamageCauses = InputValidationHelper.parseDamageCauses(lossTriggerDamageCauses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,6 +163,8 @@ public class DropperArena implements Arena {
|
|||||||
this.dropperArenaData = new DropperArenaData(this.arenaId, recordRegistries, new HashMap<>());
|
this.dropperArenaData = new DropperArenaData(this.arenaId, recordRegistries, new HashMap<>());
|
||||||
this.winBlockType = Material.WATER;
|
this.winBlockType = Material.WATER;
|
||||||
this.dropperArenaHandler = arenaHandler;
|
this.dropperArenaHandler = arenaHandler;
|
||||||
|
this.allowedDamageCauses = new HashSet<>();
|
||||||
|
this.lossTriggerDamageCauses = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -167,13 +196,13 @@ public class DropperArena implements Arena {
|
|||||||
public void addReward(@NotNull RewardCondition rewardCondition, @NotNull Reward reward) {
|
public void addReward(@NotNull RewardCondition rewardCondition, @NotNull Reward reward) {
|
||||||
this.rewards.computeIfAbsent(rewardCondition, k -> new HashSet<>());
|
this.rewards.computeIfAbsent(rewardCondition, k -> new HashSet<>());
|
||||||
this.rewards.get(rewardCondition).add(reward);
|
this.rewards.get(rewardCondition).add(reward);
|
||||||
this.dropperArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearRewards(@NotNull RewardCondition rewardCondition) {
|
public void clearRewards(@NotNull RewardCondition rewardCondition) {
|
||||||
this.rewards.remove(rewardCondition);
|
this.rewards.remove(rewardCondition);
|
||||||
this.dropperArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -185,6 +214,124 @@ public class DropperArena implements Arena {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
public @NotNull Set<EntityDamageEvent.DamageCause> getAllowedDamageCauses() {
|
||||||
|
return this.allowedDamageCauses;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Set<EntityDamageEvent.DamageCause> getLossTriggerDamageCauses() {
|
||||||
|
return this.lossTriggerDamageCauses;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setAllowedDamageCauses(@NotNull Set<EntityDamageEvent.DamageCause> causes) {
|
||||||
|
this.allowedDamageCauses = causes;
|
||||||
|
this.saveArena();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setLossTriggerDamageCauses(@NotNull Set<EntityDamageEvent.DamageCause> causes) {
|
||||||
|
this.lossTriggerDamageCauses = causes;
|
||||||
|
this.saveArena();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Material getWinBlockType() {
|
||||||
|
return this.winBlockType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public String getArenaNameSanitized() {
|
||||||
|
return StringSanitizer.sanitizeArenaName(this.getArenaName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeData() {
|
||||||
|
return DropperArenaStorageHelper.removeDropperArenaData(getArenaId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveData() {
|
||||||
|
try {
|
||||||
|
DropperArenaStorageHelper.saveDropperArenaData(getData());
|
||||||
|
return true;
|
||||||
|
} catch (IOException exception) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean willCauseWin(@NotNull Block block) {
|
||||||
|
return block.getType() == winBlockType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean willCauseLoss(@NotNull Block block) {
|
||||||
|
return !dropperConfiguration.getBlockWhitelist().contains(block.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean winLocationIsSolid() {
|
||||||
|
return winBlockType.isSolid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setSpawnLocation(@Nullable Location newLocation) {
|
||||||
|
if (isInvalid(newLocation)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
this.spawnLocation = newLocation;
|
||||||
|
this.saveArena();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setExitLocation(@Nullable Location newLocation) {
|
||||||
|
if (isInvalid(newLocation)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
this.exitLocation = newLocation;
|
||||||
|
this.saveArena();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setName(@NotNull String arenaName) {
|
||||||
|
if (!arenaName.isBlank()) {
|
||||||
|
String oldName = this.getArenaNameSanitized();
|
||||||
|
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.saveArena();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the vertical velocity for players in this arena
|
* Gets the vertical velocity for players in this arena
|
||||||
*
|
*
|
||||||
@ -208,119 +355,13 @@ public class DropperArena implements Arena {
|
|||||||
return this.playerHorizontalVelocity;
|
return this.playerHorizontalVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the type of block a player has to hit to win this arena
|
|
||||||
*
|
|
||||||
* @return <p>The kind of block players must hit</p>
|
|
||||||
*/
|
|
||||||
public @NotNull Material getWinBlockType() {
|
|
||||||
return this.winBlockType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets this arena's sanitized name
|
|
||||||
*
|
|
||||||
* @return <p>This arena's sanitized name</p>
|
|
||||||
*/
|
|
||||||
public @NotNull String getArenaNameSanitized() {
|
|
||||||
return StringSanitizer.sanitizeArenaName(this.getArenaName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeData() {
|
|
||||||
return DropperArenaStorageHelper.removeDropperArenaData(getArenaId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean saveData() {
|
|
||||||
try {
|
|
||||||
DropperArenaStorageHelper.saveDropperArenaData(getData());
|
|
||||||
return true;
|
|
||||||
} catch (IOException exception) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean willCauseWin(Block block) {
|
|
||||||
return block.getType() == winBlockType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean willCauseLoss(Block block) {
|
|
||||||
return !dropperConfiguration.getBlockWhitelist().contains(block.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean winLocationIsSolid() {
|
|
||||||
return winBlockType.isSolid();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the spawn location for this arena
|
|
||||||
*
|
|
||||||
* @param newLocation <p>The new spawn location</p>
|
|
||||||
* @return <p>True if successfully updated</p>
|
|
||||||
*/
|
|
||||||
public boolean setSpawnLocation(@NotNull Location newLocation) {
|
|
||||||
if (isInvalid(newLocation)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
this.spawnLocation = newLocation;
|
|
||||||
this.dropperArenaHandler.saveArenas();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the exit location for this arena
|
|
||||||
*
|
|
||||||
* @param newLocation <p>The new exit location</p>
|
|
||||||
* @return <p>True if successfully updated</p>
|
|
||||||
*/
|
|
||||||
public boolean setExitLocation(@NotNull Location newLocation) {
|
|
||||||
if (isInvalid(newLocation)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
this.exitLocation = newLocation;
|
|
||||||
this.dropperArenaHandler.saveArenas();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the name of this arena
|
|
||||||
*
|
|
||||||
* @param arenaName <p>The new name</p>
|
|
||||||
* @return <p>True if successfully updated</p>
|
|
||||||
*/
|
|
||||||
public boolean setName(@NotNull String arenaName) {
|
|
||||||
if (!arenaName.isBlank()) {
|
|
||||||
String oldName = this.getArenaNameSanitized();
|
|
||||||
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();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the material of the win block type
|
|
||||||
*
|
|
||||||
* <p>The win block type is the type of block a player must hit to win in this arena</p>
|
|
||||||
*
|
|
||||||
* @param material <p>The material to set for the win block type</p>
|
|
||||||
* @return <p>True if successfully updated</p>
|
|
||||||
*/
|
|
||||||
public boolean setWinBlockType(@NotNull Material material) {
|
public boolean setWinBlockType(@NotNull Material material) {
|
||||||
if (material.isAir() || !material.isBlock()) {
|
if (material.isAir() || !material.isBlock()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
this.winBlockType = material;
|
this.winBlockType = material;
|
||||||
this.dropperArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,7 +379,7 @@ public class DropperArena implements Arena {
|
|||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
this.playerHorizontalVelocity = horizontalVelocity;
|
this.playerHorizontalVelocity = horizontalVelocity;
|
||||||
this.dropperArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -354,11 +395,24 @@ public class DropperArena implements Arena {
|
|||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
this.playerVerticalVelocity = verticalVelocity;
|
this.playerVerticalVelocity = verticalVelocity;
|
||||||
this.dropperArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
return true;
|
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
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (!(other instanceof DropperArena otherArena)) {
|
if (!(other instanceof DropperArena otherArena)) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.knarcraft.minigames.arena.dropper;
|
package net.knarcraft.minigames.arena.dropper;
|
||||||
|
|
||||||
import net.knarcraft.minigames.arena.EditablePropertyType;
|
import net.knarcraft.minigames.arena.EditablePropertyType;
|
||||||
|
import net.knarcraft.minigames.util.ArenaStorageHelper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -45,6 +46,26 @@ public enum DropperArenaEditableProperty {
|
|||||||
*/
|
*/
|
||||||
WIN_BLOCK_TYPE("winBlockType", (arena) -> arena.getWinBlockType().toString(),
|
WIN_BLOCK_TYPE("winBlockType", (arena) -> arena.getWinBlockType().toString(),
|
||||||
EditablePropertyType.BLOCK_TYPE),
|
EditablePropertyType.BLOCK_TYPE),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arena's max players
|
||||||
|
*/
|
||||||
|
MAX_PLAYERS("maxPlayers", (arena) -> String.valueOf(arena.getMaxPlayers()),
|
||||||
|
EditablePropertyType.INTEGER),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arena's allowed damage causes
|
||||||
|
*/
|
||||||
|
ALLOWED_DAMAGE_CAUSES("allowedDamageCauses", (arena) -> String.valueOf(
|
||||||
|
ArenaStorageHelper.getDamageCauseNames(arena.getAllowedDamageCauses())),
|
||||||
|
EditablePropertyType.DAMAGE_CAUSE_LIST),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arena's loss trigger damage causes
|
||||||
|
*/
|
||||||
|
LOSS_TRIGGER_DAMAGE_CAUSES("lossTriggerDamageCauses", (arena) -> String.valueOf(
|
||||||
|
ArenaStorageHelper.getDamageCauseNames(arena.getLossTriggerDamageCauses())),
|
||||||
|
EditablePropertyType.DAMAGE_CAUSE_LIST),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final @NotNull String argumentString;
|
private final @NotNull String argumentString;
|
||||||
|
@ -34,11 +34,11 @@ public enum DropperArenaGameMode implements ConfigurationSerializable, ArenaGame
|
|||||||
* @param gameMode <p>The game-mode string to match</p>
|
* @param gameMode <p>The game-mode string to match</p>
|
||||||
* @return <p>The specified arena game-mode</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();
|
String sanitized = gameMode.trim().toLowerCase();
|
||||||
if (sanitized.matches("(invert(ed)?|inverse)")) {
|
if (sanitized.matches("(invert(ed)?|inverse)")) {
|
||||||
return DropperArenaGameMode.INVERTED;
|
return DropperArenaGameMode.INVERTED;
|
||||||
} else if (sanitized.matches("rand(om)?")) {
|
} else if (sanitized.matches("rand(om)?_?(inverted)?")) {
|
||||||
return DropperArenaGameMode.RANDOM_INVERTED;
|
return DropperArenaGameMode.RANDOM_INVERTED;
|
||||||
} else {
|
} else {
|
||||||
return DropperArenaGameMode.DEFAULT;
|
return DropperArenaGameMode.DEFAULT;
|
||||||
|
@ -8,8 +8,11 @@ import net.knarcraft.minigames.arena.reward.RewardCondition;
|
|||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
import net.knarcraft.minigames.gui.ArenaGUI;
|
import net.knarcraft.minigames.gui.ArenaGUI;
|
||||||
import net.knarcraft.minigames.gui.DropperGUI;
|
import net.knarcraft.minigames.gui.DropperGUI;
|
||||||
|
import net.knarcraft.minigames.gui.DropperGUIBedrock;
|
||||||
|
import net.knarcraft.minigames.util.GeyserHelper;
|
||||||
import net.knarcraft.minigames.util.PlayerTeleporter;
|
import net.knarcraft.minigames.util.PlayerTeleporter;
|
||||||
import net.knarcraft.minigames.util.RewardHelper;
|
import net.knarcraft.minigames.util.RewardHelper;
|
||||||
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -114,6 +117,7 @@ public class DropperArenaSession extends AbstractArenaSession {
|
|||||||
this.deaths++;
|
this.deaths++;
|
||||||
//Teleport the player back to the top
|
//Teleport the player back to the top
|
||||||
PlayerTeleporter.teleportPlayer(this.player, this.arena.getSpawnLocation(), true, false);
|
PlayerTeleporter.teleportPlayer(this.player, this.arena.getSpawnLocation(), true, false);
|
||||||
|
this.player.playSound(this.player, Sound.ENTITY_CHICKEN_EGG, 5f, 0.5f);
|
||||||
this.entryState.setArenaState();
|
this.entryState.setArenaState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +128,11 @@ public class DropperArenaSession extends AbstractArenaSession {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ArenaGUI getGUI() {
|
public @NotNull ArenaGUI getGUI() {
|
||||||
return new DropperGUI(player);
|
if (GeyserHelper.isGeyserPlayer(this.player)) {
|
||||||
|
return new DropperGUIBedrock(this.player);
|
||||||
|
} else {
|
||||||
|
return new DropperGUI(this.player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -137,7 +145,7 @@ public class DropperArenaSession extends AbstractArenaSession {
|
|||||||
protected void removeSession() {
|
protected void removeSession() {
|
||||||
// Remove this session for game sessions to stop listeners from fiddling more with the player
|
// Remove this session for game sessions to stop listeners from fiddling more with the player
|
||||||
boolean removedSession = MiniGames.getInstance().getDropperArenaPlayerRegistry().removePlayer(
|
boolean removedSession = MiniGames.getInstance().getDropperArenaPlayerRegistry().removePlayer(
|
||||||
player.getUniqueId(), true);
|
this.player.getUniqueId(), true);
|
||||||
if (!removedSession) {
|
if (!removedSession) {
|
||||||
MiniGames.log(Level.SEVERE, "Unable to remove dropper arena session for " + player.getName() + ". " +
|
MiniGames.log(Level.SEVERE, "Unable to remove dropper arena session for " + player.getName() + ". " +
|
||||||
"This will have unintended consequences.");
|
"This will have unintended consequences.");
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package net.knarcraft.minigames.arena.dropper;
|
package net.knarcraft.minigames.arena.dropper;
|
||||||
|
|
||||||
|
import net.knarcraft.minigames.arena.StorageKey;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of each key used for storing arena data
|
* A representation of each key used for storing arena data
|
||||||
*/
|
*/
|
||||||
public enum DropperArenaStorageKey {
|
public enum DropperArenaStorageKey implements StorageKey {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key for an arena's id
|
* The key for an arena's id
|
||||||
@ -51,6 +52,21 @@ public enum DropperArenaStorageKey {
|
|||||||
* The key for this arena's rewards
|
* The key for this arena's rewards
|
||||||
*/
|
*/
|
||||||
REWARDS("rewards"),
|
REWARDS("rewards"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key for this arena's maximum players
|
||||||
|
*/
|
||||||
|
MAX_PLAYERS("maxPlayers"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key for this arena's allowed damage causes
|
||||||
|
*/
|
||||||
|
ALLOWED_DAMAGE_CAUSES("allowedDamageCauses"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key for this arena's loss trigger damage causes
|
||||||
|
*/
|
||||||
|
LOSS_TRIGGER_DAMAGE_CAUSES("lossTriggerDamageCauses"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final @NotNull String key;
|
private final @NotNull String key;
|
||||||
@ -64,11 +80,7 @@ public enum DropperArenaStorageKey {
|
|||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Gets the configuration key this enum represents
|
|
||||||
*
|
|
||||||
* @return <p>The string key representation.</p>
|
|
||||||
*/
|
|
||||||
public @NotNull String getKey() {
|
public @NotNull String getKey() {
|
||||||
return this.key;
|
return this.key;
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,11 @@ import net.knarcraft.minigames.container.SerializableUUID;
|
|||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -45,14 +48,20 @@ public class DropperPlayerEntryState extends AbstractPlayerEntryState {
|
|||||||
* @param originalFlySpeed <p>The fly-speed of the player before entering the arena</p>
|
* @param originalFlySpeed <p>The fly-speed of the player before entering the arena</p>
|
||||||
* @param horizontalVelocity <p>The horizontal velocity of the player before entering the arena</p>
|
* @param horizontalVelocity <p>The horizontal velocity of the player before entering the arena</p>
|
||||||
* @param originalCollideAble <p>Whether the player was collide-able before entering the arena</p>
|
* @param originalCollideAble <p>Whether the player was collide-able before entering the arena</p>
|
||||||
|
* @param originalPotionEffects <p>The potion effects applied to the player when joining</p>
|
||||||
|
* @param originalHealth <p>The health of the player when joining the arena</p>
|
||||||
|
* @param originalSaturation <p>The saturation of the player when joining the arena</p>
|
||||||
*/
|
*/
|
||||||
public DropperPlayerEntryState(@NotNull UUID playerId, Location entryLocation,
|
public DropperPlayerEntryState(@NotNull UUID playerId, @NotNull Location entryLocation,
|
||||||
boolean originalIsFlying, GameMode originalGameMode, boolean originalAllowFlight,
|
boolean originalIsFlying, GameMode originalGameMode, boolean originalAllowFlight,
|
||||||
boolean originalInvulnerable, boolean originalIsSwimming,
|
boolean originalInvulnerable, boolean originalIsSwimming,
|
||||||
float originalFlySpeed, float horizontalVelocity,
|
float originalFlySpeed, float horizontalVelocity,
|
||||||
DropperArenaGameMode arenaGameMode, boolean originalCollideAble) {
|
@NotNull DropperArenaGameMode arenaGameMode, boolean originalCollideAble,
|
||||||
|
@NotNull Collection<PotionEffect> originalPotionEffects, double originalHealth,
|
||||||
|
float originalSaturation) {
|
||||||
super(playerId, entryLocation, originalIsFlying, originalGameMode, originalAllowFlight,
|
super(playerId, entryLocation, originalIsFlying, originalGameMode, originalAllowFlight,
|
||||||
originalInvulnerable, originalIsSwimming, originalCollideAble);
|
originalInvulnerable, originalIsSwimming, originalCollideAble, originalPotionEffects, originalHealth,
|
||||||
|
originalSaturation);
|
||||||
this.originalFlySpeed = originalFlySpeed;
|
this.originalFlySpeed = originalFlySpeed;
|
||||||
this.horizontalVelocity = horizontalVelocity;
|
this.horizontalVelocity = horizontalVelocity;
|
||||||
this.arenaGameMode = arenaGameMode;
|
this.arenaGameMode = arenaGameMode;
|
||||||
@ -108,7 +117,7 @@ public class DropperPlayerEntryState extends AbstractPlayerEntryState {
|
|||||||
*
|
*
|
||||||
* @return <p>The data to deserialize</p>
|
* @return <p>The data to deserialize</p>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings({"unused", "unchecked"})
|
||||||
public static DropperPlayerEntryState deserialize(Map<String, Object> data) {
|
public static DropperPlayerEntryState deserialize(Map<String, Object> data) {
|
||||||
UUID playerId = ((SerializableUUID) data.get("playerId")).getRawValue();
|
UUID playerId = ((SerializableUUID) data.get("playerId")).getRawValue();
|
||||||
Location entryLocation = (Location) data.get("entryLocation");
|
Location entryLocation = (Location) data.get("entryLocation");
|
||||||
@ -121,10 +130,15 @@ public class DropperPlayerEntryState extends AbstractPlayerEntryState {
|
|||||||
float horizontalVelocity = ((Number) data.get("horizontalVelocity")).floatValue();
|
float horizontalVelocity = ((Number) data.get("horizontalVelocity")).floatValue();
|
||||||
DropperArenaGameMode arenaGameMode = (DropperArenaGameMode) data.get("arenaGameMode");
|
DropperArenaGameMode arenaGameMode = (DropperArenaGameMode) data.get("arenaGameMode");
|
||||||
boolean originalCollideAble = getBoolean(data, "originalCollideAble");
|
boolean originalCollideAble = getBoolean(data, "originalCollideAble");
|
||||||
|
Collection<PotionEffect> originalPotionEffect =
|
||||||
|
(Collection<PotionEffect>) data.getOrDefault("originalPotionEffects", new ArrayList<>());
|
||||||
|
double originalHealth = ((Number) data.get("originalHealth")).doubleValue();
|
||||||
|
float originalSaturation = ((Number) data.get("originalSaturation")).floatValue();
|
||||||
|
|
||||||
return new DropperPlayerEntryState(playerId, entryLocation, originalIsFlying,
|
return new DropperPlayerEntryState(playerId, entryLocation, originalIsFlying,
|
||||||
originalGameMode, originalAllowFlight, originalInvulnerable, originalIsSwimming,
|
originalGameMode, originalAllowFlight, originalInvulnerable, originalIsSwimming,
|
||||||
originalFlySpeed, horizontalVelocity, arenaGameMode, originalCollideAble);
|
originalFlySpeed, horizontalVelocity, arenaGameMode, originalCollideAble, originalPotionEffect,
|
||||||
|
originalHealth, originalSaturation);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,14 @@ import net.knarcraft.minigames.arena.ArenaGameMode;
|
|||||||
import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
|
import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
|
||||||
import net.knarcraft.minigames.arena.reward.Reward;
|
import net.knarcraft.minigames.arena.reward.Reward;
|
||||||
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
||||||
|
import net.knarcraft.minigames.util.InputValidationHelper;
|
||||||
import net.knarcraft.minigames.util.ParkourArenaStorageHelper;
|
import net.knarcraft.minigames.util.ParkourArenaStorageHelper;
|
||||||
import net.knarcraft.minigames.util.StringSanitizer;
|
import net.knarcraft.minigames.util.StringSanitizer;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -23,6 +26,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import static net.knarcraft.minigames.util.InputValidationHelper.isInvalid;
|
import static net.knarcraft.minigames.util.InputValidationHelper.isInvalid;
|
||||||
|
|
||||||
@ -72,6 +76,31 @@ public class ParkourArena implements Arena {
|
|||||||
*/
|
*/
|
||||||
private @Nullable Set<Material> killPlaneBlocks;
|
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 maximum amount of players able to join this arena at any time
|
||||||
|
*/
|
||||||
|
private int maxPlayers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of damage that won't be blocked in this arena
|
||||||
|
*/
|
||||||
|
private Set<EntityDamageEvent.DamageCause> allowedDamageCauses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of damage that will trigger a loss in this arena
|
||||||
|
*/
|
||||||
|
private Set<EntityDamageEvent.DamageCause> lossTriggerDamageCauses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The checkpoints for this arena. Entering a checkpoint overrides the player's spawn location.
|
* The checkpoints for this arena. Entering a checkpoint overrides the player's spawn location.
|
||||||
*/
|
*/
|
||||||
@ -95,17 +124,24 @@ public class ParkourArena implements Arena {
|
|||||||
* @param exitLocation <p>The location the players are teleported to when exiting the arena, or null</p>
|
* @param exitLocation <p>The location the players are teleported to when exiting the arena, or null</p>
|
||||||
* @param winBlockType <p>The material of the block players have to hit to win this parkour arena</p>
|
* @param 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 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 checkpoints <p>The checkpoints set for this arena</p>
|
||||||
|
* @param maxPlayers <p>The maximum amount of players able to join this arena at once</p>
|
||||||
* @param rewards <p>The rewards given by this arena</p>
|
* @param rewards <p>The rewards given by this arena</p>
|
||||||
* @param parkourArenaData <p>The arena data keeping track of which players have done what in this arena</p>
|
* @param parkourArenaData <p>The arena data keeping track of which players have done what in this arena</p>
|
||||||
* @param arenaHandler <p>The arena handler used for saving any changes</p>
|
* @param arenaHandler <p>The arena handler used for saving any changes</p>
|
||||||
|
* @param allowedDamageCauses <p>The damage causes to not cancel. If the player received fatal damage, a loss is triggered.</p>
|
||||||
|
* @param lossTriggerDamageCauses <p>The damage causes that will trigger a loss (for arrow traps and similar)</p>
|
||||||
*/
|
*/
|
||||||
public ParkourArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
|
public ParkourArena(@NotNull UUID arenaId, @NotNull String arenaName, @NotNull Location spawnLocation,
|
||||||
@Nullable Location exitLocation, @NotNull Material winBlockType, @Nullable Location winLocation,
|
@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, int maxPlayers,
|
||||||
@NotNull Map<RewardCondition, Set<Reward>> rewards,
|
@NotNull Map<RewardCondition, Set<Reward>> rewards,
|
||||||
@NotNull ParkourArenaData parkourArenaData, @NotNull ParkourArenaHandler arenaHandler) {
|
@NotNull ParkourArenaData parkourArenaData, @NotNull ParkourArenaHandler arenaHandler,
|
||||||
|
@Nullable Set<String> allowedDamageCauses,
|
||||||
|
@Nullable Set<String> lossTriggerDamageCauses) {
|
||||||
this.arenaId = arenaId;
|
this.arenaId = arenaId;
|
||||||
this.arenaName = arenaName;
|
this.arenaName = arenaName;
|
||||||
this.spawnLocation = spawnLocation;
|
this.spawnLocation = spawnLocation;
|
||||||
@ -115,10 +151,16 @@ public class ParkourArena implements Arena {
|
|||||||
this.killPlaneBlockNames = killPlaneBlockNames;
|
this.killPlaneBlockNames = killPlaneBlockNames;
|
||||||
this.killPlaneBlocks = this.killPlaneBlockNames == null ? null : MaterialHelper.loadMaterialList(
|
this.killPlaneBlocks = this.killPlaneBlockNames == null ? null : MaterialHelper.loadMaterialList(
|
||||||
new ArrayList<>(killPlaneBlockNames), "+", MiniGames.getInstance().getLogger());
|
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.checkpoints = checkpoints;
|
||||||
this.parkourArenaData = parkourArenaData;
|
this.parkourArenaData = parkourArenaData;
|
||||||
this.parkourArenaHandler = arenaHandler;
|
this.parkourArenaHandler = arenaHandler;
|
||||||
this.rewards = rewards;
|
this.rewards = rewards;
|
||||||
|
this.maxPlayers = maxPlayers;
|
||||||
|
this.allowedDamageCauses = InputValidationHelper.parseDamageCauses(allowedDamageCauses);
|
||||||
|
this.lossTriggerDamageCauses = InputValidationHelper.parseDamageCauses(lossTriggerDamageCauses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,8 +189,12 @@ public class ParkourArena implements Arena {
|
|||||||
this.parkourArenaData = new ParkourArenaData(this.arenaId, recordRegistries, new HashMap<>());
|
this.parkourArenaData = new ParkourArenaData(this.arenaId, recordRegistries, new HashMap<>());
|
||||||
this.winBlockType = Material.EMERALD_BLOCK;
|
this.winBlockType = Material.EMERALD_BLOCK;
|
||||||
this.killPlaneBlocks = null;
|
this.killPlaneBlocks = null;
|
||||||
|
this.obstacleBlocks = null;
|
||||||
this.checkpoints = new ArrayList<>();
|
this.checkpoints = new ArrayList<>();
|
||||||
this.parkourArenaHandler = arenaHandler;
|
this.parkourArenaHandler = arenaHandler;
|
||||||
|
this.maxPlayers = -1;
|
||||||
|
this.allowedDamageCauses = new HashSet<>();
|
||||||
|
this.lossTriggerDamageCauses = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -180,13 +226,13 @@ public class ParkourArena implements Arena {
|
|||||||
public void addReward(@NotNull RewardCondition rewardCondition, @NotNull Reward reward) {
|
public void addReward(@NotNull RewardCondition rewardCondition, @NotNull Reward reward) {
|
||||||
this.rewards.computeIfAbsent(rewardCondition, k -> new HashSet<>());
|
this.rewards.computeIfAbsent(rewardCondition, k -> new HashSet<>());
|
||||||
this.rewards.get(rewardCondition).add(reward);
|
this.rewards.get(rewardCondition).add(reward);
|
||||||
this.parkourArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearRewards(@NotNull RewardCondition rewardCondition) {
|
public void clearRewards(@NotNull RewardCondition rewardCondition) {
|
||||||
this.rewards.remove(rewardCondition);
|
this.rewards.remove(rewardCondition);
|
||||||
this.parkourArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -198,12 +244,49 @@ public class ParkourArena implements Arena {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Gets the type of block a player has to hit to win this arena
|
public int getMaxPlayers() {
|
||||||
*
|
return this.maxPlayers;
|
||||||
* @return <p>The kind of block players must hit</p>
|
}
|
||||||
*/
|
|
||||||
public @NotNull Material getWinBlockType() {
|
@Override
|
||||||
|
public boolean setMaxPlayers(int newValue) {
|
||||||
|
if (newValue < -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maxPlayers = newValue;
|
||||||
|
this.saveArena();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Set<EntityDamageEvent.DamageCause> getAllowedDamageCauses() {
|
||||||
|
return this.allowedDamageCauses;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Set<EntityDamageEvent.DamageCause> getLossTriggerDamageCauses() {
|
||||||
|
return this.lossTriggerDamageCauses;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setAllowedDamageCauses(@NotNull Set<EntityDamageEvent.DamageCause> causes) {
|
||||||
|
this.allowedDamageCauses = causes;
|
||||||
|
this.saveArena();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setLossTriggerDamageCauses(@NotNull Set<EntityDamageEvent.DamageCause> causes) {
|
||||||
|
this.lossTriggerDamageCauses = causes;
|
||||||
|
this.saveArena();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public Material getWinBlockType() {
|
||||||
return this.winBlockType;
|
return this.winBlockType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,6 +323,28 @@ public class ParkourArena implements Arena {
|
|||||||
return this.killPlaneBlockNames;
|
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
|
* Gets all checkpoint locations for this arena
|
||||||
*
|
*
|
||||||
@ -262,12 +367,9 @@ public class ParkourArena implements Arena {
|
|||||||
return this.checkpoints.isEmpty();
|
return this.checkpoints.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Gets this arena's sanitized name
|
@NotNull
|
||||||
*
|
public String getArenaNameSanitized() {
|
||||||
* @return <p>This arena's sanitized name</p>
|
|
||||||
*/
|
|
||||||
public @NotNull String getArenaNameSanitized() {
|
|
||||||
return StringSanitizer.sanitizeArenaName(this.getArenaName());
|
return StringSanitizer.sanitizeArenaName(this.getArenaName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,14 +389,21 @@ public class ParkourArena implements Arena {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean willCauseWin(Block block) {
|
public boolean willCauseWin(@NotNull Block block) {
|
||||||
return (this.winLocation != null && this.winLocation.getBlock().equals(block)) ||
|
if (this.winLocation != null) {
|
||||||
(this.winLocation == null && this.winBlockType == block.getType());
|
return this.winLocation.getBlock().equals(block);
|
||||||
|
} else {
|
||||||
|
if (this.winBlockType.isSolid()) {
|
||||||
|
return this.winBlockType == block.getRelative(BlockFace.DOWN).getType();
|
||||||
|
} else {
|
||||||
|
return this.winBlockType == block.getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean willCauseLoss(Block block) {
|
public boolean willCauseLoss(@NotNull Block block) {
|
||||||
return this.getKillPlaneBlocks().contains(block.getType());
|
return this.getKillPlaneBlocks().contains(block.getType()) || this.getObstacleBlocks().contains(block.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -303,71 +412,49 @@ public class ParkourArena implements Arena {
|
|||||||
this.winBlockType.isSolid();
|
this.winBlockType.isSolid();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the spawn location for this arena
|
public boolean setSpawnLocation(@Nullable Location newLocation) {
|
||||||
*
|
|
||||||
* @param newLocation <p>The new spawn location</p>
|
|
||||||
* @return <p>True if successfully updated</p>
|
|
||||||
*/
|
|
||||||
public boolean setSpawnLocation(@NotNull Location newLocation) {
|
|
||||||
if (isInvalid(newLocation)) {
|
if (isInvalid(newLocation)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
this.spawnLocation = newLocation;
|
this.spawnLocation = newLocation;
|
||||||
this.parkourArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the exit location for this arena
|
public boolean setExitLocation(@Nullable Location newLocation) {
|
||||||
*
|
|
||||||
* @param newLocation <p>The new exit location</p>
|
|
||||||
* @return <p>True if successfully updated</p>
|
|
||||||
*/
|
|
||||||
public boolean setExitLocation(@NotNull Location newLocation) {
|
|
||||||
if (isInvalid(newLocation)) {
|
if (isInvalid(newLocation)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
this.exitLocation = newLocation;
|
this.exitLocation = newLocation;
|
||||||
this.parkourArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the name of this arena
|
|
||||||
*
|
|
||||||
* @param arenaName <p>The new name</p>
|
|
||||||
* @return <p>True if successfully updated</p>
|
|
||||||
*/
|
|
||||||
public boolean setName(@NotNull String arenaName) {
|
public boolean setName(@NotNull String arenaName) {
|
||||||
if (!arenaName.isBlank()) {
|
if (!arenaName.isBlank()) {
|
||||||
String oldName = this.getArenaNameSanitized();
|
String oldName = this.getArenaNameSanitized();
|
||||||
this.arenaName = arenaName;
|
this.arenaName = arenaName;
|
||||||
// Update the arena lookup map to make sure the new name can be used immediately
|
// Update the arena lookup map to make sure the new name can be used immediately
|
||||||
this.parkourArenaHandler.updateLookupName(oldName, this.getArenaNameSanitized());
|
this.parkourArenaHandler.updateLookupName(oldName, this.getArenaNameSanitized());
|
||||||
this.parkourArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the material of the win block type
|
|
||||||
*
|
|
||||||
* <p>The win block type is the type of block a player must hit to win in this arena</p>
|
|
||||||
*
|
|
||||||
* @param material <p>The material to set for the win block type</p>
|
|
||||||
* @return <p>True if successfully updated</p>
|
|
||||||
*/
|
|
||||||
public boolean setWinBlockType(@NotNull Material material) {
|
public boolean setWinBlockType(@NotNull Material material) {
|
||||||
if (material.isAir() || !material.isBlock()) {
|
if (material.isAir() || !material.isBlock()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
this.winBlockType = material;
|
this.winBlockType = material;
|
||||||
this.parkourArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,13 +465,18 @@ public class ParkourArena implements Arena {
|
|||||||
* @param newLocation <p>The location players have to reach</p>
|
* @param newLocation <p>The location players have to reach</p>
|
||||||
* @return <p>True if successfully changed</p>
|
* @return <p>True if successfully changed</p>
|
||||||
*/
|
*/
|
||||||
public boolean setWinLocation(@NotNull Location newLocation) {
|
public boolean setWinLocation(@Nullable Location newLocation) {
|
||||||
if (isInvalid(newLocation)) {
|
if (newLocation == null) {
|
||||||
return false;
|
// Un-set the win location, and fall back to the win block type
|
||||||
} else {
|
this.winLocation = null;
|
||||||
this.winLocation = newLocation.clone();
|
this.saveArena();
|
||||||
this.parkourArenaHandler.saveArenas();
|
|
||||||
return true;
|
return true;
|
||||||
|
} else if (!isInvalid(newLocation)) {
|
||||||
|
this.winLocation = newLocation.clone();
|
||||||
|
this.saveArena();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,8 +485,9 @@ public class ParkourArena implements Arena {
|
|||||||
*
|
*
|
||||||
* @param killPlaneBlockNames <p>The names of the blocks that will cause players to lose</p>
|
* @param killPlaneBlockNames <p>The names of the blocks that will cause players to lose</p>
|
||||||
*/
|
*/
|
||||||
public boolean setKillPlaneBlocks(@NotNull Set<String> killPlaneBlockNames) {
|
public boolean setKillPlaneBlocks(@Nullable Set<String> killPlaneBlockNames) {
|
||||||
if (killPlaneBlockNames.isEmpty()) {
|
if (killPlaneBlockNames == null || killPlaneBlockNames.isEmpty()) {
|
||||||
|
this.killPlaneBlockNames = null;
|
||||||
this.killPlaneBlocks = null;
|
this.killPlaneBlocks = null;
|
||||||
} else {
|
} else {
|
||||||
Set<Material> parsed = MaterialHelper.loadMaterialList(new ArrayList<>(killPlaneBlockNames), "+",
|
Set<Material> parsed = MaterialHelper.loadMaterialList(new ArrayList<>(killPlaneBlockNames), "+",
|
||||||
@ -402,9 +495,32 @@ public class ParkourArena implements Arena {
|
|||||||
if (parsed.isEmpty()) {
|
if (parsed.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
this.killPlaneBlockNames = killPlaneBlockNames;
|
||||||
this.killPlaneBlocks = parsed;
|
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(@Nullable Set<String> obstacleBlockNames) {
|
||||||
|
if (obstacleBlockNames == null || 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,13 +530,13 @@ public class ParkourArena implements Arena {
|
|||||||
* @param checkpoint <p>The checkpoint to add</p>
|
* @param checkpoint <p>The checkpoint to add</p>
|
||||||
* @return <p>True if successfully added</p>
|
* @return <p>True if successfully added</p>
|
||||||
*/
|
*/
|
||||||
public boolean addCheckpoint(@NotNull Location checkpoint) {
|
public boolean addCheckpoint(@Nullable Location checkpoint) {
|
||||||
if (isInvalid(checkpoint)) {
|
if (isInvalid(checkpoint)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkpoints.add(checkpoint.clone());
|
this.checkpoints.add(checkpoint.clone());
|
||||||
this.parkourArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,10 +551,23 @@ public class ParkourArena implements Arena {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.checkpoints.clear();
|
this.checkpoints.clear();
|
||||||
this.parkourArenaHandler.saveArenas();
|
this.saveArena();
|
||||||
return true;
|
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
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (!(other instanceof ParkourArena otherArena)) {
|
if (!(other instanceof ParkourArena otherArena)) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.knarcraft.minigames.arena.parkour;
|
package net.knarcraft.minigames.arena.parkour;
|
||||||
|
|
||||||
import net.knarcraft.minigames.arena.EditablePropertyType;
|
import net.knarcraft.minigames.arena.EditablePropertyType;
|
||||||
|
import net.knarcraft.minigames.util.ArenaStorageHelper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -62,6 +63,32 @@ public enum ParkourArenaEditableProperty {
|
|||||||
*/
|
*/
|
||||||
KILL_PLANE_BLOCKS("killPlaneBlocks", (arena) -> String.valueOf(arena.getKillPlaneBlockNames()),
|
KILL_PLANE_BLOCKS("killPlaneBlocks", (arena) -> String.valueOf(arena.getKillPlaneBlockNames()),
|
||||||
EditablePropertyType.MATERIAL_LIST),
|
EditablePropertyType.MATERIAL_LIST),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The blocks used as this arena's obstacle blocks
|
||||||
|
*/
|
||||||
|
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),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arena's allowed damage causes
|
||||||
|
*/
|
||||||
|
ALLOWED_DAMAGE_CAUSES("allowedDamageCauses", (arena) -> String.valueOf(
|
||||||
|
ArenaStorageHelper.getDamageCauseNames(arena.getAllowedDamageCauses())),
|
||||||
|
EditablePropertyType.DAMAGE_CAUSE_LIST),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arena's loss trigger damage causes
|
||||||
|
*/
|
||||||
|
LOSS_TRIGGER_DAMAGE_CAUSES("lossTriggerDamageCauses", (arena) -> String.valueOf(
|
||||||
|
ArenaStorageHelper.getDamageCauseNames(arena.getLossTriggerDamageCauses())),
|
||||||
|
EditablePropertyType.DAMAGE_CAUSE_LIST),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final @NotNull String argumentString;
|
private final @NotNull String argumentString;
|
||||||
|
@ -29,7 +29,7 @@ public enum ParkourArenaGameMode implements ConfigurationSerializable, ArenaGame
|
|||||||
* @param gameMode <p>The game-mode string to match</p>
|
* @param gameMode <p>The game-mode string to match</p>
|
||||||
* @return <p>The specified arena game-mode</p>
|
* @return <p>The specified arena game-mode</p>
|
||||||
*/
|
*/
|
||||||
public static @NotNull ParkourArenaGameMode matchGamemode(@NotNull String gameMode) {
|
public static @NotNull ParkourArenaGameMode matchGameMode(@NotNull String gameMode) {
|
||||||
try {
|
try {
|
||||||
return ParkourArenaGameMode.valueOf(gameMode.toUpperCase());
|
return ParkourArenaGameMode.valueOf(gameMode.toUpperCase());
|
||||||
} catch (IllegalArgumentException exception) {
|
} catch (IllegalArgumentException exception) {
|
||||||
|
@ -3,18 +3,29 @@ package net.knarcraft.minigames.arena.parkour;
|
|||||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.AbstractArenaSession;
|
import net.knarcraft.minigames.arena.AbstractArenaSession;
|
||||||
|
import net.knarcraft.minigames.arena.Arena;
|
||||||
import net.knarcraft.minigames.arena.PlayerEntryState;
|
import net.knarcraft.minigames.arena.PlayerEntryState;
|
||||||
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
import net.knarcraft.minigames.gui.ArenaGUI;
|
import net.knarcraft.minigames.gui.ArenaGUI;
|
||||||
import net.knarcraft.minigames.gui.ParkourGUI;
|
import net.knarcraft.minigames.gui.ParkourGUI;
|
||||||
|
import net.knarcraft.minigames.gui.ParkourGUIBedrock;
|
||||||
|
import net.knarcraft.minigames.util.GeyserHelper;
|
||||||
import net.knarcraft.minigames.util.PlayerTeleporter;
|
import net.knarcraft.minigames.util.PlayerTeleporter;
|
||||||
import net.knarcraft.minigames.util.RewardHelper;
|
import net.knarcraft.minigames.util.RewardHelper;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.block.data.Powerable;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,10 +33,11 @@ import java.util.logging.Level;
|
|||||||
*/
|
*/
|
||||||
public class ParkourArenaSession extends AbstractArenaSession {
|
public class ParkourArenaSession extends AbstractArenaSession {
|
||||||
|
|
||||||
|
private static final @NotNull Map<Arena, Set<Block>> changedLevers = new HashMap<>();
|
||||||
private final @NotNull ParkourArena arena;
|
private final @NotNull ParkourArena arena;
|
||||||
private final @NotNull Player player;
|
private final @NotNull Player player;
|
||||||
private final @NotNull ParkourArenaGameMode gameMode;
|
private final @NotNull ParkourArenaGameMode gameMode;
|
||||||
private Location reachedCheckpoint = null;
|
private @Nullable Location reachedCheckpoint = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new parkour arena session
|
* Instantiates a new parkour arena session
|
||||||
@ -63,6 +75,16 @@ public class ParkourArenaSession extends AbstractArenaSession {
|
|||||||
this.reachedCheckpoint = location;
|
this.reachedCheckpoint = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a lever change
|
||||||
|
*
|
||||||
|
* @param block <p>The block of the lever</p>
|
||||||
|
*/
|
||||||
|
public void registerChangedLever(@NotNull Block block) {
|
||||||
|
changedLevers.putIfAbsent(this.arena, new HashSet<>());
|
||||||
|
changedLevers.get(this.arena).add(block);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the checkpoint currently registered as the player's spawn location
|
* Gets the checkpoint currently registered as the player's spawn location
|
||||||
*
|
*
|
||||||
@ -102,6 +124,10 @@ public class ParkourArenaSession extends AbstractArenaSession {
|
|||||||
|
|
||||||
// Teleport the player out of the arena
|
// Teleport the player out of the arena
|
||||||
teleportToExit(false);
|
teleportToExit(false);
|
||||||
|
|
||||||
|
if (MiniGames.getInstance().getParkourArenaPlayerRegistry().getPlayingPlayers(this.arena).isEmpty()) {
|
||||||
|
resetLevers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -110,6 +136,7 @@ public class ParkourArenaSession extends AbstractArenaSession {
|
|||||||
//Teleport the player back to the top
|
//Teleport the player back to the top
|
||||||
Location spawnLocation = this.reachedCheckpoint != null ? this.reachedCheckpoint : this.arena.getSpawnLocation();
|
Location spawnLocation = this.reachedCheckpoint != null ? this.reachedCheckpoint : this.arena.getSpawnLocation();
|
||||||
PlayerTeleporter.teleportPlayer(this.player, spawnLocation, true, false);
|
PlayerTeleporter.teleportPlayer(this.player, spawnLocation, true, false);
|
||||||
|
this.player.playSound(this.player, Sound.ENTITY_CHICKEN_EGG, 5f, 0.5f);
|
||||||
this.entryState.setArenaState();
|
this.entryState.setArenaState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,12 +147,19 @@ public class ParkourArenaSession extends AbstractArenaSession {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ArenaGUI getGUI() {
|
public @NotNull ArenaGUI getGUI() {
|
||||||
return new ParkourGUI(player);
|
if (GeyserHelper.isGeyserPlayer(this.player)) {
|
||||||
|
return new ParkourGUIBedrock(this.player);
|
||||||
|
} else {
|
||||||
|
return new ParkourGUI(this.player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
this.reachedCheckpoint = null;
|
this.reachedCheckpoint = null;
|
||||||
|
if (MiniGames.getInstance().getParkourArenaPlayerRegistry().getPlayingPlayers(this.arena).size() == 1) {
|
||||||
|
resetLevers();
|
||||||
|
}
|
||||||
super.reset();
|
super.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,8 +169,8 @@ public class ParkourArenaSession extends AbstractArenaSession {
|
|||||||
boolean removedSession = MiniGames.getInstance().getParkourArenaPlayerRegistry().removePlayer(
|
boolean removedSession = MiniGames.getInstance().getParkourArenaPlayerRegistry().removePlayer(
|
||||||
player.getUniqueId(), true);
|
player.getUniqueId(), true);
|
||||||
if (!removedSession) {
|
if (!removedSession) {
|
||||||
MiniGames.log(Level.SEVERE, "Unable to remove parkour arena session for " + player.getName() + ". " +
|
MiniGames.log(Level.SEVERE, "Unable to remove parkour arena session for " + this.player.getName() +
|
||||||
"This will have unintended consequences.");
|
". This will have unintended consequences.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,4 +182,34 @@ public class ParkourArenaSession extends AbstractArenaSession {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void triggerQuit(boolean immediately, boolean removeSession) {
|
||||||
|
super.triggerQuit(immediately, removeSession);
|
||||||
|
|
||||||
|
// Note: As immediately is only used when stopping the server, levers should be reset regardless of current players
|
||||||
|
if (MiniGames.getInstance().getParkourArenaPlayerRegistry().getPlayingPlayers(this.arena).isEmpty() || immediately) {
|
||||||
|
resetLevers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets all levers if the arena is empty
|
||||||
|
*/
|
||||||
|
private void resetLevers() {
|
||||||
|
// Make a copy in case new player join while the levers are resetting
|
||||||
|
Set<Block> changed = changedLevers.remove(this.arena);
|
||||||
|
if (changed == null || changed.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset all levers toggled by players in the arena
|
||||||
|
for (Block block : changed) {
|
||||||
|
BlockData blockData = block.getBlockData();
|
||||||
|
if (blockData instanceof Powerable powerable) {
|
||||||
|
powerable.setPowered(false);
|
||||||
|
block.setBlockData(blockData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package net.knarcraft.minigames.arena.parkour;
|
package net.knarcraft.minigames.arena.parkour;
|
||||||
|
|
||||||
|
import net.knarcraft.minigames.arena.StorageKey;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of each key used for storing arena data
|
* A representation of each key used for storing arena data
|
||||||
*/
|
*/
|
||||||
public enum ParkourArenaStorageKey {
|
public enum ParkourArenaStorageKey implements StorageKey {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key for an arena's id
|
* The key for an arena's id
|
||||||
@ -42,6 +43,11 @@ public enum ParkourArenaStorageKey {
|
|||||||
*/
|
*/
|
||||||
KILL_PLANE_BLOCKS("killPlaneBlocks"),
|
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
|
* The key for this arena's checkpoint locations
|
||||||
*/
|
*/
|
||||||
@ -56,6 +62,21 @@ public enum ParkourArenaStorageKey {
|
|||||||
* The key for this arena's rewards
|
* The key for this arena's rewards
|
||||||
*/
|
*/
|
||||||
REWARDS("rewards"),
|
REWARDS("rewards"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key for this arena's maximum players
|
||||||
|
*/
|
||||||
|
MAX_PLAYERS("maxPlayers"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key for this arena's allowed damage causes
|
||||||
|
*/
|
||||||
|
ALLOWED_DAMAGE_CAUSES("allowedDamageCauses"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key for this arena's loss trigger damage causes
|
||||||
|
*/
|
||||||
|
LOSS_TRIGGER_DAMAGE_CAUSES("lossTriggerDamageCauses"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final @NotNull String key;
|
private final @NotNull String key;
|
||||||
@ -69,11 +90,7 @@ public enum ParkourArenaStorageKey {
|
|||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Gets the configuration key this enum represents
|
|
||||||
*
|
|
||||||
* @return <p>The string key representation.</p>
|
|
||||||
*/
|
|
||||||
public @NotNull String getKey() {
|
public @NotNull String getKey() {
|
||||||
return this.key;
|
return this.key;
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,11 @@ import net.knarcraft.minigames.container.SerializableUUID;
|
|||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -35,12 +38,18 @@ public class ParkourPlayerEntryState extends AbstractPlayerEntryState {
|
|||||||
* @param originalInvulnerable <p>Whether the player was invulnerable before entering the arena</p>
|
* @param originalInvulnerable <p>Whether the player was invulnerable before entering the arena</p>
|
||||||
* @param originalIsSwimming <p>Whether the player was swimming before entering the arena</p>
|
* @param originalIsSwimming <p>Whether the player was swimming before entering the arena</p>
|
||||||
* @param originalCollideAble <p>Whether the player was collide-able before entering the arena</p>
|
* @param originalCollideAble <p>Whether the player was collide-able before entering the arena</p>
|
||||||
|
* @param originalPotionEffects <p>The potion effects applied to the player when joining</p>
|
||||||
|
* @param originalHealth <p>The health of the player when joining the arena</p>
|
||||||
|
* @param originalSaturation <p>The saturation of the player when joining the arena</p>
|
||||||
*/
|
*/
|
||||||
public ParkourPlayerEntryState(@NotNull UUID playerId, Location entryLocation,
|
public ParkourPlayerEntryState(@NotNull UUID playerId, Location entryLocation,
|
||||||
boolean originalIsFlying, GameMode originalGameMode, boolean originalAllowFlight,
|
boolean originalIsFlying, GameMode originalGameMode, boolean originalAllowFlight,
|
||||||
boolean originalInvulnerable, boolean originalIsSwimming, boolean originalCollideAble) {
|
boolean originalInvulnerable, boolean originalIsSwimming,
|
||||||
|
boolean originalCollideAble, Collection<PotionEffect> originalPotionEffects,
|
||||||
|
double originalHealth, float originalSaturation) {
|
||||||
super(playerId, entryLocation, originalIsFlying, originalGameMode, originalAllowFlight,
|
super(playerId, entryLocation, originalIsFlying, originalGameMode, originalAllowFlight,
|
||||||
originalInvulnerable, originalIsSwimming, originalCollideAble);
|
originalInvulnerable, originalIsSwimming, originalCollideAble, originalPotionEffects, originalHealth,
|
||||||
|
originalSaturation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -60,7 +69,7 @@ public class ParkourPlayerEntryState extends AbstractPlayerEntryState {
|
|||||||
*
|
*
|
||||||
* @return <p>The data to deserialize</p>
|
* @return <p>The data to deserialize</p>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings({"unused", "unchecked"})
|
||||||
public static ParkourPlayerEntryState deserialize(Map<String, Object> data) {
|
public static ParkourPlayerEntryState deserialize(Map<String, Object> data) {
|
||||||
UUID playerId = ((SerializableUUID) data.get("playerId")).getRawValue();
|
UUID playerId = ((SerializableUUID) data.get("playerId")).getRawValue();
|
||||||
Location entryLocation = (Location) data.get("entryLocation");
|
Location entryLocation = (Location) data.get("entryLocation");
|
||||||
@ -70,9 +79,14 @@ public class ParkourPlayerEntryState extends AbstractPlayerEntryState {
|
|||||||
boolean originalInvulnerable = getBoolean(data, "originalInvulnerable");
|
boolean originalInvulnerable = getBoolean(data, "originalInvulnerable");
|
||||||
boolean originalIsSwimming = getBoolean(data, "originalIsSwimming");
|
boolean originalIsSwimming = getBoolean(data, "originalIsSwimming");
|
||||||
boolean originalCollideAble = getBoolean(data, "originalCollideAble");
|
boolean originalCollideAble = getBoolean(data, "originalCollideAble");
|
||||||
|
Collection<PotionEffect> originalPotionEffect =
|
||||||
|
(Collection<PotionEffect>) data.getOrDefault("originalPotionEffects", new ArrayList<>());
|
||||||
|
double originalHealth = ((Number) data.get("originalHealth")).doubleValue();
|
||||||
|
float originalSaturation = ((Number) data.get("originalSaturation")).floatValue();
|
||||||
|
|
||||||
return new ParkourPlayerEntryState(playerId, entryLocation, originalIsFlying,
|
return new ParkourPlayerEntryState(playerId, entryLocation, originalIsFlying, originalGameMode,
|
||||||
originalGameMode, originalAllowFlight, originalInvulnerable, originalIsSwimming, originalCollideAble);
|
originalAllowFlight, originalInvulnerable, originalIsSwimming, originalCollideAble,
|
||||||
|
originalPotionEffect, originalHealth, originalSaturation);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,13 @@ public abstract class ArenaRecord<K extends Comparable<K>> implements Comparable
|
|||||||
return record;
|
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
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
return other instanceof ArenaRecord<?> && userId.equals(((ArenaRecord<?>) other).userId);
|
return other instanceof ArenaRecord<?> && userId.equals(((ArenaRecord<?>) other).userId);
|
||||||
|
@ -19,6 +19,11 @@ public class IntegerRecord extends SummableArenaRecord<Integer> {
|
|||||||
super(userId, record);
|
super(userId, record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAsString() {
|
||||||
|
return String.valueOf(this.getRecord());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SummableArenaRecord<Integer> sum(Integer value) {
|
public SummableArenaRecord<Integer> sum(Integer value) {
|
||||||
return new IntegerRecord(this.getUserId(), this.getRecord() + value);
|
return new IntegerRecord(this.getUserId(), this.getRecord() + value);
|
||||||
|
@ -7,7 +7,7 @@ import java.util.Map;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A record storing a Long
|
* A record storing a Long time
|
||||||
*/
|
*/
|
||||||
public class LongRecord extends SummableArenaRecord<Long> {
|
public class LongRecord extends SummableArenaRecord<Long> {
|
||||||
|
|
||||||
@ -29,6 +29,22 @@ public class LongRecord extends SummableArenaRecord<Long> {
|
|||||||
return new LongRecord(this.getUserId(), this.getRecord() + value);
|
return new LongRecord(this.getUserId(), this.getRecord() + value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAsString() {
|
||||||
|
double seconds = getRecord() / 1000.0;
|
||||||
|
double minutes = 0;
|
||||||
|
if (seconds > 60) {
|
||||||
|
minutes = seconds / 60.0;
|
||||||
|
seconds = seconds % 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minutes > 0) {
|
||||||
|
return String.format("%.0fm%.2fs", minutes, seconds);
|
||||||
|
} else {
|
||||||
|
return String.format("%.2fs", seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserializes the saved arena record
|
* Deserializes the saved arena record
|
||||||
*
|
*
|
||||||
@ -37,7 +53,8 @@ public class LongRecord extends SummableArenaRecord<Long> {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static LongRecord deserialize(@NotNull Map<String, Object> data) {
|
public static LongRecord deserialize(@NotNull Map<String, Object> data) {
|
||||||
return new LongRecord(((SerializableUUID) data.get("userId")).getRawValue(), ((Number) data.get("record")).longValue());
|
return new LongRecord(((SerializableUUID) data.get("userId")).getRawValue(),
|
||||||
|
((Number) data.get("record")).longValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package net.knarcraft.minigames.arena.reward;
|
|||||||
|
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@ -43,9 +44,10 @@ public class ItemReward implements Reward {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String getGrantMessage() {
|
public @NotNull String getGrantMessage() {
|
||||||
|
NamespacedKey key = item.getType().getKeyOrNull();
|
||||||
|
String name = key == null ? "Unnamed item" : key.getKey().replace("_", " ");
|
||||||
return MiniGames.getInstance().getStringFormatter().replacePlaceholders(MiniGameMessage.SUCCESS_ITEM_REWARDED,
|
return MiniGames.getInstance().getStringFormatter().replacePlaceholders(MiniGameMessage.SUCCESS_ITEM_REWARDED,
|
||||||
new String[]{"{amount}", "{item}"}, new String[]{String.valueOf(item.getAmount()),
|
new String[]{"{amount}", "{item}"}, new String[]{String.valueOf(item.getAmount()), name});
|
||||||
item.getType().getKey().getKey().replace("_", " ")});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -22,6 +22,7 @@ public interface Reward extends ConfigurationSerializable {
|
|||||||
*
|
*
|
||||||
* @return <p>The message to display when this reward is granted</p>
|
* @return <p>The message to display when this reward is granted</p>
|
||||||
*/
|
*/
|
||||||
@NotNull String getGrantMessage();
|
@NotNull
|
||||||
|
String getGrantMessage();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,134 @@
|
|||||||
|
package net.knarcraft.minigames.command;
|
||||||
|
|
||||||
|
import net.knarcraft.minigames.config.DropperConfiguration;
|
||||||
|
import net.knarcraft.minigames.util.InputValidationHelper;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 <p>The configuration to use</p>
|
||||||
|
*/
|
||||||
|
public EditArenaCommand(DropperConfiguration configuration) {
|
||||||
|
this.configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the specified max players
|
||||||
|
*
|
||||||
|
* @param maxPlayers <p>The max players string to parse</p>
|
||||||
|
* @return <p>The parsed value, or -1 if not parse-able</p>
|
||||||
|
*/
|
||||||
|
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 <p>The string to parse into a velocity</p>
|
||||||
|
* @return <p>The parsed velocity, defaulting to 0.5 if not parse-able</p>
|
||||||
|
*/
|
||||||
|
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 <p>The string to parse into a velocity</p>
|
||||||
|
* @return <p>The parsed velocity, defaulting to 1 if not parse-able</p>
|
||||||
|
*/
|
||||||
|
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 <p>The player changing a location</p>
|
||||||
|
* @param locationString <p>The location string to parse</p>
|
||||||
|
* @return <p>The parsed location, or the player's location if not parse-able</p>
|
||||||
|
*/
|
||||||
|
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 <p>The material name to parse</p>
|
||||||
|
* @return <p>The parsed material, or AIR if not valid</p>
|
||||||
|
*/
|
||||||
|
protected @NotNull Material parseMaterial(String materialName) {
|
||||||
|
Material material = Material.matchMaterial(materialName);
|
||||||
|
if (material == null) {
|
||||||
|
material = Material.AIR;
|
||||||
|
}
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits the given string on comma, and returns a set of its parts
|
||||||
|
*
|
||||||
|
* @param input <p>The input string to get as a set</p>
|
||||||
|
* @return <p>The resulting string set</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
protected Set<String> asSet(@NotNull String input) {
|
||||||
|
if (InputValidationHelper.isEmptyValue(input)) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return new HashSet<>(List.of(input.split(",")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package net.knarcraft.minigames.command;
|
||||||
|
|
||||||
|
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||||
|
import net.knarcraft.minigames.MiniGames;
|
||||||
|
import net.knarcraft.minigames.arena.Arena;
|
||||||
|
import net.knarcraft.minigames.arena.ArenaGroup;
|
||||||
|
import net.knarcraft.minigames.arena.ArenaHandler;
|
||||||
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabExecutor;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command for listing the arenas in a group
|
||||||
|
*
|
||||||
|
* @param <K> <p>The type of arena handler to get arenas from</p>
|
||||||
|
* @param <L> <p>The type of arena to list</p>
|
||||||
|
* @param <M> <p>The type of arena group to list</p>
|
||||||
|
*/
|
||||||
|
public abstract class GroupListCommand<
|
||||||
|
K extends ArenaHandler<L, M>,
|
||||||
|
L extends Arena,
|
||||||
|
M extends ArenaGroup<L, M>
|
||||||
|
> implements TabExecutor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays all currently existing dropper arena groups
|
||||||
|
*
|
||||||
|
* @param arenaHandler <p>The arena handler to get groups from</p>
|
||||||
|
* @param sender <p>The command sender to display the groups to</p>
|
||||||
|
*/
|
||||||
|
protected void displayExistingGroups(@NotNull K arenaHandler, @NotNull CommandSender sender) {
|
||||||
|
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
|
||||||
|
StringBuilder builder = new StringBuilder(stringFormatter.getUnFormattedMessage(
|
||||||
|
MiniGameMessage.SUCCESS_GROUPS)).append("\n");
|
||||||
|
arenaHandler.getAllGroups().stream().sorted().forEachOrdered((group) ->
|
||||||
|
builder.append("- ").append(group.getGroupName()).append("\n"));
|
||||||
|
stringFormatter.displaySuccessMessage(sender, builder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the ordered stages in a specified group to the specified command sender
|
||||||
|
*
|
||||||
|
* @param arenaHandler <p>The arena handler to get groups from</p>
|
||||||
|
* @param sender <p>The command sender to display the stages to</p>
|
||||||
|
* @param groupName <p>The name of the group to display stages for</p>
|
||||||
|
* @return <p>True if the stages were successfully displayed</p>
|
||||||
|
*/
|
||||||
|
protected boolean displayOrderedArenaNames(@NotNull K arenaHandler, @NotNull CommandSender sender,
|
||||||
|
@NotNull String groupName) {
|
||||||
|
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
|
||||||
|
M arenaGroup = arenaHandler.getGroup(groupName);
|
||||||
|
if (arenaGroup == null) {
|
||||||
|
stringFormatter.displayErrorMessage(sender, MiniGameMessage.ERROR_GROUP_NOT_FOUND);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a list of all stages (arenas in the group)
|
||||||
|
StringBuilder builder = new StringBuilder(stringFormatter.replacePlaceholder(
|
||||||
|
MiniGameMessage.SUCCESS_GROUP_STAGES, "{group}", groupName));
|
||||||
|
int counter = 1;
|
||||||
|
for (UUID arenaId : arenaGroup.getArenas()) {
|
||||||
|
L arena = arenaHandler.getArena(arenaId);
|
||||||
|
if (arena != null) {
|
||||||
|
builder.append("\n").append(counter++).append(". ").append(arena.getArenaName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stringFormatter.displaySuccessMessage(sender, builder.toString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all available groups
|
||||||
|
*
|
||||||
|
* @return <p>All available groups</p>
|
||||||
|
*/
|
||||||
|
protected abstract Set<M> getGroups();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||||
|
@NotNull String[] arguments) {
|
||||||
|
if (arguments.length == 1) {
|
||||||
|
List<String> groupNames = new ArrayList<>();
|
||||||
|
for (M group : getGroups()) {
|
||||||
|
groupNames.add(group.getGroupName());
|
||||||
|
}
|
||||||
|
return filterMatchingContains(groupNames, arguments[0]);
|
||||||
|
} else {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,6 +5,7 @@ import net.knarcraft.minigames.arena.Arena;
|
|||||||
import net.knarcraft.minigames.arena.reward.Reward;
|
import net.knarcraft.minigames.arena.reward.Reward;
|
||||||
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
|
import net.knarcraft.minigames.util.InputValidationHelper;
|
||||||
import net.knarcraft.minigames.util.RewardHelper;
|
import net.knarcraft.minigames.util.RewardHelper;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
@ -60,7 +61,7 @@ public class SetArenaRewardCommand implements CommandExecutor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments[0].equalsIgnoreCase("clear")) {
|
if (InputValidationHelper.isEmptyValue(arguments[0])) {
|
||||||
arena.clearRewards(condition);
|
arena.clearRewards(condition);
|
||||||
MiniGames.getInstance().getStringFormatter().displaySuccessMessage(player,
|
MiniGames.getInstance().getStringFormatter().displaySuccessMessage(player,
|
||||||
MiniGameMessage.SUCCESS_REWARDS_CLEARED);
|
MiniGameMessage.SUCCESS_REWARDS_CLEARED);
|
||||||
|
@ -6,6 +6,7 @@ import net.knarcraft.minigames.MiniGames;
|
|||||||
import net.knarcraft.minigames.arena.Arena;
|
import net.knarcraft.minigames.arena.Arena;
|
||||||
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
import net.knarcraft.minigames.arena.reward.RewardCondition;
|
||||||
import net.knarcraft.minigames.arena.reward.RewardType;
|
import net.knarcraft.minigames.arena.reward.RewardType;
|
||||||
|
import net.knarcraft.minigames.util.InputValidationHelper;
|
||||||
import net.knarcraft.minigames.util.TabCompleteHelper;
|
import net.knarcraft.minigames.util.TabCompleteHelper;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
@ -40,7 +41,7 @@ public class SetArenaRewardTabCompleter implements TabCompleter {
|
|||||||
}
|
}
|
||||||
if (arguments.length >= 2) {
|
if (arguments.length >= 2) {
|
||||||
// If the first argument is invalid, stop further tab completion
|
// 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<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,8 +74,7 @@ public class SetArenaRewardTabCompleter implements TabCompleter {
|
|||||||
}
|
}
|
||||||
if (arguments.length >= 5) {
|
if (arguments.length >= 5) {
|
||||||
// If the condition is invalid, or it's the clear action, stop tab-completion
|
// If the condition is invalid, or it's the clear action, stop tab-completion
|
||||||
if (RewardCondition.getFromString(arguments[3]) == null ||
|
if (RewardCondition.getFromString(arguments[3]) == null || InputValidationHelper.isEmptyValue(arguments[0])) {
|
||||||
arguments[0].equalsIgnoreCase("clear")) {
|
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ public class CreateDropperArenaCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DropperArenaHandler arenaHandler = MiniGames.getInstance().getDropperArenaHandler();
|
DropperArenaHandler arenaHandler = MiniGames.getInstance().getDropperArenaHandler();
|
||||||
|
|
||||||
DropperArena existingArena = arenaHandler.getArena(arenaName);
|
DropperArena existingArena = arenaHandler.getArena(arenaName);
|
||||||
if (existingArena != null) {
|
if (existingArena != null) {
|
||||||
MiniGames.getInstance().getStringFormatter().displayErrorMessage(commandSender,
|
MiniGames.getInstance().getStringFormatter().displayErrorMessage(commandSender,
|
||||||
|
@ -1,27 +1,20 @@
|
|||||||
package net.knarcraft.minigames.command.dropper;
|
package net.knarcraft.minigames.command.dropper;
|
||||||
|
|
||||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArena;
|
import net.knarcraft.minigames.arena.dropper.DropperArena;
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArenaGroup;
|
import net.knarcraft.minigames.arena.dropper.DropperArenaGroup;
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArenaHandler;
|
import net.knarcraft.minigames.arena.dropper.DropperArenaHandler;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.command.GroupListCommand;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.TabExecutor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Set;
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command for listing groups and the stages within
|
* The command for listing groups and the stages within
|
||||||
*/
|
*/
|
||||||
public class DropperGroupListCommand implements TabExecutor {
|
public class DropperGroupListCommand extends GroupListCommand<DropperArenaHandler, DropperArena, DropperArenaGroup> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||||
@ -37,63 +30,9 @@ public class DropperGroupListCommand implements TabExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays all currently existing dropper arena groups
|
|
||||||
*
|
|
||||||
* @param arenaHandler <p>The arena handler to get groups from</p>
|
|
||||||
* @param sender <p>The command sender to display the groups to</p>
|
|
||||||
*/
|
|
||||||
private void displayExistingGroups(@NotNull DropperArenaHandler arenaHandler, @NotNull CommandSender sender) {
|
|
||||||
StringBuilder builder = new StringBuilder("Dropper arena groups:").append("\n");
|
|
||||||
arenaHandler.getAllGroups().stream().sorted().forEachOrdered((group) ->
|
|
||||||
builder.append(group.getGroupName()).append("\n"));
|
|
||||||
sender.sendMessage(builder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the ordered stages in a specified group to the specified command sender
|
|
||||||
*
|
|
||||||
* @param arenaHandler <p>The arena handler to get groups from</p>
|
|
||||||
* @param sender <p>The command sender to display the stages to</p>
|
|
||||||
* @param groupName <p>The name of the group to display stages for</p>
|
|
||||||
* @return <p>True if the stages were successfully displayed</p>
|
|
||||||
*/
|
|
||||||
private boolean displayOrderedArenaNames(@NotNull DropperArenaHandler arenaHandler, @NotNull CommandSender sender,
|
|
||||||
@NotNull String groupName) {
|
|
||||||
DropperArenaGroup arenaGroup = arenaHandler.getGroup(groupName);
|
|
||||||
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
|
|
||||||
if (arenaGroup == null) {
|
|
||||||
stringFormatter.displayErrorMessage(sender, MiniGameMessage.ERROR_GROUP_NOT_FOUND);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a list of all stages (arenas in the group)
|
|
||||||
StringBuilder builder = new StringBuilder(stringFormatter.replacePlaceholder(
|
|
||||||
MiniGameMessage.SUCCESS_GROUP_STAGES, "{group}", groupName));
|
|
||||||
int counter = 1;
|
|
||||||
for (UUID arenaId : arenaGroup.getArenas()) {
|
|
||||||
DropperArena arena = arenaHandler.getArena(arenaId);
|
|
||||||
if (arena != null) {
|
|
||||||
builder.append(counter++).append(". ").append(arena.getArenaName()).append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stringFormatter.displaySuccessMessage(sender, builder.toString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
protected Set<DropperArenaGroup> getGroups() {
|
||||||
@NotNull String[] arguments) {
|
return MiniGames.getInstance().getDropperArenaHandler().getAllGroups();
|
||||||
if (arguments.length == 1) {
|
|
||||||
List<String> groupNames = new ArrayList<>();
|
|
||||||
for (DropperArenaGroup group : MiniGames.getInstance().getDropperArenaHandler().getAllGroups()) {
|
|
||||||
groupNames.add(group.getGroupName());
|
|
||||||
}
|
|
||||||
return filterMatchingContains(groupNames, arguments[0]);
|
|
||||||
} else {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import net.knarcraft.minigames.arena.dropper.DropperArena;
|
|||||||
import net.knarcraft.minigames.arena.dropper.DropperArenaGroup;
|
import net.knarcraft.minigames.arena.dropper.DropperArenaGroup;
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArenaHandler;
|
import net.knarcraft.minigames.arena.dropper.DropperArenaHandler;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
|
import net.knarcraft.minigames.util.InputValidationHelper;
|
||||||
import net.knarcraft.minigames.util.StringSanitizer;
|
import net.knarcraft.minigames.util.StringSanitizer;
|
||||||
import net.knarcraft.minigames.util.TabCompleteHelper;
|
import net.knarcraft.minigames.util.TabCompleteHelper;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
@ -46,7 +47,7 @@ public class DropperGroupSetCommand implements TabExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DropperArenaGroup arenaGroup;
|
DropperArenaGroup arenaGroup;
|
||||||
if (groupName.equalsIgnoreCase("null") || groupName.equalsIgnoreCase("none")) {
|
if (InputValidationHelper.isEmptyValue(groupName)) {
|
||||||
arenaGroup = null;
|
arenaGroup = null;
|
||||||
} else {
|
} else {
|
||||||
arenaGroup = arenaHandler.getGroup(groupName);
|
arenaGroup = arenaHandler.getGroup(groupName);
|
||||||
|
@ -4,12 +4,11 @@ import net.knarcraft.knarlib.formatting.StringFormatter;
|
|||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArena;
|
import net.knarcraft.minigames.arena.dropper.DropperArena;
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArenaEditableProperty;
|
import net.knarcraft.minigames.arena.dropper.DropperArenaEditableProperty;
|
||||||
|
import net.knarcraft.minigames.command.EditArenaCommand;
|
||||||
import net.knarcraft.minigames.config.DropperConfiguration;
|
import net.knarcraft.minigames.config.DropperConfiguration;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
import org.bukkit.Location;
|
import net.knarcraft.minigames.util.InputValidationHelper;
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -17,9 +16,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
/**
|
/**
|
||||||
* The command for editing an existing dropper arena
|
* The command for editing an existing dropper arena
|
||||||
*/
|
*/
|
||||||
public class EditDropperArenaCommand implements CommandExecutor {
|
public class EditDropperArenaCommand extends EditArenaCommand {
|
||||||
|
|
||||||
private final DropperConfiguration configuration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new edit arena command
|
* Instantiates a new edit arena command
|
||||||
@ -27,7 +24,7 @@ public class EditDropperArenaCommand implements CommandExecutor {
|
|||||||
* @param configuration <p>The configuration to use</p>
|
* @param configuration <p>The configuration to use</p>
|
||||||
*/
|
*/
|
||||||
public EditDropperArenaCommand(DropperConfiguration configuration) {
|
public EditDropperArenaCommand(DropperConfiguration configuration) {
|
||||||
this.configuration = configuration;
|
super(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -93,80 +90,12 @@ public class EditDropperArenaCommand implements CommandExecutor {
|
|||||||
case SPAWN_LOCATION -> arena.setSpawnLocation(parseLocation(player, value));
|
case SPAWN_LOCATION -> arena.setSpawnLocation(parseLocation(player, value));
|
||||||
case NAME -> arena.setName(value);
|
case NAME -> arena.setName(value);
|
||||||
case EXIT_LOCATION -> arena.setExitLocation(parseLocation(player, value));
|
case EXIT_LOCATION -> arena.setExitLocation(parseLocation(player, value));
|
||||||
|
case MAX_PLAYERS -> arena.setMaxPlayers(parseMaxPlayers(value));
|
||||||
|
case ALLOWED_DAMAGE_CAUSES ->
|
||||||
|
arena.setAllowedDamageCauses(InputValidationHelper.parseDamageCauses(asSet(value)));
|
||||||
|
case LOSS_TRIGGER_DAMAGE_CAUSES ->
|
||||||
|
arena.setLossTriggerDamageCauses(InputValidationHelper.parseDamageCauses(asSet(value)));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sanitizes the player's specified vertical velocity
|
|
||||||
*
|
|
||||||
* @param velocityString <p>The string to parse into a velocity</p>
|
|
||||||
* @return <p>The parsed velocity, defaulting to 0.5 if not parse-able</p>
|
|
||||||
*/
|
|
||||||
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 <p>The string to parse into a velocity</p>
|
|
||||||
* @return <p>The parsed velocity, defaulting to 1 if not parse-able</p>
|
|
||||||
*/
|
|
||||||
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 <p>The player changing a location</p>
|
|
||||||
* @param locationString <p>The location string to parse</p>
|
|
||||||
* @return <p>The parsed location, or the player's location if not parse-able</p>
|
|
||||||
*/
|
|
||||||
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 <p>The material name to parse</p>
|
|
||||||
* @return <p>The parsed material, or AIR if not valid</p>
|
|
||||||
*/
|
|
||||||
private @NotNull Material parseMaterial(String materialName) {
|
|
||||||
Material material = Material.matchMaterial(materialName);
|
|
||||||
if (material == null) {
|
|
||||||
material = Material.AIR;
|
|
||||||
}
|
|
||||||
return material;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.knarcraft.minigames.command.dropper;
|
package net.knarcraft.minigames.command.dropper;
|
||||||
|
|
||||||
|
import net.knarcraft.minigames.arena.EditablePropertyType;
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArenaEditableProperty;
|
import net.knarcraft.minigames.arena.dropper.DropperArenaEditableProperty;
|
||||||
import net.knarcraft.minigames.util.TabCompleteHelper;
|
import net.knarcraft.minigames.util.TabCompleteHelper;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
@ -30,8 +31,14 @@ public class EditDropperArenaTabCompleter implements TabCompleter {
|
|||||||
if (property == null) {
|
if (property == null) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
return filterMatchingContains(TabCompleteHelper.getTabCompleteSuggestions(property.getPropertyType()),
|
EditablePropertyType propertyType = property.getPropertyType();
|
||||||
arguments[2]);
|
|
||||||
|
if (propertyType == EditablePropertyType.MATERIAL_LIST ||
|
||||||
|
propertyType == EditablePropertyType.DAMAGE_CAUSE_LIST) {
|
||||||
|
return TabCompleteHelper.getListCompleteSuggestions(propertyType, arguments[2]);
|
||||||
|
} else {
|
||||||
|
return filterMatchingContains(TabCompleteHelper.getTabCompleteSuggestions(propertyType), arguments[2]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import net.knarcraft.minigames.arena.dropper.DropperArenaSession;
|
|||||||
import net.knarcraft.minigames.config.DropperConfiguration;
|
import net.knarcraft.minigames.config.DropperConfiguration;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
import net.knarcraft.minigames.util.GUIHelper;
|
import net.knarcraft.minigames.util.GUIHelper;
|
||||||
|
import net.knarcraft.minigames.util.GeyserHelper;
|
||||||
import net.knarcraft.minigames.util.PlayerTeleporter;
|
import net.knarcraft.minigames.util.PlayerTeleporter;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
@ -35,10 +36,15 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GeyserHelper.isGeyserPlayer(player)) {
|
||||||
|
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_GEYSER_DROPPER);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Disallow joining if the player is already in a mini-game arena
|
// Disallow joining if the player is already in a mini-game arena
|
||||||
if (MiniGames.getInstance().getSession(player.getUniqueId()) != null) {
|
if (MiniGames.getInstance().getSession(player.getUniqueId()) != null) {
|
||||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_ALREADY_PLAYING);
|
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_ALREADY_PLAYING);
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the arena exists
|
// Make sure the arena exists
|
||||||
@ -51,10 +57,18 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
|||||||
// Deny vehicles as allowing this is tricky, and will cause problems in some cases
|
// Deny vehicles as allowing this is tricky, and will cause problems in some cases
|
||||||
if (player.isInsideVehicle() || !player.getPassengers().isEmpty()) {
|
if (player.isInsideVehicle() || !player.getPassengers().isEmpty()) {
|
||||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_JOIN_IN_VEHICLE_OR_PASSENGER);
|
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_JOIN_IN_VEHICLE_OR_PASSENGER);
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return joinArena(specifiedArena, player, arguments);
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,13 +77,12 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
|||||||
* @param specifiedArena <p>The arena the player wants to join</p>
|
* @param specifiedArena <p>The arena the player wants to join</p>
|
||||||
* @param player <p>The player joining the arena</p>
|
* @param player <p>The player joining the arena</p>
|
||||||
* @param arguments <p>The arguments given</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
|
// Find the specified game-mode
|
||||||
DropperArenaGameMode gameMode;
|
DropperArenaGameMode gameMode;
|
||||||
if (arguments.length > 1) {
|
if (arguments.length > 1) {
|
||||||
gameMode = DropperArenaGameMode.matchGamemode(arguments[1]);
|
gameMode = DropperArenaGameMode.matchGameMode(arguments[1]);
|
||||||
} else {
|
} else {
|
||||||
gameMode = DropperArenaGameMode.DEFAULT;
|
gameMode = DropperArenaGameMode.DEFAULT;
|
||||||
}
|
}
|
||||||
@ -77,7 +90,7 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
|||||||
// Make sure the player has beaten the necessary levels
|
// Make sure the player has beaten the necessary levels
|
||||||
DropperArenaGroup arenaGroup = MiniGames.getInstance().getDropperArenaHandler().getGroup(specifiedArena.getArenaId());
|
DropperArenaGroup arenaGroup = MiniGames.getInstance().getDropperArenaHandler().getGroup(specifiedArena.getArenaId());
|
||||||
if (arenaGroup != null && !doGroupChecks(specifiedArena, arenaGroup, gameMode, player)) {
|
if (arenaGroup != null && !doGroupChecks(specifiedArena, arenaGroup, gameMode, player)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
|
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
|
||||||
@ -87,7 +100,7 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
|||||||
gameMode != DropperArenaGameMode.DEFAULT &&
|
gameMode != DropperArenaGameMode.DEFAULT &&
|
||||||
specifiedArena.getData().hasNotCompleted(DropperArenaGameMode.DEFAULT, player)) {
|
specifiedArena.getData().hasNotCompleted(DropperArenaGameMode.DEFAULT, player)) {
|
||||||
stringFormatter.displayErrorMessage(player, MiniGameMessage.ERROR_NORMAL_MODE_REQUIRED);
|
stringFormatter.displayErrorMessage(player, MiniGameMessage.ERROR_NORMAL_MODE_REQUIRED);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the player's session
|
// Register the player's session
|
||||||
@ -103,14 +116,12 @@ public class JoinDropperArenaCommand implements CommandExecutor {
|
|||||||
if (!teleported) {
|
if (!teleported) {
|
||||||
stringFormatter.displayErrorMessage(player, MiniGameMessage.ERROR_ARENA_TELEPORT_FAILED);
|
stringFormatter.displayErrorMessage(player, MiniGameMessage.ERROR_ARENA_TELEPORT_FAILED);
|
||||||
newSession.triggerQuit(false, true);
|
newSession.triggerQuit(false, true);
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
// Update the player's state to follow the arena's rules
|
// Update the player's state to follow the arena's rules
|
||||||
newSession.getEntryState().setArenaState();
|
newSession.getEntryState().setArenaState();
|
||||||
|
|
||||||
player.getInventory().addItem(GUIHelper.getGUIOpenItem());
|
player.getInventory().addItem(GUIHelper.getGUIOpenItem(player));
|
||||||
stringFormatter.displaySuccessMessage(player, MiniGameMessage.SUCCESS_ARENA_JOINED);
|
stringFormatter.displaySuccessMessage(player, MiniGameMessage.SUCCESS_ARENA_JOINED);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@ public class CreateParkourArenaCommand implements CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ParkourArenaHandler arenaHandler = MiniGames.getInstance().getParkourArenaHandler();
|
ParkourArenaHandler arenaHandler = MiniGames.getInstance().getParkourArenaHandler();
|
||||||
|
|
||||||
ParkourArena existingArena = arenaHandler.getArena(arenaName);
|
ParkourArena existingArena = arenaHandler.getArena(arenaName);
|
||||||
if (existingArena != null) {
|
if (existingArena != null) {
|
||||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_ARENA_NAME_COLLISION);
|
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_ARENA_NAME_COLLISION);
|
||||||
|
@ -4,27 +4,24 @@ import net.knarcraft.knarlib.formatting.StringFormatter;
|
|||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArenaEditableProperty;
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaEditableProperty;
|
||||||
|
import net.knarcraft.minigames.command.EditArenaCommand;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
import org.bukkit.Location;
|
import net.knarcraft.minigames.util.InputValidationHelper;
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command for editing an existing dropper arena
|
* The command for editing an existing dropper arena
|
||||||
*/
|
*/
|
||||||
public class EditParkourArenaCommand implements CommandExecutor {
|
public class EditParkourArenaCommand extends EditArenaCommand {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new edit arena command
|
* Instantiates a new edit arena command
|
||||||
*/
|
*/
|
||||||
public EditParkourArenaCommand() {
|
public EditParkourArenaCommand() {
|
||||||
|
super(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -60,7 +57,12 @@ public class EditParkourArenaCommand implements CommandExecutor {
|
|||||||
new String[]{editableProperty.getArgumentString(), value}));
|
new String[]{editableProperty.getArgumentString(), value}));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} 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) {
|
if (successful) {
|
||||||
stringFormatter.displaySuccessMessage(player, stringFormatter.replacePlaceholder(
|
stringFormatter.displaySuccessMessage(player, stringFormatter.replacePlaceholder(
|
||||||
MiniGameMessage.SUCCESS_PROPERTY_CHANGED, "{property}",
|
MiniGameMessage.SUCCESS_PROPERTY_CHANGED, "{property}",
|
||||||
@ -80,9 +82,10 @@ public class EditParkourArenaCommand implements CommandExecutor {
|
|||||||
* @param value <p>The new value of the property</p>
|
* @param value <p>The new value of the property</p>
|
||||||
* @param player <p>The player trying to change the value</p>
|
* @param player <p>The player trying to change the value</p>
|
||||||
* @return <p>True if the value was successfully changed</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,
|
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) {
|
return switch (property) {
|
||||||
case WIN_BLOCK_TYPE -> arena.setWinBlockType(parseMaterial(value));
|
case WIN_BLOCK_TYPE -> arena.setWinBlockType(parseMaterial(value));
|
||||||
case SPAWN_LOCATION -> arena.setSpawnLocation(parseLocation(player, value));
|
case SPAWN_LOCATION -> arena.setSpawnLocation(parseLocation(player, value));
|
||||||
@ -91,42 +94,14 @@ public class EditParkourArenaCommand implements CommandExecutor {
|
|||||||
case WIN_LOCATION -> arena.setWinLocation(parseLocation(player, value));
|
case WIN_LOCATION -> arena.setWinLocation(parseLocation(player, value));
|
||||||
case CHECKPOINT_ADD -> arena.addCheckpoint(parseLocation(player, value));
|
case CHECKPOINT_ADD -> arena.addCheckpoint(parseLocation(player, value));
|
||||||
case CHECKPOINT_CLEAR -> arena.clearCheckpoints();
|
case CHECKPOINT_CLEAR -> arena.clearCheckpoints();
|
||||||
case KILL_PLANE_BLOCKS -> arena.setKillPlaneBlocks(new HashSet<>(List.of(value.split(","))));
|
case KILL_PLANE_BLOCKS -> arena.setKillPlaneBlocks(asSet(value));
|
||||||
|
case OBSTACLE_BLOCKS -> arena.setObstacleBlocks(asSet(value));
|
||||||
|
case MAX_PLAYERS -> arena.setMaxPlayers(parseMaxPlayers(value));
|
||||||
|
case ALLOWED_DAMAGE_CAUSES ->
|
||||||
|
arena.setAllowedDamageCauses(InputValidationHelper.parseDamageCauses(asSet(value)));
|
||||||
|
case LOSS_TRIGGER_DAMAGE_CAUSES ->
|
||||||
|
arena.setLossTriggerDamageCauses(InputValidationHelper.parseDamageCauses(asSet(value)));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the given location string
|
|
||||||
*
|
|
||||||
* @param player <p>The player changing a location</p>
|
|
||||||
* @param locationString <p>The location string to parse</p>
|
|
||||||
* @return <p>The parsed location, or the player's location if not parse-able</p>
|
|
||||||
*/
|
|
||||||
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 <p>The material name to parse</p>
|
|
||||||
* @return <p>The parsed material, or AIR if not valid</p>
|
|
||||||
*/
|
|
||||||
private @NotNull Material parseMaterial(String materialName) {
|
|
||||||
Material material = Material.matchMaterial(materialName);
|
|
||||||
if (material == null) {
|
|
||||||
material = Material.AIR;
|
|
||||||
}
|
|
||||||
return material;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.knarcraft.minigames.command.parkour;
|
package net.knarcraft.minigames.command.parkour;
|
||||||
|
|
||||||
|
import net.knarcraft.minigames.arena.EditablePropertyType;
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArenaEditableProperty;
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaEditableProperty;
|
||||||
import net.knarcraft.minigames.util.TabCompleteHelper;
|
import net.knarcraft.minigames.util.TabCompleteHelper;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
@ -30,8 +31,14 @@ public class EditParkourArenaTabCompleter implements TabCompleter {
|
|||||||
if (property == null) {
|
if (property == null) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
return filterMatchingContains(TabCompleteHelper.getTabCompleteSuggestions(property.getPropertyType()),
|
EditablePropertyType propertyType = property.getPropertyType();
|
||||||
arguments[2]);
|
|
||||||
|
if (propertyType == EditablePropertyType.MATERIAL_LIST ||
|
||||||
|
propertyType == EditablePropertyType.DAMAGE_CAUSE_LIST) {
|
||||||
|
return TabCompleteHelper.getListCompleteSuggestions(propertyType, arguments[2]);
|
||||||
|
} else {
|
||||||
|
return filterMatchingContains(TabCompleteHelper.getTabCompleteSuggestions(propertyType), arguments[2]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
|||||||
// Disallow joining if the player is already in a mini-game arena
|
// Disallow joining if the player is already in a mini-game arena
|
||||||
if (MiniGames.getInstance().getSession(player.getUniqueId()) != null) {
|
if (MiniGames.getInstance().getSession(player.getUniqueId()) != null) {
|
||||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_ALREADY_PLAYING);
|
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_ALREADY_PLAYING);
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the arena exists
|
// Make sure the arena exists
|
||||||
@ -51,10 +51,18 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
|||||||
// Deny vehicles as allowing this is tricky, and will cause problems in some cases
|
// Deny vehicles as allowing this is tricky, and will cause problems in some cases
|
||||||
if (player.isInsideVehicle() || !player.getPassengers().isEmpty()) {
|
if (player.isInsideVehicle() || !player.getPassengers().isEmpty()) {
|
||||||
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_JOIN_IN_VEHICLE_OR_PASSENGER);
|
stringFormatter.displayErrorMessage(commandSender, MiniGameMessage.ERROR_JOIN_IN_VEHICLE_OR_PASSENGER);
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return joinArena(specifiedArena, player, arguments);
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,13 +71,12 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
|||||||
* @param specifiedArena <p>The arena the player wants to join</p>
|
* @param specifiedArena <p>The arena the player wants to join</p>
|
||||||
* @param player <p>The player joining the arena</p>
|
* @param player <p>The player joining the arena</p>
|
||||||
* @param arguments <p>The arguments given</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
|
// Find the specified game-mode
|
||||||
ParkourArenaGameMode gameMode;
|
ParkourArenaGameMode gameMode;
|
||||||
if (arguments.length > 1) {
|
if (arguments.length > 1) {
|
||||||
gameMode = ParkourArenaGameMode.matchGamemode(arguments[1]);
|
gameMode = ParkourArenaGameMode.matchGameMode(arguments[1]);
|
||||||
} else {
|
} else {
|
||||||
gameMode = ParkourArenaGameMode.DEFAULT;
|
gameMode = ParkourArenaGameMode.DEFAULT;
|
||||||
}
|
}
|
||||||
@ -78,13 +85,13 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
|||||||
if (specifiedArena.hasNoCheckpoints() && gameMode == ParkourArenaGameMode.HARDCORE) {
|
if (specifiedArena.hasNoCheckpoints() && gameMode == ParkourArenaGameMode.HARDCORE) {
|
||||||
MiniGames.getInstance().getStringFormatter().displayErrorMessage(player,
|
MiniGames.getInstance().getStringFormatter().displayErrorMessage(player,
|
||||||
MiniGameMessage.ERROR_HARDCORE_NO_CHECKPOINTS);
|
MiniGameMessage.ERROR_HARDCORE_NO_CHECKPOINTS);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the player has beaten the necessary levels
|
// Make sure the player has beaten the necessary levels
|
||||||
ParkourArenaGroup arenaGroup = MiniGames.getInstance().getParkourArenaHandler().getGroup(specifiedArena.getArenaId());
|
ParkourArenaGroup arenaGroup = MiniGames.getInstance().getParkourArenaHandler().getGroup(specifiedArena.getArenaId());
|
||||||
if (arenaGroup != null && !doGroupChecks(specifiedArena, arenaGroup, gameMode, player)) {
|
if (arenaGroup != null && !doGroupChecks(specifiedArena, arenaGroup, gameMode, player)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the player's session
|
// Register the player's session
|
||||||
@ -101,15 +108,13 @@ public class JoinParkourArenaCommand implements CommandExecutor {
|
|||||||
MiniGames.getInstance().getStringFormatter().displayErrorMessage(player,
|
MiniGames.getInstance().getStringFormatter().displayErrorMessage(player,
|
||||||
MiniGameMessage.ERROR_ARENA_TELEPORT_FAILED);
|
MiniGameMessage.ERROR_ARENA_TELEPORT_FAILED);
|
||||||
newSession.triggerQuit(false, true);
|
newSession.triggerQuit(false, true);
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
// Update the player's state to follow the arena's rules
|
// Update the player's state to follow the arena's rules
|
||||||
newSession.getEntryState().setArenaState();
|
newSession.getEntryState().setArenaState();
|
||||||
|
|
||||||
player.getInventory().addItem(GUIHelper.getGUIOpenItem());
|
player.getInventory().addItem(GUIHelper.getGUIOpenItem(player));
|
||||||
MiniGames.getInstance().getStringFormatter().displaySuccessMessage(player,
|
MiniGames.getInstance().getStringFormatter().displaySuccessMessage(player,
|
||||||
MiniGameMessage.SUCCESS_ARENA_JOINED);
|
MiniGameMessage.SUCCESS_ARENA_JOINED);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,28 +1,20 @@
|
|||||||
package net.knarcraft.minigames.command.parkour;
|
package net.knarcraft.minigames.command.parkour;
|
||||||
|
|
||||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArenaGroup;
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaGroup;
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArenaHandler;
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaHandler;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.command.GroupListCommand;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.TabExecutor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command for listing groups and the stages within
|
* The command for listing groups and the stages within
|
||||||
*/
|
*/
|
||||||
public class ParkourGroupListCommand implements TabExecutor {
|
public class ParkourGroupListCommand extends GroupListCommand<ParkourArenaHandler, ParkourArena, ParkourArenaGroup> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
||||||
@ -38,64 +30,9 @@ public class ParkourGroupListCommand implements TabExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays all currently existing parkour arena groups
|
|
||||||
*
|
|
||||||
* @param arenaHandler <p>The arena handler to get groups from</p>
|
|
||||||
* @param sender <p>The command sender to display the groups to</p>
|
|
||||||
*/
|
|
||||||
private void displayExistingGroups(@NotNull ParkourArenaHandler arenaHandler, @NotNull CommandSender sender) {
|
|
||||||
StringBuilder builder = new StringBuilder("Parkour arena groups:").append("\n");
|
|
||||||
arenaHandler.getAllGroups().stream().sorted().forEachOrdered((group) ->
|
|
||||||
builder.append(group.getGroupName()).append("\n"));
|
|
||||||
sender.sendMessage(builder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the ordered stages in a specified group to the specified command sender
|
|
||||||
*
|
|
||||||
* @param arenaHandler <p>The arena handler to get groups from</p>
|
|
||||||
* @param sender <p>The command sender to display the stages to</p>
|
|
||||||
* @param groupName <p>The name of the group to display stages for</p>
|
|
||||||
* @return <p>True if the stages were successfully displayed</p>
|
|
||||||
*/
|
|
||||||
private boolean displayOrderedArenaNames(@NotNull ParkourArenaHandler arenaHandler, @NotNull CommandSender sender,
|
|
||||||
@NotNull String groupName) {
|
|
||||||
StringFormatter stringFormatter = MiniGames.getInstance().getStringFormatter();
|
|
||||||
ParkourArenaGroup arenaGroup = arenaHandler.getGroup(groupName);
|
|
||||||
if (arenaGroup == null) {
|
|
||||||
stringFormatter.displayErrorMessage(sender, MiniGameMessage.ERROR_GROUP_NOT_FOUND);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a list of all stages (arenas in the group)
|
|
||||||
StringBuilder builder = new StringBuilder(stringFormatter.replacePlaceholder(
|
|
||||||
MiniGameMessage.SUCCESS_GROUP_STAGES, "{group}", groupName));
|
|
||||||
int counter = 1;
|
|
||||||
for (UUID arenaId : arenaGroup.getArenas()) {
|
|
||||||
ParkourArena arena = arenaHandler.getArena(arenaId);
|
|
||||||
if (arena != null) {
|
|
||||||
builder.append("\n").append(counter++).append(". ").append(arena.getArenaName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stringFormatter.displaySuccessMessage(sender, builder.toString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s,
|
protected Set<ParkourArenaGroup> getGroups() {
|
||||||
@NotNull String[] arguments) {
|
return MiniGames.getInstance().getParkourArenaHandler().getAllGroups();
|
||||||
if (arguments.length == 1) {
|
|
||||||
List<String> groupNames = new ArrayList<>();
|
|
||||||
Set<ParkourArenaGroup> arenaGroups = MiniGames.getInstance().getParkourArenaHandler().getAllGroups();
|
|
||||||
for (ParkourArenaGroup group : arenaGroups) {
|
|
||||||
groupNames.add(group.getGroupName());
|
|
||||||
}
|
|
||||||
return filterMatchingContains(groupNames, arguments[0]);
|
|
||||||
} else {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
|||||||
import net.knarcraft.minigames.arena.parkour.ParkourArenaGroup;
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaGroup;
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArenaHandler;
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaHandler;
|
||||||
import net.knarcraft.minigames.config.MiniGameMessage;
|
import net.knarcraft.minigames.config.MiniGameMessage;
|
||||||
|
import net.knarcraft.minigames.util.InputValidationHelper;
|
||||||
import net.knarcraft.minigames.util.StringSanitizer;
|
import net.knarcraft.minigames.util.StringSanitizer;
|
||||||
import net.knarcraft.minigames.util.TabCompleteHelper;
|
import net.knarcraft.minigames.util.TabCompleteHelper;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
@ -47,7 +48,7 @@ public class ParkourGroupSetCommand implements TabExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ParkourArenaGroup arenaGroup;
|
ParkourArenaGroup arenaGroup;
|
||||||
if (groupName.equalsIgnoreCase("null") || groupName.equalsIgnoreCase("none")) {
|
if (InputValidationHelper.isEmptyValue(groupName)) {
|
||||||
arenaGroup = null;
|
arenaGroup = null;
|
||||||
} else {
|
} else {
|
||||||
arenaGroup = arenaHandler.getGroup(groupName);
|
arenaGroup = arenaHandler.getGroup(groupName);
|
||||||
|
@ -165,6 +165,16 @@ public enum MiniGameMessage implements TranslatableMessage {
|
|||||||
*/
|
*/
|
||||||
ERROR_REWARD_CONDITION_INVALID,
|
ERROR_REWARD_CONDITION_INVALID,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message displayed when a geyser player tries to join a dropper arena
|
||||||
|
*/
|
||||||
|
ERROR_GEYSER_DROPPER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message displayed when a player attempts to join a full arena
|
||||||
|
*/
|
||||||
|
ERROR_JOIN_ARENA_FULL,
|
||||||
|
|
||||||
/* **************** *
|
/* **************** *
|
||||||
* Success messages *
|
* Success messages *
|
||||||
* **************** */
|
* **************** */
|
||||||
@ -293,6 +303,11 @@ public enum MiniGameMessage implements TranslatableMessage {
|
|||||||
* The message displayed when arena rewards have been cleared
|
* The message displayed when arena rewards have been cleared
|
||||||
*/
|
*/
|
||||||
SUCCESS_REWARDS_CLEARED,
|
SUCCESS_REWARDS_CLEARED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message displayed when listing arena groups
|
||||||
|
*/
|
||||||
|
SUCCESS_GROUPS,
|
||||||
;
|
;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,6 +17,7 @@ public class ParkourConfiguration extends MiniGameConfiguration {
|
|||||||
private boolean mustDoGroupedInSequence;
|
private boolean mustDoGroupedInSequence;
|
||||||
private boolean ignoreRecordsUntilGroupBeatenOnce;
|
private boolean ignoreRecordsUntilGroupBeatenOnce;
|
||||||
private Set<Material> killPlaneBlocks;
|
private Set<Material> killPlaneBlocks;
|
||||||
|
private Set<Material> obstacleBlocks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new dropper configuration
|
* Instantiates a new dropper configuration
|
||||||
@ -63,12 +64,22 @@ public class ParkourConfiguration extends MiniGameConfiguration {
|
|||||||
return new HashSet<>(this.killPlaneBlocks);
|
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
|
@Override
|
||||||
protected void load() {
|
protected void load() {
|
||||||
this.enforceCheckpointOrder = configuration.getBoolean(rootNode + "enforceCheckpointOrder", false);
|
this.enforceCheckpointOrder = configuration.getBoolean(rootNode + "enforceCheckpointOrder", false);
|
||||||
this.mustDoGroupedInSequence = configuration.getBoolean(rootNode + "mustDoGroupedInSequence", true);
|
this.mustDoGroupedInSequence = configuration.getBoolean(rootNode + "mustDoGroupedInSequence", true);
|
||||||
this.ignoreRecordsUntilGroupBeatenOnce = configuration.getBoolean(rootNode + "ignoreRecordsUntilGroupBeatenOnce", false);
|
this.ignoreRecordsUntilGroupBeatenOnce = configuration.getBoolean(rootNode + "ignoreRecordsUntilGroupBeatenOnce", false);
|
||||||
this.killPlaneBlocks = loadMaterialList(rootNode + "killPlaneBlocks");
|
this.killPlaneBlocks = loadMaterialList(rootNode + "killPlaneBlocks");
|
||||||
|
this.obstacleBlocks = loadMaterialList(rootNode + "obstacleBlocks");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -82,6 +93,10 @@ public class ParkourConfiguration extends MiniGameConfiguration {
|
|||||||
for (Material material : killPlaneBlocks) {
|
for (Material material : killPlaneBlocks) {
|
||||||
builder.append("\n - ").append(material.name());
|
builder.append("\n - ").append(material.name());
|
||||||
}
|
}
|
||||||
|
builder.append("\n" + "Obstacle blocks: ");
|
||||||
|
for (Material material : obstacleBlocks) {
|
||||||
|
builder.append("\n - ").append(material.name());
|
||||||
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,14 +4,20 @@ import net.knarcraft.knargui.AbstractGUI;
|
|||||||
import net.knarcraft.knargui.GUIAction;
|
import net.knarcraft.knargui.GUIAction;
|
||||||
import net.knarcraft.knargui.item.GUIItemFactory;
|
import net.knarcraft.knargui.item.GUIItemFactory;
|
||||||
import net.knarcraft.knargui.item.PlayerHeadGUIItemFactory;
|
import net.knarcraft.knargui.item.PlayerHeadGUIItemFactory;
|
||||||
|
import net.knarcraft.knargui.item.SimpleGUIItemFactory;
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.ArenaPlayerRegistry;
|
import net.knarcraft.minigames.arena.ArenaPlayerRegistry;
|
||||||
import net.knarcraft.minigames.arena.ArenaSession;
|
import net.knarcraft.minigames.arena.ArenaSession;
|
||||||
import net.knarcraft.minigames.arena.PlayerVisibilityManager;
|
import net.knarcraft.minigames.arena.PlayerVisibilityManager;
|
||||||
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaSession;
|
||||||
|
import net.knarcraft.minigames.util.GeyserHelper;
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.inventory.ClickType;
|
import org.bukkit.event.inventory.ClickType;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -27,23 +33,46 @@ public abstract class ArenaGUI extends AbstractGUI {
|
|||||||
* @param inventorySize <p>The size of the GUI's inventory</p>
|
* @param inventorySize <p>The size of the GUI's inventory</p>
|
||||||
* @param inventoryName <p>The name of the inventory</p>
|
* @param inventoryName <p>The name of the inventory</p>
|
||||||
*/
|
*/
|
||||||
public ArenaGUI(int inventorySize, String inventoryName) {
|
public ArenaGUI(int inventorySize, @NotNull String inventoryName) {
|
||||||
super(inventorySize, inventoryName, null);
|
super(inventorySize, inventoryName, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an item describing a retry arena action
|
* Gets an item describing a retry arena action (for Java edition)
|
||||||
*
|
*
|
||||||
* @return <p>An arena restart item</p>
|
* @return <p>An arena restart item</p>
|
||||||
*/
|
*/
|
||||||
protected ItemStack getRestartItem() {
|
@NotNull
|
||||||
|
protected ItemStack getRestartItemJava() {
|
||||||
PlayerHeadGUIItemFactory restartItemFactory = new PlayerHeadGUIItemFactory();
|
PlayerHeadGUIItemFactory restartItemFactory = new PlayerHeadGUIItemFactory();
|
||||||
restartItemFactory.useSkin("e23b225ed0443c4eec7cf30a034490485904e6eb3d53ef2ab9e39c73bdf22c30");
|
restartItemFactory.useSkin("e23b225ed0443c4eec7cf30a034490485904e6eb3d53ef2ab9e39c73bdf22c30");
|
||||||
|
return setRestartItemData(restartItemFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an item describing a retry arena action (for Bedrock edition)
|
||||||
|
*
|
||||||
|
* @return <p>An arena restart item</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
protected ItemStack getRestartItemBedrock() {
|
||||||
|
return setRestartItemData(new SimpleGUIItemFactory(Material.MAGENTA_GLAZED_TERRACOTTA));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the lore and name for a retry item, and returns the finished item
|
||||||
|
*
|
||||||
|
* @param guiItemFactory <p>The factory to apply the data to</p>
|
||||||
|
* @return <p>The finished item, with the data applied</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
protected ItemStack setRestartItemData(@NotNull GUIItemFactory guiItemFactory) {
|
||||||
List<String> loreLines = getLoreLines();
|
List<String> loreLines = getLoreLines();
|
||||||
loreLines.add(ChatColor.GRAY + "Use this item to retry the arena");
|
loreLines.add(ChatColor.GRAY + "Use this item to retry the arena");
|
||||||
restartItemFactory.setName(ChatColor.BLUE + "Retry arena");
|
loreLines.add(ChatColor.GRAY + "(deaths and time is reset to 0)");
|
||||||
restartItemFactory.setLore(loreLines);
|
guiItemFactory.setName(ChatColor.BLUE + "Retry arena");
|
||||||
return restartItemFactory.build();
|
guiItemFactory.setLore(loreLines);
|
||||||
|
return guiItemFactory.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,8 +80,9 @@ public abstract class ArenaGUI extends AbstractGUI {
|
|||||||
*
|
*
|
||||||
* @return <p>A player toggle item</p>
|
* @return <p>A player toggle item</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
protected ItemStack getTogglePlayersItemDisabled() {
|
protected ItemStack getTogglePlayersItemDisabled() {
|
||||||
GUIItemFactory togglePlayersItemFactory = new GUIItemFactory(Material.PLAYER_HEAD);
|
GUIItemFactory togglePlayersItemFactory = new SimpleGUIItemFactory(Material.PLAYER_HEAD);
|
||||||
List<String> loreLines = getLoreLines();
|
List<String> loreLines = getLoreLines();
|
||||||
loreLines.add(ChatColor.GRAY + "Use this item to disable the visibility");
|
loreLines.add(ChatColor.GRAY + "Use this item to disable the visibility");
|
||||||
loreLines.add(ChatColor.GRAY + "of other players");
|
loreLines.add(ChatColor.GRAY + "of other players");
|
||||||
@ -64,27 +94,80 @@ public abstract class ArenaGUI extends AbstractGUI {
|
|||||||
/**
|
/**
|
||||||
* Gets an item describing player visibility toggling
|
* Gets an item describing player visibility toggling
|
||||||
*
|
*
|
||||||
|
* @param player <p>The player to get the item for</p>
|
||||||
* @return <p>A player toggle item</p>
|
* @return <p>A player toggle item</p>
|
||||||
*/
|
*/
|
||||||
protected ItemStack getTogglePlayersItemEnabled() {
|
@NotNull
|
||||||
|
protected ItemStack getTogglePlayersItemEnabled(@NotNull Player player) {
|
||||||
|
if (GeyserHelper.isGeyserPlayer(player)) {
|
||||||
|
return getTogglePlayersItemEnabledBedrock();
|
||||||
|
} else {
|
||||||
|
return getTogglePlayersItemEnabledJava();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an item describing player visibility toggling
|
||||||
|
*
|
||||||
|
* @return <p>A player toggle item</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
protected ItemStack getTogglePlayersItemEnabledJava() {
|
||||||
PlayerHeadGUIItemFactory togglePlayersItemFactory = new PlayerHeadGUIItemFactory();
|
PlayerHeadGUIItemFactory togglePlayersItemFactory = new PlayerHeadGUIItemFactory();
|
||||||
togglePlayersItemFactory.useSkin("c10591e6909e6a281b371836e462d67a2c78fa0952e910f32b41a26c48c1757c");
|
togglePlayersItemFactory.useSkin("c10591e6909e6a281b371836e462d67a2c78fa0952e910f32b41a26c48c1757c");
|
||||||
|
return setTogglePlayersItemData(togglePlayersItemFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an item describing player visibility toggling
|
||||||
|
*
|
||||||
|
* @return <p>A player toggle item</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
protected ItemStack getTogglePlayersItemEnabledBedrock() {
|
||||||
|
return setTogglePlayersItemData(new SimpleGUIItemFactory(Material.SKELETON_SKULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the lore and name for a toggle players item, and returns the finished item
|
||||||
|
*
|
||||||
|
* @param itemFactory <p>The factory to apply the data to</p>
|
||||||
|
* @return <p>The finished item, with the data applied</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
protected ItemStack setTogglePlayersItemData(@NotNull GUIItemFactory itemFactory) {
|
||||||
List<String> loreLines = getLoreLines();
|
List<String> loreLines = getLoreLines();
|
||||||
loreLines.add(ChatColor.GRAY + "Use this item to enable the visibility");
|
loreLines.add(ChatColor.GRAY + "Use this item to enable the visibility");
|
||||||
loreLines.add(ChatColor.GRAY + "of other players");
|
loreLines.add(ChatColor.GRAY + "of other players");
|
||||||
togglePlayersItemFactory.setName(ChatColor.BLUE + "Enable Players");
|
itemFactory.setName(ChatColor.BLUE + "Enable Players");
|
||||||
togglePlayersItemFactory.setLore(loreLines);
|
itemFactory.setLore(loreLines);
|
||||||
return togglePlayersItemFactory.build();
|
return itemFactory.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an item describing a give up action
|
||||||
|
*
|
||||||
|
* @return <p>A give up item</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
protected ItemStack getGiveUpItem() {
|
||||||
|
GUIItemFactory giveUpItemFactory = new SimpleGUIItemFactory(Material.RESPAWN_ANCHOR);
|
||||||
|
List<String> loreLines = getLoreLines();
|
||||||
|
loreLines.add(ChatColor.GRAY + "Use this item to give up and");
|
||||||
|
loreLines.add(ChatColor.GRAY + "go to your current checkpoint");
|
||||||
|
giveUpItemFactory.setName(ChatColor.RED + "Give up");
|
||||||
|
giveUpItemFactory.setLore(loreLines);
|
||||||
|
return giveUpItemFactory.build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an item describing a leave arena action
|
* Gets an item describing a leave arena action
|
||||||
*
|
*
|
||||||
* @return <p>A leave item</p>
|
* @return <p>A leave item</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
protected ItemStack getLeaveItem() {
|
protected ItemStack getLeaveItem() {
|
||||||
GUIItemFactory leaveItemFactory = new GUIItemFactory(Material.BARRIER);
|
GUIItemFactory leaveItemFactory = new SimpleGUIItemFactory(Material.BARRIER);
|
||||||
List<String> loreLines = getLoreLines();
|
List<String> loreLines = getLoreLines();
|
||||||
loreLines.add(ChatColor.GRAY + "Use this item to leave the arena");
|
loreLines.add(ChatColor.GRAY + "Use this item to leave the arena");
|
||||||
leaveItemFactory.setName(ChatColor.DARK_RED + "Leave");
|
leaveItemFactory.setName(ChatColor.DARK_RED + "Leave");
|
||||||
@ -97,6 +180,7 @@ public abstract class ArenaGUI extends AbstractGUI {
|
|||||||
*
|
*
|
||||||
* @return <p>An arraylist with one blank line</p>
|
* @return <p>An arraylist with one blank line</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
protected List<String> getLoreLines() {
|
protected List<String> getLoreLines() {
|
||||||
List<String> loreLines = new ArrayList<>();
|
List<String> loreLines = new ArrayList<>();
|
||||||
loreLines.add("");
|
loreLines.add("");
|
||||||
@ -109,7 +193,7 @@ public abstract class ArenaGUI extends AbstractGUI {
|
|||||||
* @param inventorySlot <p>The inventory slot the action should be added to</p>
|
* @param inventorySlot <p>The inventory slot the action should be added to</p>
|
||||||
* @param action <p>The action to register</p>
|
* @param action <p>The action to register</p>
|
||||||
*/
|
*/
|
||||||
protected void setAnyClickAction(int inventorySlot, GUIAction action) {
|
protected void setAnyClickAction(int inventorySlot, @NotNull GUIAction action) {
|
||||||
setClickAction(inventorySlot, ClickType.LEFT, action);
|
setClickAction(inventorySlot, ClickType.LEFT, action);
|
||||||
setClickAction(inventorySlot, ClickType.RIGHT, action);
|
setClickAction(inventorySlot, ClickType.RIGHT, action);
|
||||||
}
|
}
|
||||||
@ -119,6 +203,7 @@ public abstract class ArenaGUI extends AbstractGUI {
|
|||||||
*
|
*
|
||||||
* @return <p>The leave action</p>
|
* @return <p>The leave action</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
public static GUIAction getLeaveAction() {
|
public static GUIAction getLeaveAction() {
|
||||||
return (player) -> {
|
return (player) -> {
|
||||||
ArenaSession session = MiniGames.getInstance().getSession(player.getUniqueId());
|
ArenaSession session = MiniGames.getInstance().getSession(player.getUniqueId());
|
||||||
@ -133,6 +218,7 @@ public abstract class ArenaGUI extends AbstractGUI {
|
|||||||
*
|
*
|
||||||
* @return <p>The action for triggering a session restart</p>
|
* @return <p>The action for triggering a session restart</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
public static GUIAction getRestartAction() {
|
public static GUIAction getRestartAction() {
|
||||||
return (player -> {
|
return (player -> {
|
||||||
ArenaSession session = MiniGames.getInstance().getSession(player.getUniqueId());
|
ArenaSession session = MiniGames.getInstance().getSession(player.getUniqueId());
|
||||||
@ -146,16 +232,33 @@ public abstract class ArenaGUI extends AbstractGUI {
|
|||||||
* Gets the action to run when triggering the toggle players action
|
* Gets the action to run when triggering the toggle players action
|
||||||
*
|
*
|
||||||
* @param playerRegistry <p>The registry containing relevant players</p>
|
* @param playerRegistry <p>The registry containing relevant players</p>
|
||||||
|
* @param inventorySlot <p>The inventory slot to replace when toggling</p>
|
||||||
* @return <p>The action for triggering player visibility</p>
|
* @return <p>The action for triggering player visibility</p>
|
||||||
*/
|
*/
|
||||||
public GUIAction getTogglePlayersAction(ArenaPlayerRegistry<?> playerRegistry) {
|
@NotNull
|
||||||
|
public GUIAction getTogglePlayersAction(@Nullable ArenaPlayerRegistry<?> playerRegistry, int inventorySlot) {
|
||||||
return (player) -> {
|
return (player) -> {
|
||||||
PlayerVisibilityManager visibilityManager = MiniGames.getInstance().getPlayerVisibilityManager();
|
PlayerVisibilityManager visibilityManager = MiniGames.getInstance().getPlayerVisibilityManager();
|
||||||
visibilityManager.toggleHidePlayers(playerRegistry, player);
|
visibilityManager.toggleHidePlayers(playerRegistry, player);
|
||||||
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
||||||
setItem(0, getTogglePlayersItemEnabled());
|
setItem(inventorySlot, getTogglePlayersItemEnabled(player));
|
||||||
} else {
|
} else {
|
||||||
setItem(0, getTogglePlayersItemDisabled());
|
setItem(inventorySlot, getTogglePlayersItemDisabled());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the action to run when triggering the give up item
|
||||||
|
*
|
||||||
|
* @return <p>The give up action</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static GUIAction getGiveUpAction() {
|
||||||
|
return (player) -> {
|
||||||
|
ArenaSession session = MiniGames.getInstance().getSession(player.getUniqueId());
|
||||||
|
if (session instanceof ParkourArenaSession) {
|
||||||
|
session.triggerLoss();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,14 @@ public class DropperGUI extends ArenaGUI {
|
|||||||
public DropperGUI(Player player) {
|
public DropperGUI(Player player) {
|
||||||
super(9, "Dropper");
|
super(9, "Dropper");
|
||||||
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
||||||
setItem(0, getTogglePlayersItemEnabled());
|
setItem(0, getTogglePlayersItemEnabled(player));
|
||||||
} else {
|
} else {
|
||||||
setItem(0, getTogglePlayersItemDisabled());
|
setItem(0, getTogglePlayersItemDisabled());
|
||||||
}
|
}
|
||||||
setItem(2, getLeaveItem());
|
setItem(2, getLeaveItem());
|
||||||
setItem(4, getRestartItem());
|
setItem(4, getRestartItemJava());
|
||||||
|
|
||||||
setAnyClickAction(0, getTogglePlayersAction(MiniGames.getInstance().getDropperArenaPlayerRegistry()));
|
setAnyClickAction(0, getTogglePlayersAction(MiniGames.getInstance().getDropperArenaPlayerRegistry(), 0));
|
||||||
setAnyClickAction(2, getLeaveAction());
|
setAnyClickAction(2, getLeaveAction());
|
||||||
setAnyClickAction(4, getRestartAction());
|
setAnyClickAction(4, getRestartAction());
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package net.knarcraft.minigames.gui;
|
||||||
|
|
||||||
|
import net.knarcraft.minigames.MiniGames;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GUI used in the dropper arena, altered for Bedrock players
|
||||||
|
*/
|
||||||
|
public class DropperGUIBedrock extends ArenaGUI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new dropper gui
|
||||||
|
*
|
||||||
|
* @param player <p>The player the GUI is created for</p>
|
||||||
|
*/
|
||||||
|
public DropperGUIBedrock(Player player) {
|
||||||
|
super(27, "Dropper");
|
||||||
|
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
||||||
|
setItem(10, getTogglePlayersItemEnabledBedrock());
|
||||||
|
} else {
|
||||||
|
setItem(10, getTogglePlayersItemDisabled());
|
||||||
|
}
|
||||||
|
setItem(12, getLeaveItem());
|
||||||
|
setItem(14, getRestartItemBedrock());
|
||||||
|
|
||||||
|
setAnyClickAction(10, getTogglePlayersAction(MiniGames.getInstance().getDropperArenaPlayerRegistry(), 10));
|
||||||
|
setAnyClickAction(12, getLeaveAction());
|
||||||
|
setAnyClickAction(14, getRestartAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,12 +16,12 @@ public class MiniGamesGUI extends ArenaGUI {
|
|||||||
public MiniGamesGUI(Player player) {
|
public MiniGamesGUI(Player player) {
|
||||||
super(9, "MiniGames");
|
super(9, "MiniGames");
|
||||||
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
||||||
setItem(0, getTogglePlayersItemEnabled());
|
setItem(0, getTogglePlayersItemEnabled(player));
|
||||||
} else {
|
} else {
|
||||||
setItem(0, getTogglePlayersItemDisabled());
|
setItem(0, getTogglePlayersItemDisabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
setAnyClickAction(0, getTogglePlayersAction(null));
|
setAnyClickAction(0, getTogglePlayersAction(null, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,7 @@
|
|||||||
package net.knarcraft.minigames.gui;
|
package net.knarcraft.minigames.gui;
|
||||||
|
|
||||||
import net.knarcraft.knargui.GUIAction;
|
|
||||||
import net.knarcraft.knargui.item.GUIItemFactory;
|
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.ArenaSession;
|
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArenaSession;
|
|
||||||
import net.md_5.bungee.api.ChatColor;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A GUI used in the parkour arena
|
* A GUI used in the parkour arena
|
||||||
@ -25,47 +16,18 @@ public class ParkourGUI extends ArenaGUI {
|
|||||||
public ParkourGUI(Player player) {
|
public ParkourGUI(Player player) {
|
||||||
super(9, "Parkour");
|
super(9, "Parkour");
|
||||||
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
||||||
setItem(0, getTogglePlayersItemEnabled());
|
setItem(1, getTogglePlayersItemEnabled(player));
|
||||||
} else {
|
} else {
|
||||||
setItem(0, getTogglePlayersItemDisabled());
|
setItem(1, getTogglePlayersItemDisabled());
|
||||||
}
|
}
|
||||||
setItem(2, getGiveUpItem());
|
setItem(3, getGiveUpItem());
|
||||||
setItem(4, getLeaveItem());
|
setItem(5, getLeaveItem());
|
||||||
setItem(6, getRestartItem());
|
setItem(7, getRestartItemJava());
|
||||||
|
|
||||||
setAnyClickAction(0, getTogglePlayersAction(MiniGames.getInstance().getParkourArenaPlayerRegistry()));
|
setAnyClickAction(1, getTogglePlayersAction(MiniGames.getInstance().getParkourArenaPlayerRegistry(), 1));
|
||||||
setAnyClickAction(2, getGiveUpAction());
|
setAnyClickAction(3, getGiveUpAction());
|
||||||
setAnyClickAction(4, getLeaveAction());
|
setAnyClickAction(5, getLeaveAction());
|
||||||
setAnyClickAction(6, getRestartAction());
|
setAnyClickAction(7, getRestartAction());
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an item describing a give up action
|
|
||||||
*
|
|
||||||
* @return <p>A give up item</p>
|
|
||||||
*/
|
|
||||||
private ItemStack getGiveUpItem() {
|
|
||||||
GUIItemFactory giveUpItemFactory = new GUIItemFactory(Material.RESPAWN_ANCHOR);
|
|
||||||
List<String> loreLines = getLoreLines();
|
|
||||||
loreLines.add(ChatColor.GRAY + "Use this item to give up");
|
|
||||||
loreLines.add(ChatColor.GRAY + "and go to the last checkpoint");
|
|
||||||
giveUpItemFactory.setName(ChatColor.RED + "Give up");
|
|
||||||
giveUpItemFactory.setLore(loreLines);
|
|
||||||
return giveUpItemFactory.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the action to run when triggering the give up item
|
|
||||||
*
|
|
||||||
* @return <p>The give up action</p>
|
|
||||||
*/
|
|
||||||
public static GUIAction getGiveUpAction() {
|
|
||||||
return (player) -> {
|
|
||||||
ArenaSession session = MiniGames.getInstance().getSession(player.getUniqueId());
|
|
||||||
if (session instanceof ParkourArenaSession) {
|
|
||||||
session.triggerLoss();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package net.knarcraft.minigames.gui;
|
||||||
|
|
||||||
|
import net.knarcraft.minigames.MiniGames;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GUI used in the parkour arena, altered for Bedrock players
|
||||||
|
*/
|
||||||
|
public class ParkourGUIBedrock extends ArenaGUI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new parkour gui
|
||||||
|
*
|
||||||
|
* @param player <p>The player the GUI is created for</p>
|
||||||
|
*/
|
||||||
|
public ParkourGUIBedrock(Player player) {
|
||||||
|
super(27, "Parkour");
|
||||||
|
if (MiniGames.getInstance().getPlayerVisibilityManager().isHidingPlayers(player)) {
|
||||||
|
setItem(10, getTogglePlayersItemEnabled(player));
|
||||||
|
} else {
|
||||||
|
setItem(10, getTogglePlayersItemDisabled());
|
||||||
|
}
|
||||||
|
setItem(12, getGiveUpItem());
|
||||||
|
setItem(14, getLeaveItem());
|
||||||
|
setItem(16, getRestartItemBedrock());
|
||||||
|
|
||||||
|
setAnyClickAction(10, getTogglePlayersAction(MiniGames.getInstance().getParkourArenaPlayerRegistry(), 10));
|
||||||
|
setAnyClickAction(12, getGiveUpAction());
|
||||||
|
setAnyClickAction(14, getLeaveAction());
|
||||||
|
setAnyClickAction(16, getRestartAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,8 +1,12 @@
|
|||||||
package net.knarcraft.minigames.listener;
|
package net.knarcraft.minigames.listener;
|
||||||
|
|
||||||
|
import net.knarcraft.knarlib.lib.annotations.NotNull;
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.ArenaSession;
|
import net.knarcraft.minigames.arena.ArenaSession;
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArenaSession;
|
import net.knarcraft.minigames.arena.dropper.DropperArenaSession;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.attribute.Attribute;
|
||||||
|
import org.bukkit.attribute.AttributeInstance;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@ -16,7 +20,7 @@ import org.bukkit.event.entity.EntityDamageEvent;
|
|||||||
public class DamageListener implements Listener {
|
public class DamageListener implements Listener {
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerDamage(EntityDamageEvent event) {
|
public void onPlayerDamage(@NotNull EntityDamageEvent event) {
|
||||||
// Only player damage matters
|
// Only player damage matters
|
||||||
if (event.getEntityType() != EntityType.PLAYER) {
|
if (event.getEntityType() != EntityType.PLAYER) {
|
||||||
return;
|
return;
|
||||||
@ -32,14 +36,52 @@ public class DamageListener implements Listener {
|
|||||||
|
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
|
||||||
// Only trigger a loss when a player suffers fall damage in a dropper arena
|
// Only trigger a loss when a player suffers fall damage in a dropper arena (This cannot be cancelled!)
|
||||||
if (arenaSession instanceof DropperArenaSession && event.getCause() == EntityDamageEvent.DamageCause.FALL) {
|
if (arenaSession instanceof DropperArenaSession && event.getCause() == EntityDamageEvent.DamageCause.FALL) {
|
||||||
arenaSession.triggerLoss();
|
arenaSession.triggerLoss();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If set as allowed damage, do nothing, except if the damage is fatal
|
||||||
|
if (arenaSession.getArena().getAllowedDamageCauses().contains(event.getCause())) {
|
||||||
|
applyFakeDamage(player, event.getDamage(), arenaSession);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If set as trigger loss, trigger a loss
|
||||||
|
if (arenaSession.getArena().getLossTriggerDamageCauses().contains(event.getCause())) {
|
||||||
|
arenaSession.triggerLoss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fakes the damaging of a player
|
||||||
|
*
|
||||||
|
* @param player <p>The player to damage</p>
|
||||||
|
* @param damage <p>The raw damage to apply</p>
|
||||||
|
* @param arenaSession <p>The arena session to trigger a loss for, if the player reaches 0 damage</p>
|
||||||
|
*/
|
||||||
|
private void applyFakeDamage(@NotNull Player player, double damage, @NotNull ArenaSession arenaSession) {
|
||||||
|
if (player.getNoDamageTicks() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double newHealth = player.getHealth() - damage;
|
||||||
|
player.sendHurtAnimation(180);
|
||||||
|
if (newHealth <= 0) {
|
||||||
|
AttributeInstance health = player.getAttribute(Attribute.MAX_HEALTH);
|
||||||
|
if (health != null) {
|
||||||
|
player.setHealth(health.getValue());
|
||||||
|
}
|
||||||
|
arenaSession.triggerLoss();
|
||||||
|
} else {
|
||||||
|
player.setHealth(newHealth);
|
||||||
|
player.setNoDamageTicks(10);
|
||||||
|
player.playSound(player, Sound.ENTITY_PLAYER_HURT, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onPlayerCombustion(EntityCombustEvent event) {
|
public void onPlayerCombustion(@NotNull EntityCombustEvent event) {
|
||||||
if (event.getEntityType() != EntityType.PLAYER) {
|
if (event.getEntityType() != EntityType.PLAYER) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,25 @@
|
|||||||
package net.knarcraft.minigames.listener;
|
package net.knarcraft.minigames.listener;
|
||||||
|
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
|
import net.knarcraft.minigames.arena.ArenaPlayerRegistry;
|
||||||
|
import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
||||||
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaSession;
|
||||||
import net.knarcraft.minigames.gui.ArenaGUI;
|
import net.knarcraft.minigames.gui.ArenaGUI;
|
||||||
import net.knarcraft.minigames.gui.ParkourGUI;
|
import net.knarcraft.minigames.gui.ParkourGUI;
|
||||||
import net.knarcraft.minigames.property.PersistentDataKey;
|
import net.knarcraft.minigames.property.PersistentDataKey;
|
||||||
import net.knarcraft.minigames.util.GUIHelper;
|
import net.knarcraft.minigames.util.GUIHelper;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.type.Switch;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A listener that listens for player interactions
|
* A listener that listens for player interactions
|
||||||
@ -19,7 +27,26 @@ import org.bukkit.persistence.PersistentDataType;
|
|||||||
public class InteractListener implements Listener {
|
public class InteractListener implements Listener {
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void menuInteractListener(PlayerInteractEvent event) {
|
public void menuInteractListener(@NotNull PlayerInteractEvent event) {
|
||||||
|
handleMenuClick(event);
|
||||||
|
|
||||||
|
Block clicked = event.getClickedBlock();
|
||||||
|
if (event.useInteractedBlock() != Event.Result.DENY && event.getAction() == Action.RIGHT_CLICK_BLOCK &&
|
||||||
|
clicked != null && clicked.getBlockData() instanceof Switch) {
|
||||||
|
ArenaPlayerRegistry<ParkourArena> playerRegistry = MiniGames.getInstance().getParkourArenaPlayerRegistry();
|
||||||
|
ParkourArenaSession arenaSession = (ParkourArenaSession) playerRegistry.getArenaSession(event.getPlayer().getUniqueId());
|
||||||
|
if (arenaSession != null) {
|
||||||
|
arenaSession.registerChangedLever(clicked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles clicking of the menu item
|
||||||
|
*
|
||||||
|
* @param event <p>The triggered player interact event</p>
|
||||||
|
*/
|
||||||
|
private void handleMenuClick(@NotNull PlayerInteractEvent event) {
|
||||||
ItemStack item = event.getItem();
|
ItemStack item = event.getItem();
|
||||||
if (item == null || !item.hasItemMeta()) {
|
if (item == null || !item.hasItemMeta()) {
|
||||||
return;
|
return;
|
||||||
@ -33,7 +60,8 @@ public class InteractListener implements Listener {
|
|||||||
PersistentDataKey.MENU_ITEM.getKeyName()), PersistentDataType.INTEGER);
|
PersistentDataKey.MENU_ITEM.getKeyName()), PersistentDataType.INTEGER);
|
||||||
|
|
||||||
if (persistentData != null && persistentData == PersistentDataKey.MENU_ITEM.getDataValue()) {
|
if (persistentData != null && persistentData == PersistentDataKey.MENU_ITEM.getDataValue()) {
|
||||||
event.setCancelled(true);
|
event.setUseItemInHand(Event.Result.DENY);
|
||||||
|
event.setUseInteractedBlock(Event.Result.DENY);
|
||||||
GUIHelper.openGUI(event.getPlayer());
|
GUIHelper.openGUI(event.getPlayer());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -41,7 +69,8 @@ public class InteractListener implements Listener {
|
|||||||
persistentData = meta.getPersistentDataContainer().get(new NamespacedKey(MiniGames.getInstance(),
|
persistentData = meta.getPersistentDataContainer().get(new NamespacedKey(MiniGames.getInstance(),
|
||||||
PersistentDataKey.LEAVE_ITEM.getKeyName()), PersistentDataType.INTEGER);
|
PersistentDataKey.LEAVE_ITEM.getKeyName()), PersistentDataType.INTEGER);
|
||||||
if (persistentData != null) {
|
if (persistentData != null) {
|
||||||
event.setCancelled(true);
|
event.setUseItemInHand(Event.Result.DENY);
|
||||||
|
event.setUseInteractedBlock(Event.Result.DENY);
|
||||||
if (persistentData == PersistentDataKey.LEAVE_ITEM.getDataValue()) {
|
if (persistentData == PersistentDataKey.LEAVE_ITEM.getDataValue()) {
|
||||||
ArenaGUI.getLeaveAction().run(event.getPlayer());
|
ArenaGUI.getLeaveAction().run(event.getPlayer());
|
||||||
} else if (persistentData == PersistentDataKey.GIVE_UP_ITEM.getDataValue()) {
|
} else if (persistentData == PersistentDataKey.GIVE_UP_ITEM.getDataValue()) {
|
||||||
|
@ -3,6 +3,7 @@ package net.knarcraft.minigames.listener;
|
|||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.Arena;
|
import net.knarcraft.minigames.arena.Arena;
|
||||||
import net.knarcraft.minigames.arena.ArenaSession;
|
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.DropperArenaGameMode;
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArenaSession;
|
import net.knarcraft.minigames.arena.dropper.DropperArenaSession;
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
||||||
@ -14,11 +15,13 @@ import net.knarcraft.minigames.config.ParkourConfiguration;
|
|||||||
import net.knarcraft.minigames.config.SharedConfiguration;
|
import net.knarcraft.minigames.config.SharedConfiguration;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -26,12 +29,15 @@ import java.util.Calendar;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A listener for players moving inside a dropper arena
|
* A listener for players moving inside a dropper arena
|
||||||
*/
|
*/
|
||||||
public class MoveListener implements Listener {
|
public class MoveListener implements Listener {
|
||||||
|
|
||||||
|
private static final BoundingBox fullBlockBox = new BoundingBox(0, 0, 0, 1, 1, 1);
|
||||||
|
|
||||||
private final DropperConfiguration dropperConfiguration;
|
private final DropperConfiguration dropperConfiguration;
|
||||||
private final ParkourConfiguration parkourConfiguration;
|
private final ParkourConfiguration parkourConfiguration;
|
||||||
|
|
||||||
@ -49,12 +55,15 @@ public class MoveListener implements Listener {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerMove(PlayerMoveEvent event) {
|
public void onPlayerMove(PlayerMoveEvent event) {
|
||||||
// Ignore if no actual movement is happening
|
// Ignore if no actual movement is happening
|
||||||
if (event.getFrom().equals(event.getTo()) || event.getTo() == null) {
|
if (event.getTo() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArenaSession session = MiniGames.getInstance().getSession(event.getPlayer().getUniqueId());
|
ArenaSession session = MiniGames.getInstance().getSession(event.getPlayer().getUniqueId());
|
||||||
if (session instanceof DropperArenaSession dropperSession) {
|
if (session instanceof DropperArenaSession dropperSession) {
|
||||||
|
if (event.getFrom().equals(event.getTo())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
doDropperArenaChecks(event, dropperSession);
|
doDropperArenaChecks(event, dropperSession);
|
||||||
} else if (session instanceof ParkourArenaSession parkourSession) {
|
} else if (session instanceof ParkourArenaSession parkourSession) {
|
||||||
doParkourArenaChecks(event, parkourSession);
|
doParkourArenaChecks(event, parkourSession);
|
||||||
@ -68,8 +77,7 @@ public class MoveListener implements Listener {
|
|||||||
* @param arenaSession <p>The dropper session of the player triggering the event</p>
|
* @param arenaSession <p>The dropper session of the player triggering the event</p>
|
||||||
*/
|
*/
|
||||||
private void doParkourArenaChecks(@NotNull PlayerMoveEvent event, ParkourArenaSession arenaSession) {
|
private void doParkourArenaChecks(@NotNull PlayerMoveEvent event, ParkourArenaSession arenaSession) {
|
||||||
// Ignore movement which won't cause the player's block to change
|
if (event.getTo() == null) {
|
||||||
if (event.getTo() == null || event.getFrom().getBlock() == event.getTo().getBlock()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +102,8 @@ public class MoveListener implements Listener {
|
|||||||
* @param targetBlock <p>The block the player is moving to</p>
|
* @param targetBlock <p>The block the player is moving to</p>
|
||||||
* @param player <p>The player moving</p>
|
* @param player <p>The player moving</p>
|
||||||
*/
|
*/
|
||||||
private void updateCheckpoint(ParkourArenaSession arenaSession, Block targetBlock, Player player) {
|
private void updateCheckpoint(@NotNull ParkourArenaSession arenaSession, @NotNull Block targetBlock,
|
||||||
|
@NotNull Player player) {
|
||||||
ParkourArena arena = arenaSession.getArena();
|
ParkourArena arena = arenaSession.getArena();
|
||||||
List<Location> checkpoints = arena.getCheckpoints();
|
List<Location> checkpoints = arena.getCheckpoints();
|
||||||
for (Location checkpoint : checkpoints) {
|
for (Location checkpoint : checkpoints) {
|
||||||
@ -189,30 +198,199 @@ public class MoveListener implements Listener {
|
|||||||
* @param toLocation <p>The location the player's session is about to hit</p>
|
* @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>
|
* @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();
|
SharedConfiguration sharedConfiguration = MiniGames.getInstance().getSharedConfiguration();
|
||||||
double liquidDepth = sharedConfiguration.getLiquidHitBoxDepth();
|
|
||||||
double solidDepth = sharedConfiguration.getSolidHitBoxDistance();
|
double solidDepth = sharedConfiguration.getSolidHitBoxDistance();
|
||||||
|
double liquidDepth = sharedConfiguration.getLiquidHitBoxDepth();
|
||||||
Arena arena = arenaSession.getArena();
|
Arena arena = arenaSession.getArena();
|
||||||
|
|
||||||
|
|
||||||
|
if (arena instanceof DropperArena) {
|
||||||
|
return checkDropperWin(arenaSession, toLocation, solidDepth, liquidDepth) ||
|
||||||
|
checkDropperDeathBlocks((DropperArenaSession) arenaSession, toLocation, solidDepth, liquidDepth);
|
||||||
|
} else if (arena instanceof ParkourArena) {
|
||||||
|
return checkParkourWin(arenaSession, toLocation.getBlock()) ||
|
||||||
|
checkParkourDeathBlock((ParkourArenaSession) arenaSession, toLocation);
|
||||||
|
} else {
|
||||||
|
MiniGames.log(Level.SEVERE, "Unknown arena type encountered!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the player has triggered a parkour win block
|
||||||
|
*
|
||||||
|
* @param arenaSession <p>The player's current arena session</p>
|
||||||
|
* @param targetBlock <p>The block the player moved to</p>
|
||||||
|
* @return <p>True if the player triggered a parkour win block</p>
|
||||||
|
*/
|
||||||
|
private boolean checkParkourWin(@NotNull ArenaSession arenaSession, @NotNull Block targetBlock) {
|
||||||
|
boolean winBlock = arenaSession.getArena().willCauseWin(targetBlock);
|
||||||
|
if (winBlock) {
|
||||||
|
arenaSession.triggerWin();
|
||||||
|
}
|
||||||
|
return winBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the player has triggered a dropper win block
|
||||||
|
*
|
||||||
|
* @param arenaSession <p>The player's arena session</p>
|
||||||
|
* @param toLocation <p>The location the player moved to</p>
|
||||||
|
* @param solidDepth <p>The distance away from solid blocks that will trigger a hit</p>
|
||||||
|
* @param liquidDepth <p>The depth players need to be inside a liquid to trigger a hit</p>
|
||||||
|
* @return <p>True if the player triggered a dropper win block</p>
|
||||||
|
*/
|
||||||
|
private boolean checkDropperWin(@NotNull ArenaSession arenaSession, @NotNull Location toLocation, double solidDepth,
|
||||||
|
double liquidDepth) {
|
||||||
|
Arena arena = arenaSession.getArena();
|
||||||
|
Set<Block> potentialWinTriggerBlocks;
|
||||||
// For water, only trigger when the player enters the water, but trigger earlier for everything else
|
// For water, only trigger when the player enters the water, but trigger earlier for everything else
|
||||||
double depth = arena.winLocationIsSolid() ? solidDepth : liquidDepth;
|
if (arena.winLocationIsSolid()) {
|
||||||
for (Block block : getBlocksBeneathLocation(toLocation, depth)) {
|
potentialWinTriggerBlocks = getBlocksBeneathLocation(toLocation, solidDepth);
|
||||||
|
} else {
|
||||||
|
potentialWinTriggerBlocks = getBlocksBeneathLocation(toLocation, liquidDepth);
|
||||||
|
}
|
||||||
|
for (Block block : potentialWinTriggerBlocks) {
|
||||||
if (arena.willCauseWin(block)) {
|
if (arena.willCauseWin(block)) {
|
||||||
arenaSession.triggerWin();
|
arenaSession.triggerWin();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a player is moving onto a block part of the dropper arena death plane
|
||||||
|
*
|
||||||
|
* @param arenaSession <p>The player's arena session</p>
|
||||||
|
* @param toLocation <p>The location the player is moving to</p>
|
||||||
|
* @param solidDepth <p>The distance away from solid blocks that will trigger a hit</p>
|
||||||
|
* @param liquidDepth <p>The depth players need to be inside a liquid to trigger a hit</p>
|
||||||
|
* @return <p>True if the player triggered a dropper death block</p>
|
||||||
|
*/
|
||||||
|
private boolean checkDropperDeathBlocks(@NotNull DropperArenaSession arenaSession,
|
||||||
|
@NotNull Location toLocation, double solidDepth, double liquidDepth) {
|
||||||
|
Arena arena = arenaSession.getArena();
|
||||||
|
|
||||||
// Check if the player is about to hit a non-air and non-liquid block
|
// Check if the player is about to hit a non-air and non-liquid block
|
||||||
for (Block block : getBlocksBeneathLocation(toLocation, solidDepth)) {
|
for (Block block : getBlocksBeneathLocation(toLocation, solidDepth)) {
|
||||||
if (!block.getType().isAir() && arena.willCauseLoss(block)) {
|
if (!block.getType().isAir() && !block.isLiquid() && arena.willCauseLoss(block)) {
|
||||||
arenaSession.triggerLoss();
|
arenaSession.triggerLoss();
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the hit-box stricter for liquids beside the player to make lava labyrinths feasible
|
||||||
|
if (block.isLiquid() && player != null && block.getY() > player.getLocation().getBlockY() &&
|
||||||
|
playerBox.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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,12 +401,31 @@ public class MoveListener implements Listener {
|
|||||||
* @return <p>The blocks beneath the player</p>
|
* @return <p>The blocks beneath the player</p>
|
||||||
*/
|
*/
|
||||||
private Set<Block> getBlocksBeneathLocation(Location location, double depth) {
|
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<>();
|
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());
|
||||||
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;
|
return blocksBeneath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
package net.knarcraft.minigames.placeholder;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
import net.knarcraft.minigames.MiniGames;
|
||||||
|
import net.knarcraft.minigames.arena.dropper.DropperArena;
|
||||||
|
import net.knarcraft.minigames.arena.dropper.DropperArenaGameMode;
|
||||||
|
import net.knarcraft.minigames.arena.dropper.DropperArenaHandler;
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
public class DropperExpansion extends PlaceholderExpansion {
|
||||||
|
|
||||||
|
private final @NotNull RecordPlaceholderParser recordPlaceholderParser;
|
||||||
|
private final @NotNull PlayerPlaceholderParser<DropperArena> playerPlaceholderParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new dropper expansion
|
||||||
|
*
|
||||||
|
* @param plugin <p>A reference to the mini-games plugin</p>
|
||||||
|
*/
|
||||||
|
public DropperExpansion(@NotNull MiniGames plugin) {
|
||||||
|
DropperArenaHandler arenaHandler = plugin.getDropperArenaHandler();
|
||||||
|
this.recordPlaceholderParser = new RecordPlaceholderParser(arenaHandler, DropperArenaGameMode::matchGameMode);
|
||||||
|
this.playerPlaceholderParser = new PlayerPlaceholderParser<>(arenaHandler, DropperArenaGameMode::matchGameMode,
|
||||||
|
plugin.getDropperArenaPlayerRegistry());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears record caches
|
||||||
|
*/
|
||||||
|
public void clearCaches() {
|
||||||
|
this.recordPlaceholderParser.clearCaches();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return "dropper";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthor() {
|
||||||
|
return "EpicKnarvik97";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersion() {
|
||||||
|
return "1.0.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean persist() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(parts);
|
||||||
|
} else if (parts[0].equalsIgnoreCase("players")) {
|
||||||
|
return this.playerPlaceholderParser.onRequest(parts);
|
||||||
|
} else {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,32 +0,0 @@
|
|||||||
package net.knarcraft.minigames.placeholder;
|
|
||||||
|
|
||||||
import net.knarcraft.minigames.MiniGames;
|
|
||||||
import net.knarcraft.minigames.arena.ArenaGameMode;
|
|
||||||
import net.knarcraft.minigames.arena.dropper.DropperArenaGameMode;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder expansion for dropper record placeholders
|
|
||||||
*/
|
|
||||||
public class DropperRecordExpansion extends RecordExpansion {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a new record expansion
|
|
||||||
*
|
|
||||||
* @param plugin <p>A reference to the dropper plugin</p>
|
|
||||||
*/
|
|
||||||
public DropperRecordExpansion(MiniGames plugin) {
|
|
||||||
super(plugin.getDropperArenaHandler());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIdentifier() {
|
|
||||||
return "dropper";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @NotNull ArenaGameMode parseGameMode(@NotNull String gameMode) {
|
|
||||||
return DropperArenaGameMode.matchGamemode(gameMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,75 @@
|
|||||||
|
package net.knarcraft.minigames.placeholder;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
import net.knarcraft.minigames.MiniGames;
|
||||||
|
import net.knarcraft.minigames.arena.parkour.ParkourArena;
|
||||||
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaGameMode;
|
||||||
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaHandler;
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
public class ParkourExpansion extends PlaceholderExpansion {
|
||||||
|
|
||||||
|
private final @NotNull RecordPlaceholderParser recordPlaceholderParser;
|
||||||
|
private final @NotNull PlayerPlaceholderParser<ParkourArena> playerPlaceholderParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new dropper expansion
|
||||||
|
*
|
||||||
|
* @param plugin <p>A reference to the mini-games plugin</p>
|
||||||
|
*/
|
||||||
|
public ParkourExpansion(@NotNull MiniGames plugin) {
|
||||||
|
ParkourArenaHandler arenaHandler = plugin.getParkourArenaHandler();
|
||||||
|
this.recordPlaceholderParser = new RecordPlaceholderParser(arenaHandler, ParkourArenaGameMode::matchGameMode);
|
||||||
|
this.playerPlaceholderParser = new PlayerPlaceholderParser<>(arenaHandler, ParkourArenaGameMode::matchGameMode,
|
||||||
|
plugin.getParkourArenaPlayerRegistry());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears record caches
|
||||||
|
*/
|
||||||
|
public void clearCaches() {
|
||||||
|
this.recordPlaceholderParser.clearCaches();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return "parkour";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthor() {
|
||||||
|
return "EpicKnarvik97";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersion() {
|
||||||
|
return "1.0.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean persist() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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(parts);
|
||||||
|
} else if (parts[0].equalsIgnoreCase("players")) {
|
||||||
|
return this.playerPlaceholderParser.onRequest(parts);
|
||||||
|
} else {
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,32 +0,0 @@
|
|||||||
package net.knarcraft.minigames.placeholder;
|
|
||||||
|
|
||||||
import net.knarcraft.minigames.MiniGames;
|
|
||||||
import net.knarcraft.minigames.arena.ArenaGameMode;
|
|
||||||
import net.knarcraft.minigames.arena.parkour.ParkourArenaGameMode;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder expansion for parkour record placeholders
|
|
||||||
*/
|
|
||||||
public class ParkourRecordExpansion extends RecordExpansion {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a new record expansion
|
|
||||||
*
|
|
||||||
* @param plugin <p>A reference to the dropper plugin</p>
|
|
||||||
*/
|
|
||||||
public ParkourRecordExpansion(MiniGames plugin) {
|
|
||||||
super(plugin.getParkourArenaHandler());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getIdentifier() {
|
|
||||||
return "parkour";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @NotNull ArenaGameMode parseGameMode(@NotNull String gameMode) {
|
|
||||||
return ParkourArenaGameMode.matchGamemode(gameMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,37 @@
|
|||||||
|
package net.knarcraft.minigames.placeholder.parsing;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of player information that can be retrieved in placeholders
|
||||||
|
*/
|
||||||
|
public enum PlayerInfoType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of current players
|
||||||
|
*/
|
||||||
|
COUNT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about a single player
|
||||||
|
*/
|
||||||
|
PLAYER,
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the info type specified in the given string
|
||||||
|
*
|
||||||
|
* @param type <p>The string specifying the info type</p>
|
||||||
|
* @return <p>The info type, or null if not found</p>
|
||||||
|
*/
|
||||||
|
public static @Nullable PlayerInfoType getFromString(@NotNull String type) {
|
||||||
|
for (PlayerInfoType infoType : PlayerInfoType.values()) {
|
||||||
|
if (infoType.name().equalsIgnoreCase(type)) {
|
||||||
|
return infoType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,303 @@
|
|||||||
|
package net.knarcraft.minigames.placeholder.parsing;
|
||||||
|
|
||||||
|
import net.knarcraft.minigames.MiniGames;
|
||||||
|
import net.knarcraft.minigames.arena.Arena;
|
||||||
|
import net.knarcraft.minigames.arena.ArenaGameMode;
|
||||||
|
import net.knarcraft.minigames.arena.ArenaGroup;
|
||||||
|
import net.knarcraft.minigames.arena.ArenaHandler;
|
||||||
|
import net.knarcraft.minigames.arena.ArenaPlayerRegistry;
|
||||||
|
import net.knarcraft.minigames.arena.ArenaSession;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parser for player-related placeholders
|
||||||
|
*/
|
||||||
|
public class PlayerPlaceholderParser<K extends Arena> {
|
||||||
|
|
||||||
|
private final @NotNull ArenaHandler<K, ?> arenaHandler;
|
||||||
|
private final @NotNull Function<String, ArenaGameMode> gameModeParser;
|
||||||
|
private final ArenaPlayerRegistry<K> playerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new player placeholder parser
|
||||||
|
*
|
||||||
|
* @param arenaHandler <p>The arena handler to get arenas from</p>
|
||||||
|
* @param gameModeParser <p>The function to use for parsing the specified game-mode</p>
|
||||||
|
* @param playerRegistry <p>The player registry to get player info from</p>
|
||||||
|
*/
|
||||||
|
public PlayerPlaceholderParser(@NotNull ArenaHandler<K, ?> arenaHandler,
|
||||||
|
@NotNull Function<String, ArenaGameMode> gameModeParser,
|
||||||
|
ArenaPlayerRegistry<K> playerRegistry) {
|
||||||
|
this.arenaHandler = arenaHandler;
|
||||||
|
this.gameModeParser = gameModeParser;
|
||||||
|
this.playerRegistry = playerRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method to run when parsing a record placeholder request
|
||||||
|
*
|
||||||
|
* @param parts <p>The split parameters, without irrelevant info</p>
|
||||||
|
* @return <p>The resulting string</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String onRequest(@NotNull String[] parts) {
|
||||||
|
if (parts.length < 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 <p>The split parameters, without irrelevant info</p>
|
||||||
|
* @return <p>The resulting string</p>
|
||||||
|
*/
|
||||||
|
@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 <p>The split parameters, without irrelevant info</p>
|
||||||
|
* @return <p>The resulting string</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private String getPlayingPlayersInfo(@NotNull String[] parts) {
|
||||||
|
String gameModeName = parts[2];
|
||||||
|
ArenaGameMode gameMode = gameModeParser.apply(gameModeName);
|
||||||
|
if (gameModeName.equalsIgnoreCase("combined") || gameModeName.equalsIgnoreCase("all")) {
|
||||||
|
gameMode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectionType selectionType = SelectionType.getFromString(parts[3]);
|
||||||
|
String identifier = parts[4];
|
||||||
|
|
||||||
|
// 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 null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String info = null;
|
||||||
|
if (selectionType == SelectionType.GROUP) {
|
||||||
|
ArenaGroup<?, ?> group = arenaHandler.getGroup(identifier);
|
||||||
|
if (group != null) {
|
||||||
|
info = getGroupInfo(group, gameMode, infoType, parts);
|
||||||
|
}
|
||||||
|
} else if (selectionType == SelectionType.ARENA) {
|
||||||
|
info = getArenaInfo(identifier, gameMode, infoType, parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets information about an arena group's players
|
||||||
|
*
|
||||||
|
* @param group <p>The group to get info about</p>
|
||||||
|
* @param gameMode <p>The game-mode to get information for</p>
|
||||||
|
* @param infoType <p>The type of information to get</p>
|
||||||
|
* @param parts <p>The placeholder arguments specified by a user</p>
|
||||||
|
* @return <p>The specified group info, or null if the placeholder is invalid</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private String getGroupInfo(@NotNull ArenaGroup<?, ?> group, @Nullable ArenaGameMode gameMode,
|
||||||
|
@NotNull PlayerInfoType infoType, @NotNull String[] parts) {
|
||||||
|
List<UUID> arenaIds = group.getArenas();
|
||||||
|
List<K> arenas = new ArrayList<>();
|
||||||
|
for (UUID arenaId : arenaIds) {
|
||||||
|
K arena = arenaHandler.getArena(arenaId);
|
||||||
|
if (arena != null) {
|
||||||
|
arenas.add(arena);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (infoType == PlayerInfoType.COUNT) {
|
||||||
|
int playerCount = 0;
|
||||||
|
for (K arena : arenas) {
|
||||||
|
playerCount += getArenaPlayers(arena, gameMode).size();
|
||||||
|
}
|
||||||
|
return String.valueOf(playerCount);
|
||||||
|
} else if (infoType == PlayerInfoType.PLAYER) {
|
||||||
|
if (parts.length < 7) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Integer playerNumber = getPositionNumber(parts[6]);
|
||||||
|
|
||||||
|
List<String> arenaPlayerNames = new ArrayList<>();
|
||||||
|
for (K arena : arenas) {
|
||||||
|
arenaPlayerNames.addAll(getArenaPlayersSorted(arena, gameMode));
|
||||||
|
}
|
||||||
|
arenaPlayerNames.sort(Comparator.naturalOrder());
|
||||||
|
if (playerNumber != null) {
|
||||||
|
if (playerNumber >= arenaPlayerNames.size()) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return arenaPlayerNames.get(playerNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets information about an arena's players
|
||||||
|
*
|
||||||
|
* @param arenaName <p>The name of the arena</p>
|
||||||
|
* @param gameMode <p>The game-mode to get information for</p>
|
||||||
|
* @param infoType <p>The type of information to get</p>
|
||||||
|
* @param parts <p>The placeholder arguments specified by a user</p>
|
||||||
|
* @return <p>The specified arena info, or null if the placeholder is invalid</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private String getArenaInfo(@NotNull String arenaName, @Nullable ArenaGameMode gameMode,
|
||||||
|
@NotNull PlayerInfoType infoType, @NotNull String[] parts) {
|
||||||
|
if (infoType == PlayerInfoType.COUNT) {
|
||||||
|
Set<UUID> arenaPlayers = getArenaPlayers(arenaName, gameMode);
|
||||||
|
if (arenaPlayers != null) {
|
||||||
|
return String.valueOf(arenaPlayers.size());
|
||||||
|
}
|
||||||
|
} else if (infoType == PlayerInfoType.PLAYER) {
|
||||||
|
if (parts.length < 7) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Integer playerNumber = getPositionNumber(parts[6]);
|
||||||
|
List<String> players = getArenaPlayersSorted(arenaName, gameMode);
|
||||||
|
if (playerNumber != null && players != null) {
|
||||||
|
if (playerNumber >= players.size()) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return players.get(playerNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the position number from the given string
|
||||||
|
*
|
||||||
|
* @param positionNumber <p>The position number to parse</p>
|
||||||
|
* @return <p>The position number, or null if not valid</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private Integer getPositionNumber(@NotNull String positionNumber) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(positionNumber) - 1;
|
||||||
|
} catch (NumberFormatException exception) {
|
||||||
|
MiniGames.log(Level.WARNING, "Invalid placeholder given. " + positionNumber +
|
||||||
|
" supplied instead of player number.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets names of all players in an arena in sorted order
|
||||||
|
*
|
||||||
|
* @param arenaName <p>The name of the arena to get players from</p>
|
||||||
|
* @param arenaGameMode <p>The game-mode to get players for</p>
|
||||||
|
* @return <p>Player names in sorted order, or null if the arena name is invalid</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private List<String> getArenaPlayersSorted(@NotNull String arenaName, @Nullable ArenaGameMode arenaGameMode) {
|
||||||
|
K arena = arenaHandler.getArena(arenaName);
|
||||||
|
if (arena == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getArenaPlayersSorted(arena, arenaGameMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets names of all players in an arena in sorted order
|
||||||
|
*
|
||||||
|
* @param arena <p>The arena to get players from</p>
|
||||||
|
* @param arenaGameMode <p>The game-mode to get players for</p>
|
||||||
|
* @return <p>Player names in sorted order, or null if the arena name is invalid</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private List<String> getArenaPlayersSorted(@NotNull K arena, @Nullable ArenaGameMode arenaGameMode) {
|
||||||
|
Set<UUID> players = getArenaPlayers(arena, arenaGameMode);
|
||||||
|
List<String> playerNames = new ArrayList<>(players.size());
|
||||||
|
for (UUID playerId : players) {
|
||||||
|
Player player = Bukkit.getPlayer(playerId);
|
||||||
|
if (player != null) {
|
||||||
|
playerNames.add(player.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
playerNames.sort(Comparator.naturalOrder());
|
||||||
|
return playerNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all players from the given arena
|
||||||
|
*
|
||||||
|
* @param arenaName <p>The name of the arena to get players from</p>
|
||||||
|
* @param arenaGameMode <p>The game-mode to get players for</p>
|
||||||
|
* @return <p>The players in the given arena playing the given game-mode</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private Set<UUID> getArenaPlayers(@NotNull String arenaName, @Nullable ArenaGameMode arenaGameMode) {
|
||||||
|
K arena = arenaHandler.getArena(arenaName);
|
||||||
|
if (arena == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getArenaPlayers(arena, arenaGameMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all players from the given arena
|
||||||
|
*
|
||||||
|
* @param arena <p>The arena to get players from</p>
|
||||||
|
* @param arenaGameMode <p>The game-mode to get players for</p>
|
||||||
|
* @return <p>The players in the given arena playing the given game-mode</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private Set<UUID> getArenaPlayers(@NotNull K arena, @Nullable ArenaGameMode arenaGameMode) {
|
||||||
|
// If getting count for any game-mode, skip filtering
|
||||||
|
Set<UUID> players = playerRegistry.getPlayingPlayers(arena);
|
||||||
|
if (arenaGameMode == null) {
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<UUID> output = new HashSet<>();
|
||||||
|
for (UUID playerId : players) {
|
||||||
|
ArenaSession arenaSession = playerRegistry.getArenaSession(playerId);
|
||||||
|
if (arenaSession == null || arenaSession.getGameMode() != arenaGameMode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output.add(playerId);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package net.knarcraft.minigames.placeholder;
|
package net.knarcraft.minigames.placeholder.parsing;
|
||||||
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.Arena;
|
import net.knarcraft.minigames.arena.Arena;
|
||||||
import net.knarcraft.minigames.arena.ArenaGameMode;
|
import net.knarcraft.minigames.arena.ArenaGameMode;
|
||||||
@ -8,12 +7,10 @@ import net.knarcraft.minigames.arena.ArenaGroup;
|
|||||||
import net.knarcraft.minigames.arena.ArenaHandler;
|
import net.knarcraft.minigames.arena.ArenaHandler;
|
||||||
import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
|
import net.knarcraft.minigames.arena.ArenaRecordsRegistry;
|
||||||
import net.knarcraft.minigames.arena.record.ArenaRecord;
|
import net.knarcraft.minigames.arena.record.ArenaRecord;
|
||||||
import net.knarcraft.minigames.placeholder.parsing.InfoType;
|
import net.knarcraft.minigames.placeholder.GroupRecordCache;
|
||||||
import net.knarcraft.minigames.placeholder.parsing.SelectionType;
|
|
||||||
import net.knarcraft.minigames.property.RecordType;
|
import net.knarcraft.minigames.property.RecordType;
|
||||||
import net.knarcraft.minigames.util.GroupRecordHelper;
|
import net.knarcraft.minigames.util.GroupRecordHelper;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -23,54 +20,47 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A placeholder expansion for parkour record placeholders
|
* A parser for record-related placeholders
|
||||||
*/
|
*/
|
||||||
public abstract class RecordExpansion extends PlaceholderExpansion {
|
public class RecordPlaceholderParser {
|
||||||
|
|
||||||
private final ArenaHandler<?, ?> arenaHandler;
|
private final @NotNull ArenaHandler<?, ?> arenaHandler;
|
||||||
private final Map<UUID, Set<GroupRecordCache<Integer>>> groupRecordDeathsCache;
|
private final @NotNull Map<UUID, Set<GroupRecordCache<Integer>>> groupRecordDeathsCache;
|
||||||
private final Map<UUID, Set<GroupRecordCache<Long>>> groupRecordTimeCache;
|
private final @NotNull Map<UUID, Set<GroupRecordCache<Long>>> groupRecordTimeCache;
|
||||||
|
private final @NotNull Function<String, ArenaGameMode> gameModeParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new record expansion
|
* Initializes a new record placeholder parser
|
||||||
*/
|
*/
|
||||||
public RecordExpansion(ArenaHandler<?, ?> arenaHandler) {
|
public RecordPlaceholderParser(@NotNull ArenaHandler<?, ?> arenaHandler,
|
||||||
|
@NotNull Function<String, ArenaGameMode> gameModeParser) {
|
||||||
this.groupRecordDeathsCache = new HashMap<>();
|
this.groupRecordDeathsCache = new HashMap<>();
|
||||||
this.groupRecordTimeCache = new HashMap<>();
|
this.groupRecordTimeCache = new HashMap<>();
|
||||||
this.arenaHandler = arenaHandler;
|
this.arenaHandler = arenaHandler;
|
||||||
|
this.gameModeParser = gameModeParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public String getAuthor() {
|
* The method to run when parsing a record placeholder request
|
||||||
return "EpicKnarvik97";
|
*
|
||||||
|
* @param parts <p>All parts of the placeholder</p>
|
||||||
|
* @return <p>The resulting string</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String onRequest(@NotNull String[] parts) {
|
||||||
|
if (parts.length < 7) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getVersion() {
|
|
||||||
return "1.0.0";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean persist() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
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.length < 7 || !parts[0].equals("record")) {
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
RecordType recordType = RecordType.getFromString(parts[1]);
|
RecordType recordType = RecordType.getFromString(parts[1]);
|
||||||
ArenaGameMode gameMode = parseGameMode(parts[2]);
|
ArenaGameMode gameMode = gameModeParser.apply(parts[2]);
|
||||||
SelectionType selectionType = SelectionType.getFromString(parts[3]);
|
SelectionType selectionType = SelectionType.getFromString(parts[3]);
|
||||||
String identifier = parts[4];
|
String identifier = parts[4];
|
||||||
int recordNumber;
|
int recordNumber;
|
||||||
@ -78,13 +68,13 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
recordNumber = Integer.parseInt(parts[5]) - 1;
|
recordNumber = Integer.parseInt(parts[5]) - 1;
|
||||||
} catch (NumberFormatException exception) {
|
} catch (NumberFormatException exception) {
|
||||||
MiniGames.log(Level.WARNING, "Invalid placeholder given. " + parts[5] +
|
MiniGames.log(Level.WARNING, "Invalid placeholder given. " + parts[5] +
|
||||||
" supplied instead of record placement.");
|
" supplied instead of record position.");
|
||||||
return parameters;
|
return null;
|
||||||
}
|
}
|
||||||
InfoType infoType = InfoType.getFromString(parts[6]);
|
InfoType infoType = InfoType.getFromString(parts[6]);
|
||||||
|
|
||||||
if (recordType == null || infoType == null) {
|
if (recordType == null || infoType == null) {
|
||||||
return parameters;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String info = null;
|
String info = null;
|
||||||
@ -94,17 +84,9 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
info = getArenaRecord(arenaHandler, identifier, gameMode, recordType, recordNumber, infoType);
|
info = getArenaRecord(arenaHandler, identifier, gameMode, recordType, recordNumber, infoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Objects.requireNonNullElse(info, parameters);
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the game-mode specified in the given string
|
|
||||||
*
|
|
||||||
* @param gameMode <p>The game-mode to parse</p>
|
|
||||||
* @return <p>The parsed game-mode</p>
|
|
||||||
*/
|
|
||||||
protected abstract @NotNull ArenaGameMode parseGameMode(@NotNull String gameMode);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all record caches
|
* Clears all record caches
|
||||||
*/
|
*/
|
||||||
@ -120,11 +102,12 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
* @param identifier <p>The identifier (name/uuid) selecting the group</p>
|
* @param identifier <p>The identifier (name/uuid) selecting the group</p>
|
||||||
* @param gameMode <p>The game-mode to get a record for</p>
|
* @param gameMode <p>The game-mode to get a record for</p>
|
||||||
* @param recordType <p>The type of record to get</p>
|
* @param recordType <p>The type of record to get</p>
|
||||||
* @param recordNumber <p>The placing of the record to get (1st place, 2nd place, etc.)</p>
|
* @param recordNumber <p>The position of the record to get (1st place, 2nd place, etc.)</p>
|
||||||
* @param infoType <p>The type of info (player, value, combined) to get</p>
|
* @param infoType <p>The type of info (player, value, combined) to get</p>
|
||||||
* @return <p>The selected information about the record, or null if not found</p>
|
* @return <p>The selected information about the record, or null if not found</p>
|
||||||
*/
|
*/
|
||||||
private @Nullable String getGroupRecord(@NotNull ArenaHandler<?, ?> arenaHandler, @NotNull String identifier,
|
@Nullable
|
||||||
|
private String getGroupRecord(@NotNull ArenaHandler<?, ?> arenaHandler, @NotNull String identifier,
|
||||||
@NotNull ArenaGameMode gameMode, @NotNull RecordType recordType,
|
@NotNull ArenaGameMode gameMode, @NotNull RecordType recordType,
|
||||||
int recordNumber, @NotNull InfoType infoType) {
|
int recordNumber, @NotNull InfoType infoType) {
|
||||||
// Allow specifying the group UUID or the arena name
|
// Allow specifying the group UUID or the arena name
|
||||||
@ -158,11 +141,12 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
*
|
*
|
||||||
* @param group <p>The group to get the record from</p>
|
* @param group <p>The group to get the record from</p>
|
||||||
* @param gameMode <p>The game-mode to get the record from</p>
|
* @param gameMode <p>The game-mode to get the record from</p>
|
||||||
* @param recordNumber <p>The placing of the record to get (1st place, 2nd place, etc.)</p>
|
* @param recordNumber <p>The position of the record to get (1st place, 2nd place, etc.)</p>
|
||||||
* @param arenaHandler <p>The handler to get arenas from</p>
|
* @param arenaHandler <p>The handler to get arenas from</p>
|
||||||
* @return <p>The record, or null if not found</p>
|
* @return <p>The record, or null if not found</p>
|
||||||
*/
|
*/
|
||||||
private @Nullable ArenaRecord<?> getGroupTimeRecord(@NotNull ArenaGroup<?, ?> group,
|
@Nullable
|
||||||
|
private ArenaRecord<?> getGroupTimeRecord(@NotNull ArenaGroup<?, ?> group,
|
||||||
@NotNull ArenaGameMode gameMode, int recordNumber,
|
@NotNull ArenaGameMode gameMode, int recordNumber,
|
||||||
@NotNull ArenaHandler<?, ?> arenaHandler) {
|
@NotNull ArenaHandler<?, ?> arenaHandler) {
|
||||||
return getCachedGroupRecord(group, gameMode, RecordType.TIME, recordNumber, groupRecordTimeCache,
|
return getCachedGroupRecord(group, gameMode, RecordType.TIME, recordNumber, groupRecordTimeCache,
|
||||||
@ -174,11 +158,12 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
*
|
*
|
||||||
* @param group <p>The group to get the record from</p>
|
* @param group <p>The group to get the record from</p>
|
||||||
* @param gameMode <p>The game-mode to get the record from</p>
|
* @param gameMode <p>The game-mode to get the record from</p>
|
||||||
* @param recordNumber <p>The placing of the record to get (1st place, 2nd place, etc.)</p>
|
* @param recordNumber <p>The position of the record to get (1st place, 2nd place, etc.)</p>
|
||||||
* @param arenaHandler <p>The handler to get arenas from</p>
|
* @param arenaHandler <p>The handler to get arenas from</p>
|
||||||
* @return <p>The record, or null if not found</p>
|
* @return <p>The record, or null if not found</p>
|
||||||
*/
|
*/
|
||||||
private @Nullable ArenaRecord<?> getGroupDeathRecord(@NotNull ArenaGroup<?, ?> group,
|
@Nullable
|
||||||
|
private ArenaRecord<?> getGroupDeathRecord(@NotNull ArenaGroup<?, ?> group,
|
||||||
@NotNull ArenaGameMode gameMode, int recordNumber,
|
@NotNull ArenaGameMode gameMode, int recordNumber,
|
||||||
@NotNull ArenaHandler<?, ?> arenaHandler) {
|
@NotNull ArenaHandler<?, ?> arenaHandler) {
|
||||||
return getCachedGroupRecord(group, gameMode, RecordType.DEATHS, recordNumber, groupRecordDeathsCache,
|
return getCachedGroupRecord(group, gameMode, RecordType.DEATHS, recordNumber, groupRecordDeathsCache,
|
||||||
@ -191,13 +176,14 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
* @param group <p>The group to get the record for</p>
|
* @param group <p>The group to get the record for</p>
|
||||||
* @param gameMode <p>The game-mode to get the record for</p>
|
* @param gameMode <p>The game-mode to get the record for</p>
|
||||||
* @param recordType <p>The type of record to get</p>
|
* @param recordType <p>The type of record to get</p>
|
||||||
* @param recordNumber <p>The placing of the record to get (1st place, 2nd place, etc.)</p>
|
* @param recordNumber <p>The position of the record to get (1st place, 2nd place, etc.)</p>
|
||||||
* @param caches <p>The caches to use for looking for and saving the record</p>
|
* @param caches <p>The caches to use for looking for and saving the record</p>
|
||||||
* @param recordProvider <p>The provider of records if the cache cannot provide the record</p>
|
* @param recordProvider <p>The provider of records if the cache cannot provide the record</p>
|
||||||
* @param <K> <p>The type of the provided records</p>
|
* @param <K> <p>The type of the provided records</p>
|
||||||
* @return <p>The specified record, or null if not found</p>
|
* @return <p>The specified record, or null if not found</p>
|
||||||
*/
|
*/
|
||||||
private <K extends Comparable<K>> @Nullable ArenaRecord<?> getCachedGroupRecord(@NotNull ArenaGroup<?, ?> group,
|
@Nullable
|
||||||
|
private <K extends Comparable<K>> ArenaRecord<?> getCachedGroupRecord(@NotNull ArenaGroup<?, ?> group,
|
||||||
@NotNull ArenaGameMode gameMode,
|
@NotNull ArenaGameMode gameMode,
|
||||||
@NotNull RecordType recordType,
|
@NotNull RecordType recordType,
|
||||||
int recordNumber,
|
int recordNumber,
|
||||||
@ -240,11 +226,12 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
* @param identifier <p>The identifier (name/uuid) selecting the arena</p>
|
* @param identifier <p>The identifier (name/uuid) selecting the arena</p>
|
||||||
* @param gameMode <p>The game-mode to get a record for</p>
|
* @param gameMode <p>The game-mode to get a record for</p>
|
||||||
* @param recordType <p>The type of record to get</p>
|
* @param recordType <p>The type of record to get</p>
|
||||||
* @param recordNumber <p>The placing of the record to get (1st place, 2nd place, etc.)</p>
|
* @param recordNumber <p>The position of the record to get (1st place, 2nd place, etc.)</p>
|
||||||
* @param infoType <p>The type of info (player, value, combined) to get</p>
|
* @param infoType <p>The type of info (player, value, combined) to get</p>
|
||||||
* @return <p>The selected information about the record, or null if not found</p>
|
* @return <p>The selected information about the record, or null if not found</p>
|
||||||
*/
|
*/
|
||||||
private @Nullable String getArenaRecord(@NotNull ArenaHandler<?, ?> arenaHandler, @NotNull String identifier,
|
@Nullable
|
||||||
|
private String getArenaRecord(@NotNull ArenaHandler<?, ?> arenaHandler, @NotNull String identifier,
|
||||||
@NotNull ArenaGameMode gameMode, @NotNull RecordType recordType,
|
@NotNull ArenaGameMode gameMode, @NotNull RecordType recordType,
|
||||||
int recordNumber, @NotNull InfoType infoType) {
|
int recordNumber, @NotNull InfoType infoType) {
|
||||||
// Allow specifying the arena UUID or the arena name
|
// Allow specifying the arena UUID or the arena name
|
||||||
@ -275,10 +262,11 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
*
|
*
|
||||||
* @param recordsRegistry <p>The records registry to get the record from</p>
|
* @param recordsRegistry <p>The records registry to get the record from</p>
|
||||||
* @param recordType <p>The type of record to get</p>
|
* @param recordType <p>The type of record to get</p>
|
||||||
* @param recordNumber <p>The placing of the record to get (1st place, 2nd place, etc.)</p>
|
* @param recordNumber <p>The position of the record to get (1st place, 2nd place, etc.)</p>
|
||||||
* @return <p>The record, or null if not found</p>
|
* @return <p>The record, or null if not found</p>
|
||||||
*/
|
*/
|
||||||
private @Nullable ArenaRecord<?> getRecord(@NotNull ArenaRecordsRegistry recordsRegistry,
|
@Nullable
|
||||||
|
private ArenaRecord<?> getRecord(@NotNull ArenaRecordsRegistry recordsRegistry,
|
||||||
@NotNull RecordType recordType, int recordNumber) {
|
@NotNull RecordType recordType, int recordNumber) {
|
||||||
return switch (recordType) {
|
return switch (recordType) {
|
||||||
case TIME -> getRecord(new HashSet<>(recordsRegistry.getShortestTimeMilliSecondsRecords()), recordNumber);
|
case TIME -> getRecord(new HashSet<>(recordsRegistry.getShortestTimeMilliSecondsRecords()), recordNumber);
|
||||||
@ -294,7 +282,8 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
* @param <K> <p>The type of record in the record list</p>
|
* @param <K> <p>The type of record in the record list</p>
|
||||||
* @return <p>The record, or null if index is out of bounds</p>
|
* @return <p>The record, or null if index is out of bounds</p>
|
||||||
*/
|
*/
|
||||||
private <K extends Comparable<K>> @Nullable ArenaRecord<K> getRecord(Set<ArenaRecord<K>> records, int index) {
|
@Nullable
|
||||||
|
private <K extends Comparable<K>> ArenaRecord<K> getRecord(@NotNull Set<ArenaRecord<K>> records, int index) {
|
||||||
List<ArenaRecord<K>> sorted = getSortedRecords(records);
|
List<ArenaRecord<K>> sorted = getSortedRecords(records);
|
||||||
if (index < sorted.size() && index >= 0) {
|
if (index < sorted.size() && index >= 0) {
|
||||||
return sorted.get(index);
|
return sorted.get(index);
|
||||||
@ -310,11 +299,12 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
* @param arenaRecord <p>The record to get the data from</p>
|
* @param arenaRecord <p>The record to get the data from</p>
|
||||||
* @return <p>The requested data as a string, or null</p>
|
* @return <p>The requested data as a string, or null</p>
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
private String getRecordData(@NotNull InfoType infoType, @NotNull ArenaRecord<?> arenaRecord) {
|
private String getRecordData(@NotNull InfoType infoType, @NotNull ArenaRecord<?> arenaRecord) {
|
||||||
return switch (infoType) {
|
return switch (infoType) {
|
||||||
case PLAYER -> getPlayerName(arenaRecord.getUserId());
|
case PLAYER -> getPlayerName(arenaRecord.getUserId());
|
||||||
case VALUE -> arenaRecord.getRecord().toString();
|
case VALUE -> arenaRecord.getAsString();
|
||||||
case COMBINED -> getPlayerName(arenaRecord.getUserId()) + ": " + arenaRecord.getRecord().toString();
|
case COMBINED -> getPlayerName(arenaRecord.getUserId()) + ": " + arenaRecord.getAsString();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,8 +315,8 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
* @param <K> <p>The type of the records</p>
|
* @param <K> <p>The type of the records</p>
|
||||||
* @return <p>The sorted records</p>
|
* @return <p>The sorted records</p>
|
||||||
*/
|
*/
|
||||||
private <K extends Comparable<K>> @NotNull List<ArenaRecord<K>> getSortedRecords(
|
@NotNull
|
||||||
@NotNull Set<ArenaRecord<K>> recordSet) {
|
private <K extends Comparable<K>> List<ArenaRecord<K>> getSortedRecords(@NotNull Set<ArenaRecord<K>> recordSet) {
|
||||||
List<ArenaRecord<K>> records = new ArrayList<>(recordSet);
|
List<ArenaRecord<K>> records = new ArrayList<>(recordSet);
|
||||||
Collections.sort(records);
|
Collections.sort(records);
|
||||||
return records;
|
return records;
|
||||||
@ -338,6 +328,7 @@ public abstract class RecordExpansion extends PlaceholderExpansion {
|
|||||||
* @param playerId <p>The id of the player to get the name for</p>
|
* @param playerId <p>The id of the player to get the name for</p>
|
||||||
* @return <p>The name of the player, or a string representation of the UUID if not found</p>
|
* @return <p>The name of the player, or a string representation of the UUID if not found</p>
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
private String getPlayerName(@NotNull UUID playerId) {
|
private String getPlayerName(@NotNull UUID playerId) {
|
||||||
return Bukkit.getOfflinePlayer(playerId).getName();
|
return Bukkit.getOfflinePlayer(playerId).getName();
|
||||||
}
|
}
|
@ -2,8 +2,12 @@ package net.knarcraft.minigames.util;
|
|||||||
|
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.PlayerEntryState;
|
import net.knarcraft.minigames.arena.PlayerEntryState;
|
||||||
|
import net.knarcraft.minigames.arena.StorageKey;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -78,4 +82,40 @@ public final class ArenaStorageHelper {
|
|||||||
return arenaDataFile;
|
return arenaDataFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a set of strings from the given configuration section
|
||||||
|
*
|
||||||
|
* @param configurationSection <p>The configuration section to load from</p>
|
||||||
|
* @param storageKey <p>The key to the info to load</p>
|
||||||
|
* @return <p>The loaded items, or null if not set</p>
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Set<String> loadStrings(@NotNull ConfigurationSection configurationSection,
|
||||||
|
@NotNull StorageKey storageKey) {
|
||||||
|
List<?> rawList = configurationSection.getList(storageKey.getKey());
|
||||||
|
Set<String> output;
|
||||||
|
if (rawList == null) {
|
||||||
|
output = null;
|
||||||
|
} else {
|
||||||
|
output = new HashSet<>((List<String>) rawList);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the names of the given damage causes
|
||||||
|
*
|
||||||
|
* @param causes <p>The damage causes to get names of</p>
|
||||||
|
* @return <p>The names of the damage causes</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static List<String> getDamageCauseNames(@NotNull Set<EntityDamageEvent.DamageCause> causes) {
|
||||||
|
List<String> output = new ArrayList<>(causes.size());
|
||||||
|
for (EntityDamageEvent.DamageCause cause : causes) {
|
||||||
|
output.add(cause.name());
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import org.bukkit.configuration.ConfigurationSection;
|
|||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.yaml.snakeyaml.error.YAMLException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -31,6 +32,7 @@ import java.util.UUID;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import static net.knarcraft.minigames.util.ArenaStorageHelper.getArenaDataFile;
|
import static net.knarcraft.minigames.util.ArenaStorageHelper.getArenaDataFile;
|
||||||
|
import static net.knarcraft.minigames.util.ArenaStorageHelper.loadStrings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class for saving and loading arenas
|
* A helper class for saving and loading arenas
|
||||||
@ -97,6 +99,35 @@ public final class DropperArenaStorageHelper {
|
|||||||
YamlConfiguration configuration = new YamlConfiguration();
|
YamlConfiguration configuration = new YamlConfiguration();
|
||||||
ConfigurationSection arenaSection = configuration.createSection(dropperArenasConfigurationSection);
|
ConfigurationSection arenaSection = configuration.createSection(dropperArenasConfigurationSection);
|
||||||
for (DropperArena arena : arenas.values()) {
|
for (DropperArena arena : arenas.values()) {
|
||||||
|
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
|
//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
|
// must be stored as well
|
||||||
@NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString());
|
@NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString());
|
||||||
@ -107,11 +138,14 @@ public final class DropperArenaStorageHelper {
|
|||||||
configSection.set(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey(), arena.getPlayerVerticalVelocity());
|
configSection.set(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey(), arena.getPlayerVerticalVelocity());
|
||||||
configSection.set(DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey(), arena.getPlayerHorizontalVelocity());
|
configSection.set(DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey(), arena.getPlayerHorizontalVelocity());
|
||||||
configSection.set(DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
|
configSection.set(DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
|
||||||
|
configSection.set(DropperArenaStorageKey.MAX_PLAYERS.getKey(), arena.getMaxPlayers());
|
||||||
|
configSection.set(DropperArenaStorageKey.ALLOWED_DAMAGE_CAUSES.getKey(),
|
||||||
|
ArenaStorageHelper.getDamageCauseNames(arena.getAllowedDamageCauses()));
|
||||||
|
configSection.set(DropperArenaStorageKey.LOSS_TRIGGER_DAMAGE_CAUSES.getKey(),
|
||||||
|
ArenaStorageHelper.getDamageCauseNames(arena.getLossTriggerDamageCauses()));
|
||||||
RewardStorageHelper.saveRewards(arena, configSection, DropperArenaStorageKey.REWARDS.getKey());
|
RewardStorageHelper.saveRewards(arena, configSection, DropperArenaStorageKey.REWARDS.getKey());
|
||||||
saveDropperArenaData(arena.getData());
|
saveDropperArenaData(arena.getData());
|
||||||
}
|
}
|
||||||
configuration.save(dropperArenaFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all arenas
|
* Loads all arenas
|
||||||
@ -159,6 +193,7 @@ public final class DropperArenaStorageHelper {
|
|||||||
double verticalVelocity = configurationSection.getDouble(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey());
|
double verticalVelocity = configurationSection.getDouble(DropperArenaStorageKey.PLAYER_VERTICAL_VELOCITY.getKey());
|
||||||
float horizontalVelocity = sanitizeHorizontalVelocity((float) configurationSection.getDouble(
|
float horizontalVelocity = sanitizeHorizontalVelocity((float) configurationSection.getDouble(
|
||||||
DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey()));
|
DropperArenaStorageKey.PLAYER_HORIZONTAL_VELOCITY.getKey()));
|
||||||
|
int maxPlayers = configurationSection.getInt(DropperArenaStorageKey.MAX_PLAYERS.getKey(), -1);
|
||||||
SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get(
|
SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get(
|
||||||
DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey());
|
DropperArenaStorageKey.WIN_BLOCK_TYPE.getKey());
|
||||||
|
|
||||||
@ -183,8 +218,12 @@ public final class DropperArenaStorageHelper {
|
|||||||
arenaData = getEmptyDropperData(arenaId);
|
arenaData = getEmptyDropperData(arenaId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Set<String> allowedDamageCauseNames = loadStrings(configurationSection, DropperArenaStorageKey.ALLOWED_DAMAGE_CAUSES);
|
||||||
|
Set<String> lossTriggerDamageCauseNames = loadStrings(configurationSection, DropperArenaStorageKey.LOSS_TRIGGER_DAMAGE_CAUSES);
|
||||||
|
|
||||||
return new DropperArena(arenaId, arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity,
|
return new DropperArena(arenaId, arenaName, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity,
|
||||||
winBlockType.getRawValue(), rewards, arenaData, MiniGames.getInstance().getDropperArenaHandler());
|
winBlockType.getRawValue(), maxPlayers, rewards, arenaData,
|
||||||
|
MiniGames.getInstance().getDropperArenaHandler(), allowedDamageCauseNames, lossTriggerDamageCauseNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -222,9 +261,14 @@ public final class DropperArenaStorageHelper {
|
|||||||
* @return <p>The loaded arena data</p>
|
* @return <p>The loaded arena data</p>
|
||||||
*/
|
*/
|
||||||
private static @Nullable DropperArenaData loadDropperArenaData(@NotNull UUID arenaId) {
|
private static @Nullable DropperArenaData loadDropperArenaData(@NotNull UUID arenaId) {
|
||||||
|
try {
|
||||||
File arenaDataFile = getDropperArenaDataFile(arenaId);
|
File arenaDataFile = getDropperArenaDataFile(arenaId);
|
||||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile);
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile);
|
||||||
return (DropperArenaData) configuration.get(DropperArenaStorageKey.DATA.getKey());
|
return (DropperArenaData) configuration.get(DropperArenaStorageKey.DATA.getKey());
|
||||||
|
} catch (YAMLException exception) {
|
||||||
|
MiniGames.log(Level.SEVERE, "Unable to load arena data from arena " + arenaId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
package net.knarcraft.minigames.util;
|
package net.knarcraft.minigames.util;
|
||||||
|
|
||||||
|
import net.knarcraft.knargui.item.GUIItemFactory;
|
||||||
import net.knarcraft.knargui.item.PlayerHeadGUIItemFactory;
|
import net.knarcraft.knargui.item.PlayerHeadGUIItemFactory;
|
||||||
|
import net.knarcraft.knargui.item.SimpleGUIItemFactory;
|
||||||
import net.knarcraft.minigames.MiniGames;
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import net.knarcraft.minigames.arena.ArenaSession;
|
import net.knarcraft.minigames.arena.ArenaSession;
|
||||||
import net.knarcraft.minigames.gui.MiniGamesGUI;
|
import net.knarcraft.minigames.gui.MiniGamesGUI;
|
||||||
import net.knarcraft.minigames.property.PersistentDataKey;
|
import net.knarcraft.minigames.property.PersistentDataKey;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class for the in-arena GUI
|
* A helper class for the in-arena GUI
|
||||||
@ -21,12 +25,26 @@ public final class GUIHelper {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the GUI open item to give to the specified player
|
||||||
|
*
|
||||||
|
* @param player <p>The player to give a GUI opening item</p>
|
||||||
|
* @return <p>The item to give</p>
|
||||||
|
*/
|
||||||
|
public static ItemStack getGUIOpenItem(@NotNull Player player) {
|
||||||
|
if (GeyserHelper.isGeyserPlayer(player)) {
|
||||||
|
return getGUIOpenItemBedrock();
|
||||||
|
} else {
|
||||||
|
return getGUIOpenItemJava();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the item used for opening the mini-games menu
|
* Gets the item used for opening the mini-games menu
|
||||||
*
|
*
|
||||||
* @return <p>The item used for opening the GUI</p>
|
* @return <p>The item used for opening the GUI</p>
|
||||||
*/
|
*/
|
||||||
public static ItemStack getGUIOpenItem() {
|
public static ItemStack getGUIOpenItemJava() {
|
||||||
PlayerHeadGUIItemFactory factory = new PlayerHeadGUIItemFactory();
|
PlayerHeadGUIItemFactory factory = new PlayerHeadGUIItemFactory();
|
||||||
factory.useSkin("3fdab40434ed5d01f58c45ca0c9fada4662e1772ff43e2974979440a5cfe15c9");
|
factory.useSkin("3fdab40434ed5d01f58c45ca0c9fada4662e1772ff43e2974979440a5cfe15c9");
|
||||||
factory.setName(ChatColor.AQUA + "§ MiniGames Menu §");
|
factory.setName(ChatColor.AQUA + "§ MiniGames Menu §");
|
||||||
@ -41,6 +59,25 @@ public final class GUIHelper {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the item used for opening the mini-games menu
|
||||||
|
*
|
||||||
|
* @return <p>The item used for opening the GUI</p>
|
||||||
|
*/
|
||||||
|
public static ItemStack getGUIOpenItemBedrock() {
|
||||||
|
GUIItemFactory factory = new SimpleGUIItemFactory(Material.BEACON);
|
||||||
|
factory.setName(ChatColor.AQUA + "MiniGames Menu");
|
||||||
|
ItemStack item = factory.build();
|
||||||
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
if (meta != null) {
|
||||||
|
meta.getPersistentDataContainer().set(new NamespacedKey(MiniGames.getInstance(),
|
||||||
|
PersistentDataKey.MENU_ITEM.getKeyName()),
|
||||||
|
PersistentDataType.INTEGER, PersistentDataKey.MENU_ITEM.getDataValue());
|
||||||
|
}
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the correct GUI for the given player
|
* Opens the correct GUI for the given player
|
||||||
*
|
*
|
||||||
|
53
src/main/java/net/knarcraft/minigames/util/GeyserHelper.java
Normal file
53
src/main/java/net/knarcraft/minigames/util/GeyserHelper.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package net.knarcraft.minigames.util;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.geysermc.floodgate.api.FloodgateApi;
|
||||||
|
import org.geysermc.geyser.api.GeyserApi;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper class for dealing with geyser/floodgate players
|
||||||
|
*/
|
||||||
|
public final class GeyserHelper {
|
||||||
|
|
||||||
|
private static boolean hasGeyser = true;
|
||||||
|
private static boolean hasFloodgate = true;
|
||||||
|
|
||||||
|
private GeyserHelper() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given player is connected through Geyser
|
||||||
|
*
|
||||||
|
* @param player <p>The player to check</p>
|
||||||
|
* @return <p>True if the player is connected through Geyser</p>
|
||||||
|
*/
|
||||||
|
public static boolean isGeyserPlayer(@NotNull Player player) {
|
||||||
|
// Prevent unnecessary checking for non-geyser and floodgate servers
|
||||||
|
if (!hasGeyser && !hasFloodgate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use Geyser API to get connection status
|
||||||
|
if (hasGeyser) {
|
||||||
|
try {
|
||||||
|
return GeyserApi.api().connectionByUuid(player.getUniqueId()) != null;
|
||||||
|
} catch (NoClassDefFoundError error1) {
|
||||||
|
hasGeyser = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use Floodgate API to get connection status
|
||||||
|
if (hasFloodgate) {
|
||||||
|
try {
|
||||||
|
return FloodgateApi.getInstance().isFloodgatePlayer(player.getUniqueId());
|
||||||
|
} catch (NoClassDefFoundError error2) {
|
||||||
|
hasFloodgate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,15 @@
|
|||||||
package net.knarcraft.minigames.util;
|
package net.knarcraft.minigames.util;
|
||||||
|
|
||||||
|
import net.knarcraft.minigames.MiniGames;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class for validating whether given input is valid
|
* A helper class for validating whether given input is valid
|
||||||
@ -18,9 +26,48 @@ public final class InputValidationHelper {
|
|||||||
* @param location <p>The location to validate</p>
|
* @param location <p>The location to validate</p>
|
||||||
* @return <p>False if the location is valid</p>
|
* @return <p>False if the location is valid</p>
|
||||||
*/
|
*/
|
||||||
public static boolean isInvalid(Location location) {
|
public static boolean isInvalid(@Nullable Location location) {
|
||||||
|
if (location == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
World world = location.getWorld();
|
World world = location.getWorld();
|
||||||
return world == null || !world.getWorldBorder().isInside(location);
|
return world == null || !world.getWorldBorder().isInside(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given value can be considered "empty"
|
||||||
|
*
|
||||||
|
* @param value <p>The value to check</p>
|
||||||
|
* @return <p>True if the value can be considered as empty</p>
|
||||||
|
*/
|
||||||
|
public static boolean isEmptyValue(@NotNull String value) {
|
||||||
|
return value.equalsIgnoreCase("null") || value.equalsIgnoreCase("clear") ||
|
||||||
|
value.equalsIgnoreCase("none");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a set of damage causes from a set of damage cause names
|
||||||
|
*
|
||||||
|
* @param input <p>The damage cause names to parse</p>
|
||||||
|
* @return <p>The resulting damage causes</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Set<EntityDamageEvent.DamageCause> parseDamageCauses(@Nullable Set<String> input) {
|
||||||
|
Set<EntityDamageEvent.DamageCause> output = new HashSet<>();
|
||||||
|
|
||||||
|
if (input == null) {
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String causeName : input) {
|
||||||
|
try {
|
||||||
|
output.add(EntityDamageEvent.DamageCause.valueOf(causeName));
|
||||||
|
} catch (IllegalArgumentException | NullPointerException exception) {
|
||||||
|
MiniGames.log(Level.WARNING, "The damage cause " + causeName +
|
||||||
|
" is invalid, and will be ignored.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import java.util.UUID;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import static net.knarcraft.minigames.util.ArenaStorageHelper.getArenaDataFile;
|
import static net.knarcraft.minigames.util.ArenaStorageHelper.getArenaDataFile;
|
||||||
|
import static net.knarcraft.minigames.util.ArenaStorageHelper.loadStrings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class for saving and loading parkour arenas
|
* A helper class for saving and loading parkour arenas
|
||||||
@ -99,6 +100,35 @@ public final class ParkourArenaStorageHelper {
|
|||||||
YamlConfiguration configuration = new YamlConfiguration();
|
YamlConfiguration configuration = new YamlConfiguration();
|
||||||
ConfigurationSection arenaSection = configuration.createSection(parkourArenasConfigurationSection);
|
ConfigurationSection arenaSection = configuration.createSection(parkourArenasConfigurationSection);
|
||||||
for (ParkourArena arena : arenas.values()) {
|
for (ParkourArena arena : arenas.values()) {
|
||||||
|
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
|
//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
|
// must be stored as well
|
||||||
@NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString());
|
@NotNull ConfigurationSection configSection = arenaSection.createSection(arena.getArenaId().toString());
|
||||||
@ -108,12 +138,46 @@ public final class ParkourArenaStorageHelper {
|
|||||||
configSection.set(ParkourArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation());
|
configSection.set(ParkourArenaStorageKey.EXIT_LOCATION.getKey(), arena.getExitLocation());
|
||||||
configSection.set(ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
|
configSection.set(ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey(), new SerializableMaterial(arena.getWinBlockType()));
|
||||||
configSection.set(ParkourArenaStorageKey.WIN_LOCATION.getKey(), arena.getWinLocation());
|
configSection.set(ParkourArenaStorageKey.WIN_LOCATION.getKey(), arena.getWinLocation());
|
||||||
configSection.set(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey(), arena.getKillPlaneBlockNames());
|
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.CHECKPOINTS.getKey(), arena.getCheckpoints());
|
||||||
|
configSection.set(ParkourArenaStorageKey.MAX_PLAYERS.getKey(), arena.getMaxPlayers());
|
||||||
|
configSection.set(ParkourArenaStorageKey.ALLOWED_DAMAGE_CAUSES.getKey(),
|
||||||
|
ArenaStorageHelper.getDamageCauseNames(arena.getAllowedDamageCauses()));
|
||||||
|
configSection.set(ParkourArenaStorageKey.LOSS_TRIGGER_DAMAGE_CAUSES.getKey(),
|
||||||
|
ArenaStorageHelper.getDamageCauseNames(arena.getLossTriggerDamageCauses()));
|
||||||
RewardStorageHelper.saveRewards(arena, configSection, ParkourArenaStorageKey.REWARDS.getKey());
|
RewardStorageHelper.saveRewards(arena, configSection, ParkourArenaStorageKey.REWARDS.getKey());
|
||||||
saveParkourArenaData(arena.getData());
|
saveParkourArenaData(arena.getData());
|
||||||
}
|
}
|
||||||
configuration.save(parkourArenaFile);
|
|
||||||
|
/**
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private static List<String> getKillPlaneBlocks(@NotNull 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>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private static List<String> getObstacleBlocks(@NotNull ParkourArena arena) {
|
||||||
|
if (arena.getObstacleBlockNames() == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
} else {
|
||||||
|
return new ArrayList<>(arena.getObstacleBlockNames());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,7 +185,8 @@ public final class ParkourArenaStorageHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>The loaded arenas, or null if the arenas configuration section is missing.</p>
|
* @return <p>The loaded arenas, or null if the arenas configuration section is missing.</p>
|
||||||
*/
|
*/
|
||||||
public static @NotNull Map<UUID, ParkourArena> loadParkourArenas() {
|
@NotNull
|
||||||
|
public static Map<UUID, ParkourArena> loadParkourArenas() {
|
||||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(parkourArenaFile);
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(parkourArenaFile);
|
||||||
ConfigurationSection arenaSection = configuration.getConfigurationSection(parkourArenasConfigurationSection);
|
ConfigurationSection arenaSection = configuration.getConfigurationSection(parkourArenasConfigurationSection);
|
||||||
//If no such section exists, it must be the case that there is no data to load
|
//If no such section exists, it must be the case that there is no data to load
|
||||||
@ -154,16 +219,18 @@ public final class ParkourArenaStorageHelper {
|
|||||||
* @return <p>The loaded arena, or null if invalid</p>
|
* @return <p>The loaded arena, or null if invalid</p>
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static @Nullable ParkourArena loadParkourArena(@NotNull ConfigurationSection configurationSection) {
|
@Nullable
|
||||||
|
private static ParkourArena loadParkourArena(@NotNull ConfigurationSection configurationSection) {
|
||||||
UUID arenaId = ((SerializableUUID) configurationSection.get(ParkourArenaStorageKey.ID.getKey(),
|
UUID arenaId = ((SerializableUUID) configurationSection.get(ParkourArenaStorageKey.ID.getKey(),
|
||||||
new SerializableUUID(UUID.randomUUID()))).getRawValue();
|
new SerializableUUID(UUID.randomUUID()))).getRawValue();
|
||||||
String arenaName = configurationSection.getString(ParkourArenaStorageKey.NAME.getKey());
|
String arenaName = configurationSection.getString(ParkourArenaStorageKey.NAME.getKey());
|
||||||
Location spawnLocation = (Location) configurationSection.get(ParkourArenaStorageKey.SPAWN_LOCATION.getKey());
|
Location spawnLocation = (Location) configurationSection.get(ParkourArenaStorageKey.SPAWN_LOCATION.getKey());
|
||||||
Location exitLocation = (Location) configurationSection.get(ParkourArenaStorageKey.EXIT_LOCATION.getKey());
|
Location exitLocation = (Location) configurationSection.get(ParkourArenaStorageKey.EXIT_LOCATION.getKey());
|
||||||
Location winLocation = (Location) configurationSection.get(ParkourArenaStorageKey.WIN_LOCATION.getKey());
|
Location winLocation = (Location) configurationSection.get(ParkourArenaStorageKey.WIN_LOCATION.getKey());
|
||||||
SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get(
|
int maxPlayers = configurationSection.getInt(ParkourArenaStorageKey.MAX_PLAYERS.getKey(), -1);
|
||||||
ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey());
|
SerializableMaterial winBlockType = (SerializableMaterial) configurationSection.get(ParkourArenaStorageKey.WIN_BLOCK_TYPE.getKey());
|
||||||
List<?> killPlaneBlockNames = configurationSection.getList(ParkourArenaStorageKey.KILL_PLANE_BLOCKS.getKey());
|
Set<String> killPlaneBlockNames = loadStrings(configurationSection, ParkourArenaStorageKey.KILL_PLANE_BLOCKS);
|
||||||
|
Set<String> obstacleBlockNames = loadStrings(configurationSection, ParkourArenaStorageKey.OBSTACLE_BLOCKS);
|
||||||
List<Location> checkpoints = (List<Location>) configurationSection.get(ParkourArenaStorageKey.CHECKPOINTS.getKey());
|
List<Location> checkpoints = (List<Location>) configurationSection.get(ParkourArenaStorageKey.CHECKPOINTS.getKey());
|
||||||
|
|
||||||
Map<RewardCondition, Set<Reward>> rewards = RewardStorageHelper.loadRewards(configurationSection,
|
Map<RewardCondition, Set<Reward>> rewards = RewardStorageHelper.loadRewards(configurationSection,
|
||||||
@ -194,9 +261,12 @@ public final class ParkourArenaStorageHelper {
|
|||||||
checkpoints = new ArrayList<>();
|
checkpoints = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Set<String> allowedDamageCauseNames = loadStrings(configurationSection, ParkourArenaStorageKey.ALLOWED_DAMAGE_CAUSES);
|
||||||
|
Set<String> lossTriggerDamageCauseNames = loadStrings(configurationSection, ParkourArenaStorageKey.LOSS_TRIGGER_DAMAGE_CAUSES);
|
||||||
|
|
||||||
return new ParkourArena(arenaId, arenaName, spawnLocation, exitLocation, winBlockType.getRawValue(), winLocation,
|
return new ParkourArena(arenaId, arenaName, spawnLocation, exitLocation, winBlockType.getRawValue(), winLocation,
|
||||||
(Set<String>) killPlaneBlockNames, checkpoints, rewards, arenaData,
|
killPlaneBlockNames, obstacleBlockNames, checkpoints, maxPlayers, rewards, arenaData,
|
||||||
MiniGames.getInstance().getParkourArenaHandler());
|
MiniGames.getInstance().getParkourArenaHandler(), allowedDamageCauseNames, lossTriggerDamageCauseNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,7 +275,8 @@ public final class ParkourArenaStorageHelper {
|
|||||||
* @param arenaId <p>The id to get parkour data for</p>
|
* @param arenaId <p>The id to get parkour data for</p>
|
||||||
* @return <p>Empty parkour data</p>
|
* @return <p>Empty parkour data</p>
|
||||||
*/
|
*/
|
||||||
private static @NotNull ParkourArenaData getEmptyParkourData(@NotNull UUID arenaId) {
|
@NotNull
|
||||||
|
private static ParkourArenaData getEmptyParkourData(@NotNull UUID arenaId) {
|
||||||
Map<ArenaGameMode, ArenaRecordsRegistry> recordRegistries = new HashMap<>();
|
Map<ArenaGameMode, ArenaRecordsRegistry> recordRegistries = new HashMap<>();
|
||||||
Map<ArenaGameMode, Set<UUID>> playersCompleted = new HashMap<>();
|
Map<ArenaGameMode, Set<UUID>> playersCompleted = new HashMap<>();
|
||||||
for (ArenaGameMode arenaGameMode : ParkourArenaGameMode.values()) {
|
for (ArenaGameMode arenaGameMode : ParkourArenaGameMode.values()) {
|
||||||
@ -233,7 +304,8 @@ public final class ParkourArenaStorageHelper {
|
|||||||
* @param arenaId <p>The id of the arena to get data for</p>
|
* @param arenaId <p>The id of the arena to get data for</p>
|
||||||
* @return <p>The loaded arena data</p>
|
* @return <p>The loaded arena data</p>
|
||||||
*/
|
*/
|
||||||
private static @Nullable ParkourArenaData loadParkourArenaData(@NotNull UUID arenaId) {
|
@Nullable
|
||||||
|
private static ParkourArenaData loadParkourArenaData(@NotNull UUID arenaId) {
|
||||||
File arenaDataFile = getParkourArenaDataFile(arenaId);
|
File arenaDataFile = getParkourArenaDataFile(arenaId);
|
||||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile);
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(arenaDataFile);
|
||||||
return (ParkourArenaData) configuration.get(ParkourArenaStorageKey.DATA.getKey());
|
return (ParkourArenaData) configuration.get(ParkourArenaStorageKey.DATA.getKey());
|
||||||
@ -255,7 +327,8 @@ public final class ParkourArenaStorageHelper {
|
|||||||
* @param arenaId <p>The id of the arena to get a data file for</p>
|
* @param arenaId <p>The id of the arena to get a data file for</p>
|
||||||
* @return <p>The file the arena's data is/should be stored in</p>
|
* @return <p>The file the arena's data is/should be stored in</p>
|
||||||
*/
|
*/
|
||||||
private static @NotNull File getParkourArenaDataFile(@NotNull UUID arenaId) {
|
@NotNull
|
||||||
|
private static File getParkourArenaDataFile(@NotNull UUID arenaId) {
|
||||||
return getArenaDataFile(parkourArenaDataFolder, arenaId);
|
return getArenaDataFile(parkourArenaDataFolder, arenaId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import java.util.Collection;
|
|||||||
import java.util.UUID;
|
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 {
|
public final class RewardHelper {
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@ import net.knarcraft.minigames.arena.dropper.DropperArenaEditableProperty;
|
|||||||
import net.knarcraft.minigames.arena.parkour.ParkourArenaEditableProperty;
|
import net.knarcraft.minigames.arena.parkour.ParkourArenaEditableProperty;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.Tag;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
import org.bukkit.permissions.Permission;
|
import org.bukkit.permissions.Permission;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -16,6 +19,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,7 +40,8 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>All arena names</p>
|
* @return <p>All arena names</p>
|
||||||
*/
|
*/
|
||||||
public static @NotNull List<String> getDropperArenas() {
|
@NotNull
|
||||||
|
public static List<String> getDropperArenas() {
|
||||||
return getArenas(MiniGames.getInstance().getDropperArenaHandler());
|
return getArenas(MiniGames.getInstance().getDropperArenaHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +50,8 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>All arena names</p>
|
* @return <p>All arena names</p>
|
||||||
*/
|
*/
|
||||||
public static @NotNull List<String> getParkourArenas() {
|
@NotNull
|
||||||
|
public static List<String> getParkourArenas() {
|
||||||
return getArenas(MiniGames.getInstance().getParkourArenaHandler());
|
return getArenas(MiniGames.getInstance().getParkourArenaHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +60,8 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>All arena names</p>
|
* @return <p>All arena names</p>
|
||||||
*/
|
*/
|
||||||
private static @NotNull List<String> getArenas(ArenaHandler<?, ?> arenaHandler) {
|
@NotNull
|
||||||
|
private static List<String> getArenas(@NotNull ArenaHandler<?, ?> arenaHandler) {
|
||||||
List<String> arenaNames = new ArrayList<>();
|
List<String> arenaNames = new ArrayList<>();
|
||||||
for (Arena arena : arenaHandler.getArenas().values()) {
|
for (Arena arena : arenaHandler.getArenas().values()) {
|
||||||
arenaNames.add(arena.getArenaName());
|
arenaNames.add(arena.getArenaName());
|
||||||
@ -67,7 +74,8 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>All arena properties</p>
|
* @return <p>All arena properties</p>
|
||||||
*/
|
*/
|
||||||
public static @NotNull List<String> getDropperArenaProperties() {
|
@NotNull
|
||||||
|
public static List<String> getDropperArenaProperties() {
|
||||||
List<String> arenaProperties = new ArrayList<>();
|
List<String> arenaProperties = new ArrayList<>();
|
||||||
for (DropperArenaEditableProperty property : DropperArenaEditableProperty.values()) {
|
for (DropperArenaEditableProperty property : DropperArenaEditableProperty.values()) {
|
||||||
arenaProperties.add(property.getArgumentString());
|
arenaProperties.add(property.getArgumentString());
|
||||||
@ -80,7 +88,8 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>All arena properties</p>
|
* @return <p>All arena properties</p>
|
||||||
*/
|
*/
|
||||||
public static @NotNull List<String> getParkourArenaProperties() {
|
@NotNull
|
||||||
|
public static List<String> getParkourArenaProperties() {
|
||||||
List<String> arenaProperties = new ArrayList<>();
|
List<String> arenaProperties = new ArrayList<>();
|
||||||
for (ParkourArenaEditableProperty property : ParkourArenaEditableProperty.values()) {
|
for (ParkourArenaEditableProperty property : ParkourArenaEditableProperty.values()) {
|
||||||
arenaProperties.add(property.getArgumentString());
|
arenaProperties.add(property.getArgumentString());
|
||||||
@ -94,7 +103,8 @@ public final class TabCompleteHelper {
|
|||||||
* @param propertyType <p>The property type to get suggestions for</p>
|
* @param propertyType <p>The property type to get suggestions for</p>
|
||||||
* @return <p>The suggestions produced</p>
|
* @return <p>The suggestions produced</p>
|
||||||
*/
|
*/
|
||||||
public static List<String> getTabCompleteSuggestions(EditablePropertyType propertyType) {
|
@NotNull
|
||||||
|
public static List<String> getTabCompleteSuggestions(@NotNull EditablePropertyType propertyType) {
|
||||||
if (tabCompleteSuggestions == null) {
|
if (tabCompleteSuggestions == null) {
|
||||||
tabCompleteSuggestions = new HashMap<>();
|
tabCompleteSuggestions = new HashMap<>();
|
||||||
tabCompleteSuggestions.put(EditablePropertyType.LOCATION, getLocationSuggestions());
|
tabCompleteSuggestions.put(EditablePropertyType.LOCATION, getLocationSuggestions());
|
||||||
@ -104,20 +114,106 @@ public final class TabCompleteHelper {
|
|||||||
tabCompleteSuggestions.put(EditablePropertyType.BLOCK_TYPE, getBlockTypeSuggestions());
|
tabCompleteSuggestions.put(EditablePropertyType.BLOCK_TYPE, getBlockTypeSuggestions());
|
||||||
tabCompleteSuggestions.put(EditablePropertyType.CHECKPOINT_CLEAR, getCheckpointClearSuggestions());
|
tabCompleteSuggestions.put(EditablePropertyType.CHECKPOINT_CLEAR, getCheckpointClearSuggestions());
|
||||||
tabCompleteSuggestions.put(EditablePropertyType.MATERIAL_LIST, getMaterialListSuggestions());
|
tabCompleteSuggestions.put(EditablePropertyType.MATERIAL_LIST, getMaterialListSuggestions());
|
||||||
|
tabCompleteSuggestions.put(EditablePropertyType.DOUBLE, getDoubleSuggestions());
|
||||||
|
tabCompleteSuggestions.put(EditablePropertyType.INTEGER, getIntegerSuggestions());
|
||||||
|
tabCompleteSuggestions.put(EditablePropertyType.DAMAGE_CAUSE_LIST, getDamageCauseSuggestions());
|
||||||
}
|
}
|
||||||
|
|
||||||
return tabCompleteSuggestions.get(propertyType);
|
return tabCompleteSuggestions.get(propertyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets tab-complete suggestions for list properties
|
||||||
|
*
|
||||||
|
* @param propertyType <p>Gets the type of property to show tab-completions for</p>
|
||||||
|
* @param input <p>The input string to use for filtering</p>
|
||||||
|
* @return <p>The tab-completions to suggest</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static List<String> getListCompleteSuggestions(@NotNull EditablePropertyType propertyType,
|
||||||
|
@NotNull String input) {
|
||||||
|
List<String> allValues;
|
||||||
|
if (propertyType == EditablePropertyType.DAMAGE_CAUSE_LIST) {
|
||||||
|
allValues = getTabCompleteSuggestions((EditablePropertyType.DAMAGE_CAUSE_LIST));
|
||||||
|
} else if (propertyType == EditablePropertyType.MATERIAL_LIST) {
|
||||||
|
allValues = getTabCompleteSuggestions((EditablePropertyType.MATERIAL_LIST));
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Invalid property type given!");
|
||||||
|
}
|
||||||
|
return TabCompletionHelper.getStringList(allValues, input, TabCompletionHelper::filterMatchingContains);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets tab-complete suggestions for a list of damage causes
|
||||||
|
*
|
||||||
|
* @return <p>Damage cause suggestions</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private static List<String> getDamageCauseSuggestions() {
|
||||||
|
List<String> suggestions = new ArrayList<>();
|
||||||
|
for (EntityDamageEvent.DamageCause damageCause : EntityDamageEvent.DamageCause.values()) {
|
||||||
|
suggestions.add(damageCause.name());
|
||||||
|
}
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets tab-complete suggestions for an integer value
|
||||||
|
*
|
||||||
|
* @return <p>Integer suggestions</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private static List<String> getIntegerSuggestions() {
|
||||||
|
List<String> 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
|
||||||
|
*
|
||||||
|
* @return <p>A list of suggestions</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
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
|
* Gets suggestions for a list of materials
|
||||||
*
|
*
|
||||||
* @return <p>A list of suggestions</p>
|
* @return <p>A list of suggestions</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
private static List<String> getMaterialListSuggestions() {
|
private static List<String> getMaterialListSuggestions() {
|
||||||
List<String> suggestions = new ArrayList<>();
|
List<String> suggestions = new ArrayList<>();
|
||||||
suggestions.add("LAVA,MAGMA_BLOCK");
|
for (Material material : Material.values()) {
|
||||||
suggestions.add("WATER,MAGMA_BLOCK,LAVA,+BUTTONS,+CORALS");
|
if (material.isBlock()) {
|
||||||
|
NamespacedKey key = material.getKeyOrNull();
|
||||||
|
if (key != null) {
|
||||||
|
suggestions.add(key.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Tag<Material> tag : getTags()) {
|
||||||
|
suggestions.add("+" + tag.getKey().getKey());
|
||||||
|
}
|
||||||
return suggestions;
|
return suggestions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +222,7 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>A list of suggestions</p>
|
* @return <p>A list of suggestions</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
private static List<String> getCheckpointClearSuggestions() {
|
private static List<String> getCheckpointClearSuggestions() {
|
||||||
List<String> suggestions = new ArrayList<>();
|
List<String> suggestions = new ArrayList<>();
|
||||||
suggestions.add("true");
|
suggestions.add("true");
|
||||||
@ -137,6 +234,7 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>A list of suggestions</p>
|
* @return <p>A list of suggestions</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
private static List<String> getBlockTypeSuggestions() {
|
private static List<String> getBlockTypeSuggestions() {
|
||||||
List<String> materials = new ArrayList<>();
|
List<String> materials = new ArrayList<>();
|
||||||
for (Material material : Material.values()) {
|
for (Material material : Material.values()) {
|
||||||
@ -152,6 +250,7 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>A list of suggestions</p>
|
* @return <p>A list of suggestions</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
private static List<String> getVerticalVelocitySuggestions() {
|
private static List<String> getVerticalVelocitySuggestions() {
|
||||||
List<String> velocities = new ArrayList<>();
|
List<String> velocities = new ArrayList<>();
|
||||||
velocities.add("0.01");
|
velocities.add("0.01");
|
||||||
@ -169,6 +268,7 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>A list of suggestions</p>
|
* @return <p>A list of suggestions</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
private static List<String> getHorizontalVelocitySuggestions() {
|
private static List<String> getHorizontalVelocitySuggestions() {
|
||||||
List<String> velocities = new ArrayList<>();
|
List<String> velocities = new ArrayList<>();
|
||||||
velocities.add("0.01");
|
velocities.add("0.01");
|
||||||
@ -183,6 +283,7 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>A list of suggestions</p>
|
* @return <p>A list of suggestions</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
private static List<String> getNameSuggestions() {
|
private static List<String> getNameSuggestions() {
|
||||||
List<String> locations = new ArrayList<>();
|
List<String> locations = new ArrayList<>();
|
||||||
locations.add("DropperArena1");
|
locations.add("DropperArena1");
|
||||||
@ -197,10 +298,12 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @return <p>A list of suggestions</p>
|
* @return <p>A list of suggestions</p>
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
private static List<String> getLocationSuggestions() {
|
private static List<String> getLocationSuggestions() {
|
||||||
List<String> locations = new ArrayList<>();
|
List<String> locations = new ArrayList<>();
|
||||||
locations.add("here");
|
locations.add("here");
|
||||||
locations.add("x,y,z");
|
locations.add("x,y,z");
|
||||||
|
locations.add("null");
|
||||||
return locations;
|
return locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +313,8 @@ public final class TabCompleteHelper {
|
|||||||
* @param typedNode <p>The full permission node typed by the player</p>
|
* @param typedNode <p>The full permission node typed by the player</p>
|
||||||
* @return <p>All known valid auto-complete options</p>
|
* @return <p>All known valid auto-complete options</p>
|
||||||
*/
|
*/
|
||||||
public static List<String> tabCompletePermission(String typedNode) {
|
@NotNull
|
||||||
|
public static List<String> tabCompletePermission(@NotNull String typedNode) {
|
||||||
if (plugins == null) {
|
if (plugins == null) {
|
||||||
loadAvailablePermissions();
|
loadAvailablePermissions();
|
||||||
}
|
}
|
||||||
@ -248,7 +352,7 @@ public final class TabCompleteHelper {
|
|||||||
*
|
*
|
||||||
* @param permissionName <p>The permission to load</p>
|
* @param permissionName <p>The permission to load</p>
|
||||||
*/
|
*/
|
||||||
private static void loadPermission(String permissionName) {
|
private static void loadPermission(@NotNull String permissionName) {
|
||||||
String[] permissionParts = permissionName.split("\\.");
|
String[] permissionParts = permissionName.split("\\.");
|
||||||
if (permissionParts.length == 1 && !plugins.contains(permissionParts[0])) {
|
if (permissionParts.length == 1 && !plugins.contains(permissionParts[0])) {
|
||||||
plugins.add(permissionParts[0]);
|
plugins.add(permissionParts[0]);
|
||||||
@ -265,4 +369,28 @@ public final class TabCompleteHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all useful tags for physical blocks
|
||||||
|
*
|
||||||
|
* @return <p>All block tags</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private static Set<Tag<Material>> getTags() {
|
||||||
|
// TODO: Find a way to get the tags programmatically
|
||||||
|
return Set.of(Tag.ACACIA_LOGS, Tag.ALL_HANGING_SIGNS, Tag.ALL_SIGNS, Tag.ANVIL, Tag.WALLS,
|
||||||
|
Tag.BAMBOO_BLOCKS, Tag.BANNERS, Tag.BEDS, Tag.BEEHIVES, Tag.BIRCH_LOGS,
|
||||||
|
Tag.BUTTONS, Tag.CAMPFIRES, Tag.CANDLE_CAKES, Tag.CANDLES, Tag.CAULDRONS, Tag.CAVE_VINES,
|
||||||
|
Tag.CEILING_HANGING_SIGNS, Tag.CHERRY_LOGS, Tag.CLIMBABLE, Tag.COAL_ORES, Tag.CONCRETE_POWDER,
|
||||||
|
Tag.COPPER_ORES, Tag.CORAL_BLOCKS, Tag.CORAL_PLANTS, Tag.CORALS, Tag.CRIMSON_STEMS, Tag.CROPS,
|
||||||
|
Tag.DARK_OAK_LOGS, Tag.DIAMOND_ORES, Tag.DIRT, Tag.DOORS, Tag.EMERALD_ORES, Tag.FENCE_GATES, Tag.FENCES,
|
||||||
|
Tag.FIRE, Tag.FLOWER_POTS, Tag.FLOWERS, Tag.GOLD_ORES, Tag.ICE, Tag.IRON_ORES, Tag.JUNGLE_LOGS,
|
||||||
|
Tag.LAPIS_ORES, Tag.LEAVES, Tag.LOGS, Tag.MANGROVE_LOGS, Tag.NYLIUM, Tag.OAK_LOGS, Tag.PLANKS,
|
||||||
|
Tag.PORTALS, Tag.PRESSURE_PLATES, Tag.RAILS, Tag.REDSTONE_ORES, Tag.SAND, Tag.SAPLINGS, Tag.WART_BLOCKS,
|
||||||
|
Tag.SHULKER_BOXES, Tag.SIGNS, Tag.SLABS, Tag.SMALL_FLOWERS, Tag.SNOW, Tag.SPRUCE_LOGS, Tag.STAIRS,
|
||||||
|
Tag.STANDING_SIGNS, Tag.STONE_BRICKS, Tag.STONE_BUTTONS, Tag.TERRACOTTA, Tag.WOOL,
|
||||||
|
Tag.TRAPDOORS, Tag.WALL_CORALS, Tag.WALL_HANGING_SIGNS, Tag.WALL_SIGNS, Tag.WARPED_STEMS,
|
||||||
|
Tag.WOODEN_BUTTONS, Tag.WOODEN_DOORS, Tag.WOODEN_FENCES, Tag.WOODEN_PRESSURE_PLATES, Tag.WOODEN_STAIRS,
|
||||||
|
Tag.WOODEN_TRAPDOORS);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,12 @@ parkour:
|
|||||||
killPlaneBlocks:
|
killPlaneBlocks:
|
||||||
- LAVA
|
- LAVA
|
||||||
- MAGMA_BLOCK
|
- 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:
|
dropper:
|
||||||
# Whether to block using the shift key to drop faster than the intended drop speed
|
# Whether to block using the shift key to drop faster than the intended drop speed
|
||||||
blockSneaking: true
|
blockSneaking: true
|
||||||
@ -61,8 +67,9 @@ dropper:
|
|||||||
- REDSTONE_WALL_TORCH
|
- REDSTONE_WALL_TORCH
|
||||||
- +BANNERS
|
- +BANNERS
|
||||||
- +BUTTONS
|
- +BUTTONS
|
||||||
- +CORALS
|
- +CORAL_PLANTS
|
||||||
- +WALL_CORALS
|
- +WALL_CORALS
|
||||||
|
- LIGHT
|
||||||
shared:
|
shared:
|
||||||
# This decides how far inside a non-solid block the player must go before detection triggers (-1, 0). The closer to -1
|
# 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.
|
# it is, the more accurate it will seem to the player, but the likelihood of not detecting the hit increases.
|
||||||
|
@ -2,11 +2,13 @@ name: MiniGames
|
|||||||
prefix: MiniGames
|
prefix: MiniGames
|
||||||
version: '${project.version}'
|
version: '${project.version}'
|
||||||
main: net.knarcraft.minigames.MiniGames
|
main: net.knarcraft.minigames.MiniGames
|
||||||
api-version: 1.19
|
api-version: 1.21
|
||||||
description: A plugin that adds various mini-games
|
description: A plugin that adds various mini-games
|
||||||
softdepend:
|
softdepend:
|
||||||
- PlaceholderAPI
|
- PlaceholderAPI
|
||||||
- Vault
|
- Vault
|
||||||
|
- Geyser-Spigot
|
||||||
|
- floodgate
|
||||||
|
|
||||||
# Note to self: Aliases must be lowercase!
|
# Note to self: Aliases must be lowercase!
|
||||||
commands:
|
commands:
|
||||||
@ -82,15 +84,15 @@ commands:
|
|||||||
aliases:
|
aliases:
|
||||||
- dcreate
|
- dcreate
|
||||||
permission: minigames.create.dropper
|
permission: minigames.create.dropper
|
||||||
usage: |
|
usage: /<command> <arena>
|
||||||
/<command> <arena> <property> [new value]
|
|
||||||
- Valid properties: name, spawnLocation, exitLocation, verticalVelocity, horizontalVelocity, winBlockType
|
|
||||||
description: Used to create a new dropper arena
|
description: Used to create a new dropper arena
|
||||||
dropperEdit:
|
dropperEdit:
|
||||||
aliases:
|
aliases:
|
||||||
- dedit
|
- dedit
|
||||||
permission: minigames.edit.dropper
|
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
|
description: Used to edit an existing dropper arena
|
||||||
dropperRemove:
|
dropperRemove:
|
||||||
aliases:
|
aliases:
|
||||||
@ -143,19 +145,19 @@ commands:
|
|||||||
aliases:
|
aliases:
|
||||||
- pcreate
|
- pcreate
|
||||||
permission: minigames.create.parkour
|
permission: minigames.create.parkour
|
||||||
usage: |
|
usage: /<command> <arena>
|
||||||
/<command> <arena> <property> [new value]
|
|
||||||
- Valid properties: name, spawnLocation, exitLocation, winBlockType, winLocation, checkpointAdd, checkpointClear, killPlaneBlocks
|
|
||||||
description: Used to create a new parkour arena
|
description: Used to create a new parkour arena
|
||||||
parkourEdit:
|
parkourEdit:
|
||||||
aliases:
|
aliases:
|
||||||
- pedit
|
- pedit
|
||||||
permission: minigames.edit.parkour
|
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
|
description: Used to edit an existing parkour arena
|
||||||
parkourRemove:
|
parkourRemove:
|
||||||
aliases:
|
aliases:
|
||||||
- dremove
|
- premove
|
||||||
permission: minigames.remove.parkour
|
permission: minigames.remove.parkour
|
||||||
usage: /<command> <arena>
|
usage: /<command> <arena>
|
||||||
description: Used to remove an existing parkour arena
|
description: Used to remove an existing parkour arena
|
||||||
|
@ -29,6 +29,8 @@ en:
|
|||||||
ERROR_INVALID_COMMAND_STRING: "You specified an invalid command. Make sure you don't add a slash in front of the command definition."
|
ERROR_INVALID_COMMAND_STRING: "You specified an invalid command. Make sure you don't add a slash in front of the command definition."
|
||||||
ERROR_REWARD_TYPE_INVALID: "You have specified an invalid reward type"
|
ERROR_REWARD_TYPE_INVALID: "You have specified an invalid reward type"
|
||||||
ERROR_REWARD_CONDITION_INVALID: "You have specified an invalid reward condition"
|
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_ARENA_GROUP_UPDATED: "The arena's group has been updated"
|
||||||
SUCCESS_PLUGIN_RELOADED: "Plugin reloaded!"
|
SUCCESS_PLUGIN_RELOADED: "Plugin reloaded!"
|
||||||
SUCCESS_ARENA_CREATED: "The arena was successfully created!"
|
SUCCESS_ARENA_CREATED: "The arena was successfully created!"
|
||||||
@ -42,6 +44,7 @@ en:
|
|||||||
SUCCESS_DROPPER_ARENAS_LIST: "Dropper arenas:&r"
|
SUCCESS_DROPPER_ARENAS_LIST: "Dropper arenas:&r"
|
||||||
SUCCESS_PARKOUR_ARENAS_LIST: "Parkour arenas:&r"
|
SUCCESS_PARKOUR_ARENAS_LIST: "Parkour arenas:&r"
|
||||||
SUCCESS_CHECKPOINT_REACHED: "Checkpoint reached!"
|
SUCCESS_CHECKPOINT_REACHED: "Checkpoint reached!"
|
||||||
|
SUCCESS_GROUPS: "Arena groups:&r"
|
||||||
SUCCESS_GROUP_STAGES: "{group}'s stages:&r"
|
SUCCESS_GROUP_STAGES: "{group}'s stages:&r"
|
||||||
SUCCESS_RECORD_ACHIEVED: "You just set a {recordInfo} on the {gameMode} game-mode!"
|
SUCCESS_RECORD_ACHIEVED: "You just set a {recordInfo} on the {gameMode} game-mode!"
|
||||||
RECORD_ACHIEVED_GLOBAL: "new {recordType} record"
|
RECORD_ACHIEVED_GLOBAL: "new {recordType} record"
|
||||||
|
@ -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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Reference in New Issue
Block a user