v1.2 update

This commit is contained in:
NotAlexNoyle committed 2026-04-22 11:38:58 -04:00
1 parent 67d9de29fb
commit d98aee4d64
21 files changed
+102 -96

No files matched your search

+10
View File
@@ -1,5 +1,15 @@
# Changelog
## 1.2
- Unified bounty head formatting across item names, armor stand labels, and action bar messaging into a single canonical line showing victim, slayer, and diamond reward.
- Removed redundant bounty head lore now that the item display name carries full claim information.
- `/bounty check` now resolves offline players who still have active bounties, and tab completion suggests their names.
- Bounty check output now formats the amount through the DiamondBank shards-to-diamonds formatter for consistency with head labels and announcements.
- Bounty leaderboard GUI now reads the beheading chance from the `bounty-head-drop-chance` config value instead of hardcoding 50%.
- Added the missing `playerbountiesog.command.admin.bounty.get` permission entry and Italian translation listing; removed dead `death.announce-claimed` lang key.
- Replaced raw stack traces in the bounty data manager with logger output and pruned dead plugin-discovery code from plugin startup.
## 1.1
- Added bounty amounts to bounty head item titles so the selected hotbar item text shows the reward without using the action bar.
+3 -1
View File
@@ -15,8 +15,9 @@ PlayerBounties-OG is a hard fork of [PlayerBountiesPlus](https://github.com/Tech
## Commands
- `/bounty set <player> <amount>` – set a bounty on a player
- `/bounty add <player> <amount>` – add diamonds to an existing bounty
- `/bounty top` – list the top bounties
- `/bounty check <player>` – check a player's bounty
- `/bounty check <player>` – check a player's bounty (online or offline)
- `/pbp reload` – reload configuration and messages
- `/pbp version` – display plugin version
- `/pbp bounty set <player> <amount>` – admin set a bounty
@@ -30,6 +31,7 @@ PlayerBounties-OG is a hard fork of [PlayerBountiesPlus](https://github.com/Tech
| --- | --- |
| `playerbountiesog.command.bounty` | all |
| `playerbountiesog.command.bounty.set` | all |
| `playerbountiesog.command.bounty.add` | all |
| `playerbountiesog.event.claim` | all |
| `playerbountiesog.command.admin` | op |
| `playerbountiesog.command.admin.version` | op |
@@ -1,18 +1,14 @@
package com.tcoded.playerbountiesplus;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.event.HandlerList;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.ServicesManager;
import org.bukkit.plugin.java.JavaPlugin;
import com.google.common.collect.ImmutableList;
import com.tcoded.playerbountiesplus.command.BountyCommand;
import com.tcoded.playerbountiesplus.command.PlayerBountiesPlusAdminCmd;
import com.tcoded.playerbountiesplus.hook.currency.DiamondBankOGHook;
@@ -175,16 +171,6 @@ public final class PlayerBountiesOG extends JavaPlugin {
this.getServer().getPluginManager().registerEvents(this.bountyIncreasePromptListener, this);
this.getServer().getPluginManager().registerEvents(new GuiProtectionListener(this), this);
final List<Plugin> plugins = ImmutableList.copyOf(this.getServer().getPluginManager().getPlugins());
findPluginWithQuery(plugins, "team");
findPluginWithQuery(plugins, "teams");
findPluginWithQuery(plugins, "clan");
findPluginWithQuery(plugins, "clans");
findPluginWithQuery(plugins, "party", "voteparty");
findPluginWithQuery(plugins, "parties");
findPluginWithQuery(plugins, "guild");
findPluginWithQuery(plugins, "guilds");
}
public void reloadLang() {
@@ -268,48 +254,6 @@ public final class PlayerBountiesOG extends JavaPlugin {
}
// Utilities.
private static void findPluginWithQuery(List<Plugin> plugins, String pluginNameQuery, String... excludeStrings) {
final String firstPluginFound = plugins.stream().filter(p -> {
final String lowerName = StringUtils.lowerCase(p.getName());
// If the plugin name doesn't contain the query, skip.
if (!StringUtils.contains(lowerName, pluginNameQuery)) {
return false;
}
// If the plugin name contains any of the exclude strings, skip.
for (String excludeString : excludeStrings) {
if (StringUtils.contains(lowerName, excludeString)) {
return false;
}
}
return true;
}).findFirst().map(p -> {
final List<String> authors = p.getPluginMeta().getAuthors();
return p.getName() + " (" + (authors.isEmpty() ? "N/A" : authors.get(0)) + ")";
}).orElse(null);
if (firstPluginFound == null) {
return;
}
}
private void registerDefaultEcoHooks() {
final ServicesManager servicesManager = getServer().getServicesManager();
@@ -4,8 +4,11 @@ import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -43,36 +46,50 @@ public class BountyCheckCmd {
final String playerNameArg = args[1];
final Player target = plugin.getServer().getPlayerExact(playerNameArg);
final UUID targetUuid;
final String targetName;
if (target == null) {
final Player onlineTarget = plugin.getServer().getPlayerExact(playerNameArg);
if (onlineTarget != null) {
final String playerNotFoundMessage = plugin.getLang().getColored("command.bounty.check.player-not-found");
if (!(sender instanceof Player)) {
targetUuid = onlineTarget.getUniqueId();
targetName = onlineTarget.getName();
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), playerNotFoundMessage);
} else {
} else {
final OfflinePlayer offlineTarget = resolveOfflineTarget(playerNameArg);
if (offlineTarget == null) {
UtilitiesOG.trueogMessage((Player) sender, playerNotFoundMessage);
final String playerNotFoundMessage = plugin.getLang()
.getColored("command.bounty.check.player-not-found");
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), playerNotFoundMessage);
} else {
UtilitiesOG.trueogMessage((Player) sender, playerNotFoundMessage);
}
return true;
}
return true;
targetUuid = offlineTarget.getUniqueId();
targetName = StringUtils.defaultIfBlank(offlineTarget.getName(), playerNameArg);
}
final UUID playerUUID = target.getUniqueId();
final BountyDataManager bountyDataManager = plugin.getBountyDataManager();
final boolean hasBounty = bountyDataManager.hasBounty(playerUUID);
final boolean hasBounty = bountyDataManager.hasBounty(targetUuid);
if (hasBounty) {
// Confirmation.
final double bounty = bountyDataManager.getBounty(playerUUID);
final double bounty = bountyDataManager.getBounty(targetUuid);
final String formattedBounty = plugin.getBountyHeadFormatter().formatDiamonds(bounty) + " Diamonds";
final String bountyFoundMessage = plugin.getLang().getColored("command.bounty.check.bounty-found")
.replace("{target}", target.getName()).replace("{bounty}", Double.toString(bounty));
.replace("{target}", targetName).replace("{bounty}", formattedBounty);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), bountyFoundMessage);
@@ -86,7 +103,7 @@ public class BountyCheckCmd {
} else {
final String noBountyFoundMessage = plugin.getLang().getColored("command.bounty.check.no-bounty")
.replace("{target}", target.getName());
.replace("{target}", targetName);
if (!(sender instanceof Player)) {
UtilitiesOG.logToConsole(PlayerBountiesOG.getPrefix(), noBountyFoundMessage);
@@ -103,19 +120,46 @@ public class BountyCheckCmd {
}
@Nullable
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull String[] args) {
private static OfflinePlayer resolveOfflineTarget(String name) {
if (args.length == 2) {
for (OfflinePlayer candidate : Bukkit.getOfflinePlayers()) {
// Suggest online player names for the username.
return sender.getServer().getOnlinePlayers().stream().map(Player::getName)
.filter(name -> StringUtils.startsWith(StringUtils.lowerCase(name), StringUtils.lowerCase(args[1])))
.collect(Collectors.toList());
if (StringUtils.equalsIgnoreCase(candidate.getName(), name)) {
return candidate;
}
}
return Collections.emptyList();
@SuppressWarnings("deprecation")
final OfflinePlayer byName = Bukkit.getOfflinePlayerIfCached(name);
return byName;
}
@Nullable
public static List<String> onTabComplete(@NotNull CommandSender sender, @NotNull String[] args) {
if (args.length != 2) {
return Collections.emptyList();
}
final String prefix = StringUtils.lowerCase(args[1]);
final PlayerBountiesOG plugin = PlayerBountiesOG.getInstance();
final BountyDataManager bountyDataManager = plugin == null ? null : plugin.getBountyDataManager();
final Stream<String> onlineNames = sender.getServer().getOnlinePlayers().stream().map(Player::getName);
final Stream<String> offlineBountyNames = bountyDataManager == null ? Stream.empty()
: bountyDataManager.getBounties().keySet().stream().map(Bukkit::getOfflinePlayer)
.map(OfflinePlayer::getName).filter(name -> name != null && !name.isBlank());
return Stream.concat(onlineNames, offlineBountyNames).distinct()
.filter(name -> StringUtils.startsWith(StringUtils.lowerCase(name), prefix))
.collect(Collectors.toList());
}
@@ -253,8 +253,10 @@ public class MainBountyGui extends GUIBase {
lore.add(UtilitiesOG.trueogColorize("&7Click to increase this player's bounty."));
lore.add(UtilitiesOG.trueogColorize("&8You will be prompted in chat for the amount."));
lore.add(UtilitiesOG.trueogColorize(""));
lore.add(UtilitiesOG
.trueogColorize("&6Claiming the bounty will give you a 50% chance of beheading your victim!"));
final double dropChance = Math.max(0D,
Math.min(100D, plugin.getConfig().getDouble("bounty-head-drop-chance", 50D)));
lore.add(UtilitiesOG.trueogColorize("&6Claiming the bounty will give you a " + formatDropChance(dropChance)
+ "% chance of beheading your victim!"));
final GUIItem item;
if (entry.targetName() != null && !entry.targetName().isBlank()) {
@@ -335,6 +337,18 @@ public class MainBountyGui extends GUIBase {
}
private String formatDropChance(double chance) {
if (chance == Math.floor(chance)) {
return Long.toString((long) chance);
}
return StringUtils.stripEnd(StringUtils.stripEnd(String.format("%.2f", chance), "0"), ".");
}
private GUIItem createStaticItem(Material material, String displayName, List<TextComponent> lore) {
final GUIItem item = new GUIItem(material, 1, displayName);
@@ -6,6 +6,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
@@ -95,7 +96,8 @@ public class BountyDataManager {
} catch (IOException ioException) {
ioException.printStackTrace();
this.plugin.getLogger().log(Level.SEVERE,
"Failed to save bounties file: " + this.bountiesFile.getPath(), ioException);
}
+1
View File
@@ -10,6 +10,7 @@
# es_es - Spanish (Spain)
# hi_in - Hindi (India)
# hu_hu - Hungarian (Hungary)
# it_it - Italian (Italy)
# ru_ru - Russian (Russia)
# se_se - Swedish (Sweden)
# zh_cn - Chinese (China)
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aDer Spieler, den du getötet hast, hat eine aktive Belohnung, aber du bist im selben Team wie er!"
announce-claimed: "&4&l{killer} hat die Belohnung von {victim} im Wert von ${bounty} beansprucht"
no-permission: "&cSie dürfen keine Kopfgelder beanspruchen!"
command:
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aThe player you killed has an active bounty but you are in the same team as they are!"
announce-claimed: "&4&l{killer} claimed {victim}'s bounty worth ${bounty}"
no-permission: "&cYou are not allowed to claim bounties!"
command:
+1 -1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aThe player you killed has an active bounty but you are in the same team as they are!"
announce-claimed: "&4&l{killer} claimed {victim}'s bounty worth ${bounty}"
no-permission: "&cYou are not allowed to claim bounties!"
command:
@@ -49,6 +48,7 @@ command:
success: "&cYou placed a bounty of {bounty} on {target}'s head!"
announce: "\nA bounty of {bounty} was placed on {target}'s &ahead by&r {player}!{extra}\n"
announce-extra: " (Total: {total})"
cancelled: "&cBounty placement was cancelled."
add:
missing-args: "&cYou need to specify a player and an amount! /bounty add <player> <amount>"
amount-nan: "&cThat's not a valid number!"
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aDa pwayer you kiwwed has an active bounty but you awe in da same team as they awe!"
announce-claimed: "&4&w{killer} cwaimed {victim}'s bounty wowth ${bounty}"
no-permission: "&cYou awe nyot awwowed to cwaim bounties!"
command:
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aEl jugador que mataste tiene una recompensa activa pero estás en el mismo equipo que él."
announce-claimed: "&4&l{killer} reclamó la recompensa de {victim} valorada en ${bounty}"
no-permission: "&c¡No se le permite reclamar recompensas!"
command:
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aLe joueur que vous avez tué a une prime sur sa tête mais vous êtes dans la même équipe!"
announce-claimed: "&4&l{killer} a gagné la prime de {victim} au prix de ${bounty}"
no-permission: "&cVous n'êtes pas autorisé à réclamer des primes!"
command:
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aवह खिलाड़ी जिसे आपने मार डाला है, उसके पास एक सक्रिय इनाम है, लेकिन आप उनकी टीम में हैं!"
announce-claimed: "&4&l{killer} ने {victim} के इनाम {bounty} को मांग लिया"
no-permission: "&cआपको इनामों का दावा करने की अनुमति नहीं है!"
command:
-1
View File
@@ -4,7 +4,6 @@
death:
same-team: "&aA játékos, akit megöltél, aktív fejpénzt volt a fején, de ugyanabba a csapatba tartozol, mint ő!"
announce-claimed: "&4&l{killer} behajtotta {victim} fejpénzét és megkapta jutalmát aminek értéke: ${bounty}"
no-permission: "&cNem igényelheted a fejpénzeket!"
command:
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aIl giocatore che hai ucciso ha una taglia attiva, ma sei nella stessa squadra!"
announce-claimed: "&4&l{killer} ha reclamato la taglia di {victim} del valore di ${bounty}"
no-permission: "&cNon ti è permesso riscuotere le taglie!"
command:
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aDe speler die je hebt gedood heeft een actieve beloning, maar je zit in hetzelfde team als zij!"
announce-claimed: "&4&l{killer} heeft de beloning van {victim} ter waarde van ${bounty} geclaimd"
no-permission: "&cU mag geen premies claimen!"
command:
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aИгрок, которого вы убили, имеет активную награду, но вы находитесь в одной команде с ними!"
announce-claimed: "&4&l{killer} получил награду {victim} на сумму ${bounty}"
no-permission: "&cВам не разрешено требовать наград!"
command:
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&aDen spelare du dödade har en aktiv prissumma, men du tillhör samma lag som de är!"
announce-claimed: "&4&l{killer} har tagit {victim}s prissumma värd {bounty} dollar"
no-permission: "&cDu får inte hämta in prissummor!"
command:
-1
View File
@@ -1,6 +1,5 @@
death:
same-team: "&a你击杀的玩家有悬赏,但你与他们在同一队伍中!"
announce-claimed: "&4&l{killer} 已领取 {victim} 的悬赏,价值 ${bounty}"
no-permission: "&c你没有权限领取悬赏!"
command:
+1
View File
@@ -34,6 +34,7 @@ permissions:
playerbountiesog.command.admin.bounty.add: {}
playerbountiesog.command.admin.bounty.remove: {}
playerbountiesog.command.admin.bounty.delete: {}
playerbountiesog.command.admin.bounty.get: {}
playerbountiesog.command.bounty.set:
default: true
playerbountiesog.command.bounty.add: