193 lines
5.9 KiB
Java
193 lines
5.9 KiB
Java
package com.craftbank.hooks;
|
|
|
|
import com.craftbank.CraftBank;
|
|
import com.craftbank.model.PlayerAccount;
|
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
|
import org.bukkit.ChatColor;
|
|
import org.bukkit.OfflinePlayer;
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.RoundingMode;
|
|
import java.text.DecimalFormat;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.concurrent.CopyOnWriteArrayList;
|
|
|
|
/**
|
|
* XConomy PlaceholderAPI 兼容层, 让原有 %xconomy_*% 变量无需替换即可使用。
|
|
*/
|
|
public final class XConomyExpansion extends PlaceholderExpansion {
|
|
|
|
private static final int RANKING_SIZE = 100;
|
|
|
|
private final CraftBank plugin;
|
|
private final DecimalFormat numberFormat = new DecimalFormat("#,##0.00");
|
|
private final List<Map.Entry<String, Double>> top = new CopyOnWriteArrayList<>();
|
|
private volatile double sumBalance;
|
|
|
|
public XConomyExpansion(CraftBank plugin) {
|
|
this.plugin = plugin;
|
|
}
|
|
|
|
@Override
|
|
public @NotNull String getIdentifier() {
|
|
return "xconomy";
|
|
}
|
|
|
|
@Override
|
|
public @NotNull String getAuthor() {
|
|
return "CraftBank";
|
|
}
|
|
|
|
@Override
|
|
public @NotNull String getVersion() {
|
|
return plugin.getDescription().getVersion();
|
|
}
|
|
|
|
@Override
|
|
public boolean persist() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
|
|
String id = identifier.toLowerCase();
|
|
|
|
if (id.equals("balance") || id.equals("balance_value") || id.equals("balance_formatted")) {
|
|
double cash = getCash(player);
|
|
return switch (id) {
|
|
case "balance_value" -> decimal(cash);
|
|
case "balance_formatted" -> formatCompact(cash);
|
|
default -> formatDisplay(cash);
|
|
};
|
|
}
|
|
|
|
if (id.startsWith("top_player_")) {
|
|
Integer index = parseIndex(id, "top_player_");
|
|
if (index == null) {
|
|
return "[XConomy]Invalid index";
|
|
}
|
|
return topName(index);
|
|
}
|
|
|
|
if (id.equals("top_rank") || id.startsWith("top_rank_")) {
|
|
String name = id.equals("top_rank") ? (player == null ? null : player.getName())
|
|
: identifier.substring("top_rank_".length());
|
|
return rankOf(name);
|
|
}
|
|
|
|
if (id.startsWith("top_balance_formatted_")) {
|
|
Integer index = parseIndex(id, "top_balance_formatted_");
|
|
return index == null ? "[XConomy]Invalid index" : topBalance(index, true, false);
|
|
}
|
|
|
|
if (id.startsWith("top_balance_value_")) {
|
|
Integer index = parseIndex(id, "top_balance_value_");
|
|
return index == null ? "[XConomy]Invalid index" : topBalance(index, false, true);
|
|
}
|
|
|
|
if (id.startsWith("top_balance_")) {
|
|
Integer index = parseIndex(id, "top_balance_");
|
|
return index == null ? "[XConomy]Invalid index" : topBalance(index, false, false);
|
|
}
|
|
|
|
if (id.contains("top_hidden")) {
|
|
return "0";
|
|
}
|
|
|
|
if (id.contains("paypermission")) {
|
|
if (id.contains("_global")) {
|
|
return "1";
|
|
}
|
|
return player == null ? "Error" : "DEFAULT";
|
|
}
|
|
|
|
if (id.equals("paytoggle")) {
|
|
return player == null ? "Error" : "1";
|
|
}
|
|
|
|
if (id.contains("sum_balance")) {
|
|
return id.contains("sum_balance_value") ? decimal(sumBalance) : formatDisplay(sumBalance);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void refreshCache() {
|
|
top.clear();
|
|
top.addAll(plugin.getDatabaseManager().getTopCash(RANKING_SIZE));
|
|
sumBalance = plugin.getDatabaseManager().getTotalCash();
|
|
}
|
|
|
|
private double getCash(OfflinePlayer player) {
|
|
if (player == null) {
|
|
return 0.0;
|
|
}
|
|
PlayerAccount account = plugin.getEconomyManager().getCached(player.getUniqueId());
|
|
return account == null ? 0.0 : account.getCash();
|
|
}
|
|
|
|
private String topName(int oneBasedIndex) {
|
|
if (oneBasedIndex > top.size()) {
|
|
return "No data";
|
|
}
|
|
return top.get(oneBasedIndex - 1).getKey();
|
|
}
|
|
|
|
private String topBalance(int oneBasedIndex, boolean compact, boolean raw) {
|
|
if (oneBasedIndex > top.size()) {
|
|
return "No data";
|
|
}
|
|
double balance = top.get(oneBasedIndex - 1).getValue();
|
|
if (raw) {
|
|
return decimal(balance);
|
|
}
|
|
return compact ? formatCompact(balance) : formatDisplay(balance);
|
|
}
|
|
|
|
private String rankOf(String name) {
|
|
if (name == null) {
|
|
return "No data";
|
|
}
|
|
for (int i = 0; i < top.size(); i++) {
|
|
if (name.equalsIgnoreCase(top.get(i).getKey())) {
|
|
return Integer.toString(i + 1);
|
|
}
|
|
}
|
|
return "No data";
|
|
}
|
|
|
|
private Integer parseIndex(String id, String prefix) {
|
|
String value = id.substring(prefix.length());
|
|
if (!value.matches("\\d+") || value.matches("0+")) {
|
|
return null;
|
|
}
|
|
return Integer.parseInt(value);
|
|
}
|
|
|
|
private String formatDisplay(double amount) {
|
|
return ChatColor.translateAlternateColorCodes('&', numberFormat.format(amount) + " "
|
|
+ (round(amount).compareTo(BigDecimal.ONE) == 0 ? "dollar" : "dollars"));
|
|
}
|
|
|
|
private String formatCompact(double amount) {
|
|
double abs = Math.abs(amount);
|
|
if (abs >= 1_000_000.0) {
|
|
return numberFormat.format(amount / 1_000_000.0) + "m dollars";
|
|
}
|
|
if (abs >= 1_000.0) {
|
|
return numberFormat.format(amount / 1_000.0) + "k dollars";
|
|
}
|
|
return formatDisplay(amount);
|
|
}
|
|
|
|
private String decimal(double amount) {
|
|
return round(amount).toString();
|
|
}
|
|
|
|
private BigDecimal round(double amount) {
|
|
return BigDecimal.valueOf(amount).setScale(2, RoundingMode.DOWN);
|
|
}
|
|
}
|