diff --git a/docs/changelogs.md b/docs/changelogs.md
index 30b15d14..7d5d89fb 100644
--- a/docs/changelogs.md
+++ b/docs/changelogs.md
@@ -6,7 +6,7 @@ Please note that each version of Parkour is backwards compatible with the previo
## 7.2.0
* Added ability to set a one-time fee for a course
-Added "ParkourTool.RemoveRightClickRestriction" to support geyser controls
+* Added "ParkourTool.RemoveRightClickRestriction" to support geyser controls
* Added "Other.Display.CurrencyName" to show or hide currency name in messages
* Added Throwables to be ParkourTools
* Ability to disable nested parkour commands
diff --git a/pom.xml b/pom.xml
index 6e380fba..a7ad5185 100644
--- a/pom.xml
+++ b/pom.xml
@@ -91,7 +91,7 @@
me.clip
placeholderapi
- 2.11.2
+ 2.11.3
provided
@@ -111,7 +111,7 @@
org.bstats
bstats-bukkit
- 3.0.1
+ 3.0.2
compile
@@ -138,7 +138,7 @@
com.github.cryptomorin
XSeries
- 9.3.0
+ 9.4.0
compile
@@ -152,7 +152,7 @@
com.github.simplix-softworks
simplixstorage
- 3.2.5
+ 3.2.6
@@ -168,7 +168,7 @@
org.json
json
- 20230227
+ 20230618
diff --git a/src/main/java/io/github/a5h73y/parkour/configuration/impl/DefaultConfig.java b/src/main/java/io/github/a5h73y/parkour/configuration/impl/DefaultConfig.java
index e66c49b5..c5946648 100644
--- a/src/main/java/io/github/a5h73y/parkour/configuration/impl/DefaultConfig.java
+++ b/src/main/java/io/github/a5h73y/parkour/configuration/impl/DefaultConfig.java
@@ -98,6 +98,7 @@ public DefaultConfig(File file) {
this.setDefault("OnCourse.TreatLastCheckpointAsFinish", false);
this.setDefault("OnCourse.ParkourKit.Enabled", true);
this.setDefault("OnCourse.ParkourKit.IncludeVehicles", false);
+ this.setDefault("OnCourse.ParkourKit.FloatingClosestBlock", true);
this.setDefault("OnCourse.EnforceParkourCommands.Enabled", true);
this.setDefault("OnCourse.EnforceParkourCommands.Whitelist", Collections.singletonList("login"));
diff --git a/src/main/java/io/github/a5h73y/parkour/configuration/impl/StringsConfig.java b/src/main/java/io/github/a5h73y/parkour/configuration/impl/StringsConfig.java
index c8ee9df8..4b98a5b9 100644
--- a/src/main/java/io/github/a5h73y/parkour/configuration/impl/StringsConfig.java
+++ b/src/main/java/io/github/a5h73y/parkour/configuration/impl/StringsConfig.java
@@ -94,6 +94,7 @@ public StringsConfig(File file) {
this.setDefault("Parkour.Challenge.Winner", "Congratulations! You won the challenge on &b%VALUE%!");
this.setDefault("Parkour.Challenge.WinnerWager", "You have been rewarded &b%VALUE% &ffor winning the wager!");
this.setDefault("Parkour.Challenge.Loser", "&b%PLAYER% &fhas completed &b%COURSE% &fbefore you!");
+ this.setDefault("Parkour.Challenge.LoserWager", "You have had &b%VALUE% &fdeducted from your balance!");
this.setDefault("Event.Join", "This server uses &bParkour &3%VALUE%");
this.setDefault("Event.Checkpoint", "Checkpoint set to &b%CURRENT% &8/ &7%TOTAL%");
diff --git a/src/main/java/io/github/a5h73y/parkour/listener/move/ParkourBlockListener.java b/src/main/java/io/github/a5h73y/parkour/listener/move/ParkourBlockListener.java
index f91ef06c..a8e7634e 100644
--- a/src/main/java/io/github/a5h73y/parkour/listener/move/ParkourBlockListener.java
+++ b/src/main/java/io/github/a5h73y/parkour/listener/move/ParkourBlockListener.java
@@ -26,8 +26,11 @@ public class ParkourBlockListener extends AbstractPluginReceiver implements List
public static final List BLOCK_FACES =
Arrays.asList(BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST);
+ private final boolean floatingClosestBlock;
+
public ParkourBlockListener(final Parkour parkour) {
super(parkour);
+ this.floatingClosestBlock = parkour.getParkourConfig().getBoolean("OnCourse.ParkourKit.FloatingClosestBlock");
}
/**
@@ -64,7 +67,9 @@ public void onPlayerMove(PlayerMoveEvent event) {
}
// they are clearly hovering and another block is holding them up
- if (player.isOnGround() && XBlock.isAir(belowMaterial)) {
+ if (player.isOnGround()
+ && this.floatingClosestBlock
+ && XBlock.isAir(belowMaterial)) {
belowMaterial = calculateClosestBlock(player);
}
diff --git a/src/main/java/io/github/a5h73y/parkour/plugin/EconomyApi.java b/src/main/java/io/github/a5h73y/parkour/plugin/EconomyApi.java
index 79046ebb..1b0f1435 100644
--- a/src/main/java/io/github/a5h73y/parkour/plugin/EconomyApi.java
+++ b/src/main/java/io/github/a5h73y/parkour/plugin/EconomyApi.java
@@ -355,4 +355,9 @@ private void processAmountCommand(CommandSender commandSender, String... args) {
TranslationUtils.sendMessage(commandSender, args[2] + "'s balance: &b" + getAmount(economy.getBalance(targetPlayer)));
}
+
+ @Override
+ public String getPluginDisplayName() {
+ return "Vault (Economy)";
+ }
}
diff --git a/src/main/java/io/github/a5h73y/parkour/plugin/PermissionVault.java b/src/main/java/io/github/a5h73y/parkour/plugin/PermissionVault.java
index 91cca5dc..1d550e32 100644
--- a/src/main/java/io/github/a5h73y/parkour/plugin/PermissionVault.java
+++ b/src/main/java/io/github/a5h73y/parkour/plugin/PermissionVault.java
@@ -55,4 +55,8 @@ public String getPluginName() {
return "Vault";
}
+ @Override
+ public String getPluginDisplayName() {
+ return "Vault (Permissions)";
+ }
}
diff --git a/src/main/java/io/github/a5h73y/parkour/plugin/PluginWrapper.java b/src/main/java/io/github/a5h73y/parkour/plugin/PluginWrapper.java
index 0a3b6062..2063c467 100644
--- a/src/main/java/io/github/a5h73y/parkour/plugin/PluginWrapper.java
+++ b/src/main/java/io/github/a5h73y/parkour/plugin/PluginWrapper.java
@@ -22,6 +22,10 @@ public abstract class PluginWrapper extends AbstractPluginReceiver {
*/
public abstract String getPluginName();
+ public String getPluginDisplayName() {
+ return this.getPluginName();
+ }
+
/**
* Initialise the startup of the plugin on Construction of object.
*/
@@ -46,11 +50,11 @@ protected void initialise() {
// otherwise display error
if (externalPlugin != null && externalPlugin.isEnabled()) {
enabled = true;
- PluginUtils.log("[" + getPluginName() + "] Successfully linked. "
+ PluginUtils.log("[" + getPluginDisplayName() + "] Successfully linked. "
+ "Version: " + externalPlugin.getDescription().getVersion(), 0);
} else {
- PluginUtils.log("[" + getPluginName() + "] Plugin is missing, link was unsuccessful.", 1);
+ PluginUtils.log("[" + getPluginDisplayName() + "] Plugin is missing, link was unsuccessful.", 1);
}
}
diff --git a/src/main/java/io/github/a5h73y/parkour/type/challenge/ChallengeManager.java b/src/main/java/io/github/a5h73y/parkour/type/challenge/ChallengeManager.java
index 776bee1b..23d5745f 100644
--- a/src/main/java/io/github/a5h73y/parkour/type/challenge/ChallengeManager.java
+++ b/src/main/java/io/github/a5h73y/parkour/type/challenge/ChallengeManager.java
@@ -5,6 +5,13 @@
import static io.github.a5h73y.parkour.other.ParkourConstants.ERROR_NO_EXIST;
import static io.github.a5h73y.parkour.other.ParkourConstants.PLAYER_PLACEHOLDER;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.WeakHashMap;
+
import io.github.a5h73y.parkour.Parkour;
import io.github.a5h73y.parkour.other.AbstractPluginReceiver;
import io.github.a5h73y.parkour.plugin.EconomyApi;
@@ -15,12 +22,6 @@
import io.github.a5h73y.parkour.utility.ValidationUtils;
import io.github.a5h73y.parkour.utility.permission.Permission;
import io.github.a5h73y.parkour.utility.permission.PermissionUtils;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.WeakHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
@@ -178,7 +179,8 @@ public void removeInvitation(Player player) {
*/
public boolean hasPlayerBeenChallenged(Player player) {
return hasPlayerBeenInvited(player)
- || challenges.values().stream().filter(challenge -> challenge.hasStarted()).anyMatch(challenge -> challenge.isPlayerParticipating(player));
+ || challenges.values().stream()
+ .anyMatch(challenge -> challenge.isPlayerParticipating(player));
}
/**
@@ -267,6 +269,8 @@ public void completeChallenge(Player winner) {
if (challenge.getWager() != null) {
parkour.getEconomyApi().chargePlayer(loser, challenge.getWager());
+ TranslationUtils.sendValueTranslation("Parkour.Challenge.LoserWager",
+ parkour.getEconomyApi().getAmount(challenge.getWager()), loser);
}
}
}
@@ -361,7 +365,7 @@ public void prepareParticipant(Challenge challenge, Player participant) {
}
if (parkour.getParkourSessionManager().isPlaying(participant)) {
- parkour.getPlayerManager().leaveCourse(participant, false);
+ parkour.getPlayerManager().leaveCourse(participant, true);
}
parkour.getPlayerManager().joinCourse(participant, challenge.getCourseName());
participant.setWalkSpeed(0f);
@@ -516,15 +520,9 @@ private void processCreateCommand(Player player, String courseName, @Nullable St
}
private void processSendInviteCommand(Player player, String... args) {
- Challenge challenge = getChallengeForHost(player);
-
- if (challenge == null) {
- TranslationUtils.sendMessage(player, "You have not created a Challenge.");
- return;
- }
+ Challenge challenge = getChallengeForPlayer(player);
- if (challenge.hasStarted()) {
- TranslationUtils.sendMessage(player, "Your Challenge has already started.");
+ if (!validateChallengeAuthorityValidity(player, challenge)) {
return;
}
@@ -537,15 +535,9 @@ private void processSendInviteCommand(Player player, String... args) {
}
private void processStartCommand(Player player) {
- Challenge challenge = getChallengeForHost(player);
-
- if (challenge == null) {
- TranslationUtils.sendMessage(player, "You have not created a challenge.");
- return;
- }
+ Challenge challenge = getChallengeForPlayer(player);
- if (challenge.hasStarted()) {
- TranslationUtils.sendMessage(player, "The Challenge has already started!");
+ if (!validateChallengeAuthorityValidity(player, challenge)) {
return;
}
@@ -559,6 +551,20 @@ private void processStartCommand(Player player) {
challenge.markStarted();
}
+ private void processTerminateCommand(Player player) {
+ Challenge challenge = getChallengeForPlayer(player);
+
+ if (!validateChallengeAuthorityValidity(player, challenge)) {
+ return;
+ }
+
+ challenge.getParticipatingPlayers().forEach(participantId ->
+ TranslationUtils.sendMessage(Bukkit.getPlayer(participantId), "The host has terminated the Challenge."));
+
+ invites.entrySet().removeIf(entry -> entry.getValue().getChallenge().equals(challenge));
+ removeChallenge(player);
+ }
+
private void processInviteReceiveCommand(Player player, boolean accepted) {
ChallengeInvite invite = getInviteForPlayer(player);
@@ -574,24 +580,23 @@ private void processInviteReceiveCommand(Player player, boolean accepted) {
}
}
- private void processTerminateCommand(Player hostPlayer) {
- Challenge challenge = getChallengeForHost(hostPlayer);
-
+ private boolean validateChallengeAuthorityValidity(Player player, Challenge challenge) {
if (challenge == null) {
- TranslationUtils.sendMessage(hostPlayer, "You have not created a Challenge.");
- return;
+ TranslationUtils.sendMessage(player, "You are not on a Challenge.");
+ return false;
}
- if (challenge.hasStarted()) {
- TranslationUtils.sendMessage(hostPlayer, "You can not terminate a Challenge in progress.");
- return;
+ if (!challenge.getChallengeHost().getName().equals(player.getName())) {
+ TranslationUtils.sendMessage(player, "You are not the host of this Challenge.");
+ return false;
}
- challenge.getParticipatingPlayers().forEach(participantId ->
- TranslationUtils.sendMessage(Bukkit.getPlayer(participantId), "The host has terminated the Challenge."));
+ if (challenge.hasStarted()) {
+ TranslationUtils.sendMessage(player, "The Challenge has already started!");
+ return false;
+ }
- invites.entrySet().removeIf(entry -> entry.getValue().getChallenge().equals(challenge));
- removeChallenge(hostPlayer);
+ return true;
}
/**
@@ -648,6 +653,11 @@ public boolean canCreateChallenge(Player player, String courseNameInput, String
return false;
}
+ if (getChallengeForPlayer(player) != null) {
+ TranslationUtils.sendTranslation("Error.OnChallenge", player);
+ return false;
+ }
+
if (!parkour.getPlayerManager().canJoinCourseSilent(player, courseName)) {
TranslationUtils.sendMessage(player, "You are not able to join this Course!");
return false;
diff --git a/src/main/java/io/github/a5h73y/parkour/utility/cache/GenericCache.java b/src/main/java/io/github/a5h73y/parkour/utility/cache/GenericCache.java
index c6372b36..9d60fdd1 100644
--- a/src/main/java/io/github/a5h73y/parkour/utility/cache/GenericCache.java
+++ b/src/main/java/io/github/a5h73y/parkour/utility/cache/GenericCache.java
@@ -44,14 +44,19 @@ public boolean containsKey(K key) {
}
protected Set getExpiredKeys() {
- return this.cacheMap.keySet().parallelStream()
+ return this.cacheMap.keySet()
+ .parallelStream()
.filter(this::isExpired)
.collect(Collectors.toSet());
}
protected boolean isExpired(K key) {
- LocalDateTime expirationDateTime = this.cacheMap.get(key).getCreatedAt().plus(this.cacheTimeout, ChronoUnit.SECONDS);
- return LocalDateTime.now().isAfter(expirationDateTime);
+ boolean result = true;
+ if (this.cacheMap.containsKey(key)) {
+ LocalDateTime expirationDateTime = this.cacheMap.get(key).getCreatedAt().plus(this.cacheTimeout, ChronoUnit.SECONDS);
+ result = LocalDateTime.now().isAfter(expirationDateTime);
+ }
+ return result;
}
@Override