diff --git a/build.gradle.kts b/build.gradle.kts index a93bbdc..fb1e4e5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,6 +20,7 @@ repositories { maven("https://repo.papermc.io/repository/maven-public/") maven("https://repo.battleplugins.org/releases/") maven("https://repo.battleplugins.org/snapshots/") + maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") } dependencies { @@ -29,6 +30,7 @@ dependencies { compileOnlyApi(libs.paper.api) compileOnlyApi(libs.battlearena) + compileOnlyApi(libs.placeholderapi) } java { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bb72b07..bcc74a2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,6 +3,7 @@ bstats-bukkit = "3.0.2" paper-api = "1.20.4-R0.1-SNAPSHOT" commons = "2.12.0" battlearena = "4.0.0-SNAPSHOT" +placeholderapi = "2.11.6" [libraries] battlearena = { group = "org.battleplugins", name = "arena", version.ref = "battlearena" } @@ -10,3 +11,4 @@ bstats-bukkit = { group = "org.bstats", name = "bstats-bukkit", version.ref = "b paper-api = { group = "io.papermc.paper", name = "paper-api", version.ref = "paper-api" } commons-dbcp = { group = "org.apache.commons", name = "commons-dbcp2", version.ref = "commons" } commons-pool = { group = "org.apache.commons", name = "commons-pool2", version.ref = "commons" } +placeholderapi = { group = "me.clip", name = "placeholderapi", version.ref = "placeholderapi" } diff --git a/src/main/java/org/battleplugins/tracker/BattleTracker.java b/src/main/java/org/battleplugins/tracker/BattleTracker.java index 071dd17..552b3eb 100644 --- a/src/main/java/org/battleplugins/tracker/BattleTracker.java +++ b/src/main/java/org/battleplugins/tracker/BattleTracker.java @@ -5,6 +5,7 @@ import org.battleplugins.tracker.feature.battlearena.BattleArenaFeature; import org.battleplugins.tracker.feature.combatlog.CombatLog; import org.battleplugins.tracker.feature.damageindicators.DamageIndicators; +import org.battleplugins.tracker.feature.placeholderapi.PlaceholderApiFeature; import org.battleplugins.tracker.message.Messages; import org.battleplugins.tracker.sql.SqlSerializer; import org.battleplugins.tracker.sql.TrackerSqlSerializer; @@ -54,6 +55,8 @@ public class BattleTracker extends JavaPlugin { private final Map> trackerListeners = new HashMap<>(); private BattleArenaFeature battleArenaFeature; + private PlaceholderApiFeature placeholderApiFeature; + private CombatLog combatLog; private DamageIndicators damageIndicators; @@ -144,6 +147,9 @@ private void enable() { this.battleArenaFeature = new BattleArenaFeature(); this.battleArenaFeature.onEnable(this); + + this.placeholderApiFeature = new PlaceholderApiFeature(); + this.placeholderApiFeature.onEnable(this); } @Override @@ -160,6 +166,10 @@ private CompletableFuture disable(boolean block) { this.unloadFeature(this.battleArenaFeature); } + if (this.placeholderApiFeature != null) { + this.unloadFeature(this.placeholderApiFeature); + } + if (this.combatLog != null) { this.unloadFeature(this.combatLog); } @@ -266,7 +276,7 @@ public void registerCalculator(RatingCalculator calculator) { * @param tracker the tracker to register */ public void registerTracker(Tracker tracker) { - this.trackers.put(tracker.getName(), tracker); + this.trackers.put(tracker.getName().toLowerCase(Locale.ROOT), tracker); } /** @@ -319,7 +329,7 @@ public Optional tracker(String name) { */ @Nullable public Tracker getTracker(String name) { - return this.trackers.get(name); + return this.trackers.get(name.toLowerCase(Locale.ROOT)); } /** diff --git a/src/main/java/org/battleplugins/tracker/TrackerExecutor.java b/src/main/java/org/battleplugins/tracker/TrackerExecutor.java index 6c4a424..2ec6e10 100644 --- a/src/main/java/org/battleplugins/tracker/TrackerExecutor.java +++ b/src/main/java/org/battleplugins/tracker/TrackerExecutor.java @@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.text.DecimalFormat; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; @@ -313,19 +312,17 @@ private void versus(CommandSender sender, OfflinePlayer player1, OfflinePlayer p } private void versus0(CommandSender sender, OfflinePlayer player1, Record record1, OfflinePlayer player2, Record record2, VersusTally tally) { - DecimalFormat format = new DecimalFormat("0.##"); - Messages.send(sender, "header", Messages.getPlain("versus-tally")); Messages.send(sender, "versus", Map.of( "player", record1.getName(), "target", record2.getName(), - "player_rating", format.format(record1.getRating()), - "target_rating", format.format(record2.getRating()) + "player_rating", Util.STAT_FORMAT.format(record1.getRating()), + "target_rating", Util.STAT_FORMAT.format(record2.getRating()) )); Map replacements = new HashMap<>(); - replacements.put("kills", format.format(tally.getStat(StatType.KILLS))); - replacements.put("deaths", format.format(tally.getStat(StatType.DEATHS))); + replacements.put("kills", Util.STAT_FORMAT.format(tally.getStat(StatType.KILLS))); + replacements.put("deaths", Util.STAT_FORMAT.format(tally.getStat(StatType.DEATHS))); // Since versus tallies are only stored one way, we need to flip the value // in the scenario that the "1st" player instead the 2nd player diff --git a/src/main/java/org/battleplugins/tracker/feature/placeholderapi/BattleTrackerExpansion.java b/src/main/java/org/battleplugins/tracker/feature/placeholderapi/BattleTrackerExpansion.java new file mode 100644 index 0000000..005a6f9 --- /dev/null +++ b/src/main/java/org/battleplugins/tracker/feature/placeholderapi/BattleTrackerExpansion.java @@ -0,0 +1,104 @@ +package org.battleplugins.tracker.feature.placeholderapi; + +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import org.battleplugins.tracker.BattleTracker; +import org.battleplugins.tracker.Tracker; +import org.battleplugins.tracker.stat.Record; +import org.battleplugins.tracker.stat.StatType; +import org.battleplugins.tracker.util.Util; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +class BattleTrackerExpansion extends PlaceholderExpansion { + private final BattleTracker battleTracker; + + public BattleTrackerExpansion(BattleTracker battleTracker) { + this.battleTracker = battleTracker; + } + + @Override + public @NotNull String getIdentifier() { + return "bt"; + } + + @Override + public @NotNull String getAuthor() { + return "BattlePlugins"; + } + + @Override + public @NotNull String getVersion() { + return this.battleTracker.getPluginMeta().getVersion(); + } + + @Override + public @Nullable String onPlaceholderRequest(Player player, @NotNull String params) { + String[] split = params.split("_"); + String trackerName = split[0]; + + // The tracker is not tracked or does not exist + Tracker tracker = this.battleTracker.getTracker(trackerName); + if (tracker == null) { + return ""; + } + + // Gets leaderboard stats (ex: %bt_pvp_top_kills_1%) + if (split[1].equalsIgnoreCase("top")) { + String stat = split[2]; + StatType type = StatType.get(stat); + int idxOffset = 0; + if (type == null && split.length >= 4) { + type = StatType.get(split[2] + "_" + split[3]); + idxOffset = 1; + } + + if (type != null) { + int place; + try { + place = Integer.parseInt(split[3 + idxOffset]); + } catch (NumberFormatException ex) { + return null; // Not a number at the end of the placeholder + } + + List topRecords = tracker.getTopRecords(place, type).join(); + if (topRecords.size() < place) { + return ""; + } + + Record topRecord = topRecords.get(place - 1); + if (split.length >= 5) { + switch (split[split.length - 1]) { + case "name" -> { + return topRecord.getName(); + } + case "uuid" -> { + return topRecord.getId().toString(); + } + }; + } + + return Util.STAT_FORMAT.format(topRecord.getStat(type)); + } + } + + // Gets player stats (ex: %bt_pvp_kills%) + if (player == null || !player.isOnline()) { + return ""; + } + + StatType type = StatType.get(split[1]); + if (type == null && split.length >= 3) { + type = StatType.get(split[1] + "_" + split[2]); + } + + Record record = tracker.getRecord(player); + if (type != null) { + return Util.STAT_FORMAT.format(record.getStat(type)); + } + + return null; + } +} diff --git a/src/main/java/org/battleplugins/tracker/feature/placeholderapi/PlaceholderApiFeature.java b/src/main/java/org/battleplugins/tracker/feature/placeholderapi/PlaceholderApiFeature.java new file mode 100644 index 0000000..40198a8 --- /dev/null +++ b/src/main/java/org/battleplugins/tracker/feature/placeholderapi/PlaceholderApiFeature.java @@ -0,0 +1,37 @@ +package org.battleplugins.tracker.feature.placeholderapi; + +import org.battleplugins.tracker.BattleTracker; +import org.battleplugins.tracker.feature.Feature; +import org.bukkit.Bukkit; + +public class PlaceholderApiFeature implements Feature { + private final boolean enabled; + + private BattleTrackerExpansion expansion; + + public PlaceholderApiFeature() { + this.enabled = Bukkit.getServer().getPluginManager().getPlugin("PlaceholderAPI") != null; + } + + @Override + public boolean enabled() { + return this.enabled; + } + + @Override + public void onEnable(BattleTracker battleTracker) { + if (!this.enabled) { + return; + } + + this.expansion = new BattleTrackerExpansion(battleTracker); + this.expansion.register(); + } + + @Override + public void onDisable(BattleTracker battleTracker) { + if (this.expansion != null) { + this.expansion.unregister(); + } + } +} diff --git a/src/main/java/org/battleplugins/tracker/util/Util.java b/src/main/java/org/battleplugins/tracker/util/Util.java index f295b5f..a60c804 100644 --- a/src/main/java/org/battleplugins/tracker/util/Util.java +++ b/src/main/java/org/battleplugins/tracker/util/Util.java @@ -21,6 +21,8 @@ public final class Util { public static final DecimalFormat HEALTH_FORMAT = new DecimalFormat("0.00"); public static final DecimalFormat DAMAGE_FORMAT = new DecimalFormat("#.##"); + public static final DecimalFormat STAT_FORMAT = new DecimalFormat("0.##"); + public static String formatHealth(double health, boolean loss) { return (loss ? "-" : "+") + HEALTH_FORMAT.format(health); } @@ -31,13 +33,12 @@ public static CompletableFuture> getSortedRecords(Tracker tra } public static void sendTrackerMessage(CommandSender sender, String messageKey, int ranking, Record record) { - DecimalFormat format = new DecimalFormat("0.##"); Map replacements = new HashMap<>(StatType.values() .stream() .map(stat -> new AbstractMap.SimpleEntry<>(stat, record.getStat(stat))) .collect( LinkedHashMap::new, - (map, entry) -> map.put(entry.getKey().getKey(), format.format(entry.getValue())), + (map, entry) -> map.put(entry.getKey().getKey(), STAT_FORMAT.format(entry.getValue())), Map::putAll ) );