Skip to content

Commit

Permalink
Added %parkour_topfirstplaces_(position)% & %parkour_player_total_fir…
Browse files Browse the repository at this point in the history
…stplaces% placeholders
  • Loading branch information
ash-burns committed Oct 21, 2024
1 parent e96ed3e commit 65c8491
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 9 deletions.
17 changes: 17 additions & 0 deletions docs/files/parkourPlaceholders.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
"placeholder": "%parkour_player_total_playing_time%",
"output": "02:03:45",
"description": "The total recorded time by the Player across all Courses."
},
{
"placeholder": "%parkour_player_total_firstplaces%",
"output": "2",
"description": "The total first place positions held by the Player across all Courses."
}
]
},
Expand Down Expand Up @@ -367,5 +372,17 @@
"description": "Display a summary of the global leaderboard entry. The output can be customised in the strings.yml (PlaceholderAPI.TopTenResult)"
}
]
},
{
"heading": "TopFirstPlaces Placeholders",
"alias": "tfp",
"description": "Display a summary of the highest total first place positions held by the given row across all Courses.",
"placeholders": [
{
"placeholder": "%parkour_topfirstplaces_(position)%",
"output": "&f1) &bA5H73Y&f - &a5",
"description": "Display a summary of the top first place entry. The output can be customised in the strings.yml (PlaceholderAPI.TopFirstPlaceResult)"
}
]
}
]
40 changes: 37 additions & 3 deletions src/main/java/io/github/a5h73y/parkour/ParkourPlaceholders.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package io.github.a5h73y.parkour;

import static io.github.a5h73y.parkour.other.ParkourConstants.AMOUNT_PLACEHOLDER;
import static io.github.a5h73y.parkour.other.ParkourConstants.DEATHS_PLACEHOLDER;
import static io.github.a5h73y.parkour.other.ParkourConstants.PLAYER_PLACEHOLDER;
import static io.github.a5h73y.parkour.other.ParkourConstants.POSITION_PLACEHOLDER;
import static io.github.a5h73y.parkour.other.ParkourConstants.TIME_PLACEHOLDER;

import io.github.a5h73y.parkour.database.FirstPlacesEntry;
import io.github.a5h73y.parkour.database.TimeEntry;
import io.github.a5h73y.parkour.type.course.CourseConfig;
import io.github.a5h73y.parkour.type.player.PlayerConfig;
Expand Down Expand Up @@ -32,6 +34,7 @@ public class ParkourPlaceholders extends PlaceholderExpansion {
private static final String INVALID_SYNTAX = TranslationUtils.getTranslation("PlaceholderAPI.InvalidSyntax", false);
private static final String NO_TIME_RECORDED = TranslationUtils.getTranslation("PlaceholderAPI.NoTimeRecorded", false);
private static final String TOP_TEN_RESULT = TranslationUtils.getTranslation("PlaceholderAPI.TopTenResult", false);
private static final String TOP_FIRST_PLACE_RESULT = TranslationUtils.getTranslation("PlaceholderAPI.TopFirstPlaceResult", false);
private static final String COURSE_ACTIVE = TranslationUtils.getTranslation("PlaceholderAPI.CourseActive", false);
private static final String COURSE_INACTIVE = TranslationUtils.getTranslation("PlaceholderAPI.CourseInactive", false);
private static final String NO_COOLDOWN_REMAINING = TranslationUtils.getTranslation("PlaceholderAPI.NoPrizeCooldown", false);
Expand Down Expand Up @@ -158,6 +161,14 @@ private String retrieveValue(OfflinePlayer offlinePlayer,
}
return getTopTenPlaceholderValue(arguments);

case "tfp":
case "topfirstplaces":
if (arguments.length != 2 || !ValidationUtils.isPositiveInteger(arguments[1])) {
return INVALID_SYNTAX;
}
return getOrRetrieveCache(() -> getTopFirstPlacePlaceholderValue(arguments[1]),
arguments[0], arguments[1]);

default:
return INVALID_SYNTAX;
}
Expand Down Expand Up @@ -270,11 +281,12 @@ private String getPlayerPlaceholderValue(OfflinePlayer offlinePlayer, String...
return getPersonalCourseRecord(player, arguments[3], arguments[4]);

case TOTAL:
if (arguments.length < 4) {
return INVALID_SYNTAX;
}
switch (arguments[2]) {
case LEADERBOARD:
if (arguments.length < 4) {
return INVALID_SYNTAX;
}

switch (arguments[3]) {
case DEATHS:
return getOrRetrieveCache(() -> String.valueOf(parkour.getDatabaseManager().getAccumulatedDeaths(offlinePlayer)),
Expand All @@ -293,6 +305,10 @@ private String getPlayerPlaceholderValue(OfflinePlayer offlinePlayer, String...
}

case PLAYING:
if (arguments.length < 4) {
return INVALID_SYNTAX;
}

switch (arguments[3]) {
case DEATHS:
return String.valueOf(playerConfig.getTotalDeaths());
Expand All @@ -304,6 +320,10 @@ private String getPlayerPlaceholderValue(OfflinePlayer offlinePlayer, String...
return INVALID_SYNTAX;
}

case "firstplaces":
return getOrRetrieveCache(() -> String.valueOf(parkour.getDatabaseManager().getNumberOfFirstPlaces(offlinePlayer)),
offlinePlayer.getName(), arguments[1], arguments[2]);

default:
return INVALID_SYNTAX;
}
Expand Down Expand Up @@ -502,6 +522,20 @@ private String getTopTenPlaceholderValue(String... arguments) {
}
}

private String getTopFirstPlacePlaceholderValue(String rowNumber) {
int position = Integer.parseInt(rowNumber);
FirstPlacesEntry result = parkour.getDatabaseManager().getGlobalFirstPlaces(position - 1);

if (result == null) {
return NO_TIME_RECORDED;

} else {
return TOP_FIRST_PLACE_RESULT.replace(PLAYER_PLACEHOLDER, result.getPlayerName())
.replace(POSITION_PLACEHOLDER, String.valueOf(position))
.replace(AMOUNT_PLACEHOLDER, String.valueOf(result.getTotal()));
}
}

private TimeEntry getTopPlayerResultForCourse(Player player, String courseName) {
List<TimeEntry> time = parkour.getDatabaseManager().getTopPlayerCourseResults(player, courseName, 1);
return time.isEmpty() ? null : time.get(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ public StringsConfig(File file) {
this.setDefault("PlaceholderAPI.CurrentCourseCompleted", "Yes");
this.setDefault("PlaceholderAPI.CurrentCourseNotCompleted", "No");
this.setDefault("PlaceholderAPI.TopTenResult", "&f%POSITION%) &b%PLAYER%&f in &a%TIME%");
this.setDefault("PlaceholderAPI.TopFirstPlaceResult", "&f%POSITION%) &b%PLAYER%&f - &a%AMOUNT%");
this.setDefault("PlaceholderAPI.CourseActive", "Active");
this.setDefault("PlaceholderAPI.CourseInactive", "Inactive");
this.setDefault("PlaceholderAPI.CheckpointHologram", "Checkpoint &b%VALUE%");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,44 @@ public int getAccumulatedTimes(@NotNull OfflinePlayer player) {
return result;
}

public int getNumberOfFirstPlaces(@NotNull OfflinePlayer player) {
int result = 0;
try (PreparedStatement statement = getDatabaseConnection().prepareStatement(
"SELECT COUNT(*) AS total FROM time t JOIN (SELECT courseId, MIN(time) AS best_time FROM time GROUP BY courseId) best ON t.courseId = best.courseId AND t.time = best.best_time WHERE t.playerId = ?")) {
statement.setString(1, getPlayerId(player));
ResultSet resultSet = statement.executeQuery();

if (resultSet.next()) {
result = resultSet.getInt("total");
}
resultSet.getStatement().close();
} catch (SQLException e) {
logSqlException(e);
}

return result;
}

public FirstPlacesEntry getGlobalFirstPlaces(Integer rowNumber) {
FirstPlacesEntry result = null;
try (PreparedStatement statement = getDatabaseConnection().prepareStatement(
"SELECT t1.playerId, COUNT(*) AS total FROM time t1 JOIN (SELECT courseId, MIN(time) AS best_time FROM time GROUP BY courseId) AS best_times ON t1.courseId = best_times.courseId AND t1.time = best_times.best_time GROUP BY t1.playerId ORDER BY total DESC, t1.playerId LIMIT 1 OFFSET ?;")) {
statement.setString(1, rowNumber.toString());
ResultSet resultSet = statement.executeQuery();

if (resultSet.next()) {
result = new FirstPlacesEntry(
resultSet.getString("playerId"),
resultSet.getInt("total"));

}
resultSet.getStatement().close();
} catch (SQLException e) {
logSqlException(e);
}

return result;
}

/**
* Determine if this is the best time on the course.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.github.a5h73y.parkour.database;

import io.github.a5h73y.parkour.utility.PlayerUtils;

public class FirstPlacesEntry {

private final String playerId;
private final int total;

private String playerName;

public FirstPlacesEntry(String playerId, int total) {
this.playerId = playerId;
this.total = total;
}

public String getPlayerName() {
if (playerName == null) {
playerName = PlayerUtils.findPlayerName(this.playerId);
}
return playerName;
}

public String getPlayerId() {
return playerId;
}

public int getTotal() {
return total;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ public void playerDie(Player player) {
}

prepareParkourPlayer(player);
applyCoursePotionEffect(player);
setGameMode(player, parkour.getParkourConfig().getString("OnJoin.SetGameMode"));
Bukkit.getServer().getPluginManager().callEvent(new ParkourDeathEvent(player, session.getCourse().getName()));
}
Expand Down Expand Up @@ -824,18 +825,18 @@ public void prepareParkourPlayer(Player player) {
PlayerUtils.removeAllPotionEffects(player);
}

Damageable playerDamage = player;
playerDamage.setHealth(playerDamage.getMaxHealth());
PlayerUtils.resetPlayer(player);
}

public void applyCoursePotionEffect(Player player) {
ParkourSession session = parkour.getParkourSessionManager().getParkourSession(player);

if (session != null && session.getParkourMode() == ParkourMode.POTION) {
XPotion.addEffects(player, parkour.getConfigManager().getCourseConfig(session.getCourseName())
.getPotionParkourModeEffects());
}

Damageable playerDamage = player;
playerDamage.setHealth(playerDamage.getMaxHealth());
player.setFallDistance(0);
player.setFireTicks(0);
player.eject();
}

/**
Expand Down Expand Up @@ -1337,6 +1338,7 @@ private void preparePlayerForCourse(Player player, String courseName) {
addItemsToInventory(player, parkour.getConfigManager().getDefaultConfig().getDefaultJoinItems());
addItemsToInventory(player, courseConfig.getJoinItems());
prepareParkourPlayer(player);
applyCoursePotionEffect(player);
setGameMode(player, parkour.getParkourConfig().getString("OnJoin.SetGameMode"));

if (courseConfig.getCourseMode() == ParkourMode.NORUN) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,5 +271,11 @@ public static void setInventoryAndArmor(Player player, ItemStack[] inventory, It
player.getInventory().setArmorContents(armor);
}

public static void resetPlayer(Player player) {
player.setFallDistance(0);
player.setFireTicks(0);
player.eject();
}

private PlayerUtils() {}
}
17 changes: 17 additions & 0 deletions src/main/resources/parkourPlaceholders.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
"placeholder": "%parkour_player_total_playing_time%",
"output": "02:03:45",
"description": "The total recorded time by the Player across all Courses."
},
{
"placeholder": "%parkour_player_total_firstplaces%",
"output": "2",
"description": "The total first place positions held by the Player across all Courses."
}
]
},
Expand Down Expand Up @@ -367,5 +372,17 @@
"description": "Display a summary of the global leaderboard entry. The output can be customised in the strings.yml (PlaceholderAPI.TopTenResult)"
}
]
},
{
"heading": "TopFirstPlaces Placeholders",
"alias": "tfp",
"description": "Display a summary of the highest total first place positions held by the given row across all Courses.",
"placeholders": [
{
"placeholder": "%parkour_topfirstplaces_(position)%",
"output": "&f1) &bA5H73Y&f - &a5",
"description": "Display a summary of the top first place entry. The output can be customised in the strings.yml (PlaceholderAPI.TopFirstPlaceResult)"
}
]
}
]

0 comments on commit 65c8491

Please sign in to comment.