From 985c4d60a165d6718e2e432a3ef65b8af5d1dd29 Mon Sep 17 00:00:00 2001 From: Lykous_ Date: Tue, 31 Mar 2026 21:53:53 +0200 Subject: [PATCH 1/3] Add vote_goal placeholders --- .../placeholders/VotePlaceholderProvider.java | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/bukkit/src/main/java/com/azuriom/azlink/bukkit/placeholders/VotePlaceholderProvider.java b/bukkit/src/main/java/com/azuriom/azlink/bukkit/placeholders/VotePlaceholderProvider.java index c17bbc3..10bc288 100644 --- a/bukkit/src/main/java/com/azuriom/azlink/bukkit/placeholders/VotePlaceholderProvider.java +++ b/bukkit/src/main/java/com/azuriom/azlink/bukkit/placeholders/VotePlaceholderProvider.java @@ -22,6 +22,7 @@ public class VotePlaceholderProvider implements PlaceholderProvider, Runnable, L private final Map voteSites = new HashMap<>(); private final Map users = new HashMap<>(); private final List topVotes = new ArrayList<>(); + private volatile VoteGoal goal; private volatile boolean pendingRefresh = true; private volatile Instant lastUpdate = Instant.MIN; @@ -64,7 +65,9 @@ public List availablePlaceholders() { "%azlink_vote_sites_[id]_name%", "%azlink_vote_sites_[id]_url%", "%azlink_vote_top_[position]_name%", - "%azlink_vote_top_[position]_votes%" + "%azlink_vote_top_[position]_votes%", + "%azlink_vote_goal_target%", + "%azlink_vote_goal_progress%" ); } @@ -94,6 +97,8 @@ public String evaluatePlaceholder(String[] parts, OfflinePlayer player) { return topPlaceholder(parts); case "sites": return sitePlaceholder(parts); + case "goal": + return goalPlaceholder(parts); default: return null; } @@ -134,6 +139,23 @@ private String userCanPlaceholder(String[] parts, OfflinePlayer player) throws N return null; } + private String goalPlaceholder(String[] parts) throws NumberFormatException { + VoteGoal currentGoal = this.goal; + + if (currentGoal == null) { + return "0"; + } + + switch (parts[1]) { + case "target": + return Integer.toString(currentGoal.target); + case "progress": + return Integer.toString(currentGoal.progress); + default: + return null; + } + } + private String sitePlaceholder(String[] parts) throws NumberFormatException { if (parts[1].equals("count")) { return Integer.toString(voteSites.size()); @@ -229,6 +251,7 @@ private void refreshData() { this.voteSites.clear(); this.users.clear(); this.topVotes.clear(); + this.goal = response.goal; for (VoteSite site : response.sites) { this.voteSites.put(site.id, site); @@ -260,6 +283,12 @@ public static class VoteResponse { public List users = new ArrayList<>(); @SerializedName("top_votes") public List topVotes = new ArrayList<>(); + public VoteGoal goal; + } + + public static class VoteGoal { + public int target; + public int progress; } public static class VoteUser { From 3cf829288612fc9f5112b785bba3acc65c200353 Mon Sep 17 00:00:00 2001 From: MrMicky Date: Tue, 31 Mar 2026 17:19:37 -0400 Subject: [PATCH 2/3] Add goal placeholders to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index aee1605..0fd6eec 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ When the shop and/or vote plugins are installed on your Azuriom website, the int * `%azlink_vote_sites_[id]_url%`: URL of vote site with given ID * `%azlink_vote_top_[position]_name%`: name of player at given position in vote ranking * `%azlink_vote_top_[position]_votes%`: vote count of player at given position in ranking +* `%azlink_vote_goal_progress%`: number of votes currently counted toward the monthly vote goal +* `%azlink_vote_goal_target%`: total number of votes required to reach the monthly vote goal ### Shop Placeholders * `%azlink_shop_goal_progress%`: current progress of the shop goal this month From 36499ca2fe845bab944d00381ed8e46fa0a16845 Mon Sep 17 00:00:00 2001 From: MrMicky Date: Sun, 12 Apr 2026 08:38:25 -0400 Subject: [PATCH 3/3] Refactor with PR review suggestions --- .../placeholders/VotePlaceholderProvider.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/bukkit/src/main/java/com/azuriom/azlink/bukkit/placeholders/VotePlaceholderProvider.java b/bukkit/src/main/java/com/azuriom/azlink/bukkit/placeholders/VotePlaceholderProvider.java index 10bc288..03fad83 100644 --- a/bukkit/src/main/java/com/azuriom/azlink/bukkit/placeholders/VotePlaceholderProvider.java +++ b/bukkit/src/main/java/com/azuriom/azlink/bukkit/placeholders/VotePlaceholderProvider.java @@ -13,14 +13,14 @@ import java.time.Duration; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class VotePlaceholderProvider implements PlaceholderProvider, Runnable, Listener { - private final Map voteSites = new HashMap<>(); - private final Map users = new HashMap<>(); + private final Map voteSites = new ConcurrentHashMap<>(); + private final Map users = new ConcurrentHashMap<>(); private final List topVotes = new ArrayList<>(); private volatile VoteGoal goal; @@ -98,7 +98,7 @@ public String evaluatePlaceholder(String[] parts, OfflinePlayer player) { case "sites": return sitePlaceholder(parts); case "goal": - return goalPlaceholder(parts); + return goalPlaceholder(parts[1]); default: return null; } @@ -139,18 +139,14 @@ private String userCanPlaceholder(String[] parts, OfflinePlayer player) throws N return null; } - private String goalPlaceholder(String[] parts) throws NumberFormatException { - VoteGoal currentGoal = this.goal; + private String goalPlaceholder(String action) { + VoteGoal goal = this.goal; - if (currentGoal == null) { - return "0"; - } - - switch (parts[1]) { + switch (action) { case "target": - return Integer.toString(currentGoal.target); + return goal != null ? Integer.toString(goal.target) : "0"; case "progress": - return Integer.toString(currentGoal.progress); + return goal != null ? Integer.toString(goal.progress) : "0"; default: return null; } @@ -269,7 +265,9 @@ private void refreshData() { } private VoteUser getUserFromPlayer(OfflinePlayer player) { - return this.users.get(player.getName().toLowerCase(Locale.ROOT)); + String name = player.getName(); + + return name != null ? this.users.get(name.toLowerCase(Locale.ROOT)) : null; } private String formatDuration(Duration duration) {