d5bc819684
Adds configurable fees, transaction history, chat amount input, and v1.1.0 release documentation.
230 lines
9.3 KiB
Java
230 lines
9.3 KiB
Java
package com.craftbank.commands;
|
|
|
|
import com.craftbank.CraftBank;
|
|
import com.craftbank.economy.EconomyManager;
|
|
import com.craftbank.util.Amounts;
|
|
import com.craftbank.util.Msg;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.OfflinePlayer;
|
|
import org.bukkit.command.Command;
|
|
import org.bukkit.command.CommandSender;
|
|
import org.bukkit.command.TabExecutor;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.UUID;
|
|
|
|
/**
|
|
* /bankadmin <reload|give|take|set|setinterest> —— 管理员指令。
|
|
*/
|
|
public final class BankAdminCommand implements TabExecutor {
|
|
|
|
private final CraftBank plugin;
|
|
private final Msg msg;
|
|
|
|
public BankAdminCommand(CraftBank plugin) {
|
|
this.plugin = plugin;
|
|
this.msg = new Msg(plugin);
|
|
}
|
|
|
|
@Override
|
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
|
if (!sender.hasPermission("craftbank.admin")) {
|
|
msg.key(sender, "no-permission", "&c你没有权限执行该操作。");
|
|
return true;
|
|
}
|
|
if (args.length == 0) {
|
|
sendHelp(sender);
|
|
return true;
|
|
}
|
|
|
|
switch (args[0].toLowerCase()) {
|
|
case "reload" -> {
|
|
plugin.reloadConfig();
|
|
plugin.getEconomyManager().reload();
|
|
msg.key(sender, "reload-success", "&a配置文件已重载。");
|
|
}
|
|
case "give" -> modify(sender, args, ModifyType.GIVE);
|
|
case "take" -> modify(sender, args, ModifyType.TAKE);
|
|
case "set" -> modify(sender, args, ModifyType.SET);
|
|
case "setinterest" -> setInterest(sender, args);
|
|
case "log" -> queryLog(sender, args);
|
|
default -> sendHelp(sender);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private enum ModifyType {
|
|
GIVE, TAKE, SET
|
|
}
|
|
|
|
private void modify(CommandSender sender, String[] args, ModifyType type) {
|
|
if (args.length < 3) {
|
|
msg.raw(sender, "&c用法: /bankadmin " + type.name().toLowerCase() + " <玩家> <金额>");
|
|
return;
|
|
}
|
|
double amount = Amounts.parse(args[2]);
|
|
if (amount < 0 || (type != ModifyType.SET && amount <= 0)) {
|
|
msg.key(sender, "invalid-amount", "&c请输入一个有效的正数金额。");
|
|
return;
|
|
}
|
|
String targetName = args[1];
|
|
EconomyManager econ = plugin.getEconomyManager();
|
|
|
|
plugin.runAsync(() -> {
|
|
@SuppressWarnings("deprecation")
|
|
OfflinePlayer target = Bukkit.getOfflinePlayer(targetName);
|
|
UUID uuid = target.getUniqueId();
|
|
if (uuid == null || (!target.hasPlayedBefore() && !target.isOnline())) {
|
|
msg.key(sender, "player-not-found", "&c找不到目标玩家。");
|
|
return;
|
|
}
|
|
econ.loadBlocking(uuid, target.getName(), true);
|
|
boolean ok;
|
|
switch (type) {
|
|
case GIVE -> ok = econ.deposit(uuid, amount);
|
|
case TAKE -> ok = econ.withdraw(uuid, amount);
|
|
case SET -> ok = econ.set(uuid, amount);
|
|
default -> ok = false;
|
|
}
|
|
if (!ok) {
|
|
msg.raw(sender, "&c操作失败 (可能是余额不足)。");
|
|
return;
|
|
}
|
|
com.craftbank.model.Transaction.Type txType = switch (type) {
|
|
case GIVE -> com.craftbank.model.Transaction.Type.ADMIN_GIVE;
|
|
case TAKE -> com.craftbank.model.Transaction.Type.ADMIN_TAKE;
|
|
case SET -> com.craftbank.model.Transaction.Type.ADMIN_SET;
|
|
};
|
|
plugin.getTransactionLog().record(uuid, txType, amount,
|
|
"管理员 " + sender.getName() + " 操作");
|
|
msg.raw(sender, "&a已" + label(type) + " &f" + targetName + " &a现金 " + econ.format(amount)
|
|
+ " &7(当前: " + econ.format(econ.getCash(uuid)) + ")");
|
|
});
|
|
}
|
|
|
|
private String label(ModifyType type) {
|
|
return switch (type) {
|
|
case GIVE -> "给予";
|
|
case TAKE -> "扣除";
|
|
case SET -> "设置";
|
|
};
|
|
}
|
|
|
|
private void setInterest(CommandSender sender, String[] args) {
|
|
if (args.length < 3) {
|
|
msg.raw(sender, "&c用法: /bankadmin setinterest <savings|term_7d|term_15d|term_30d> <利率>");
|
|
return;
|
|
}
|
|
String key = args[1].toLowerCase();
|
|
List<String> valid = List.of("savings", "term_7d", "term_15d", "term_30d");
|
|
if (!valid.contains(key)) {
|
|
msg.raw(sender, "&c利率类型无效, 可选: " + String.join(", ", valid));
|
|
return;
|
|
}
|
|
double rate;
|
|
try {
|
|
rate = Double.parseDouble(args[2]);
|
|
} catch (NumberFormatException ex) {
|
|
msg.raw(sender, "&c请输入一个有效的利率 (例如 0.005)。");
|
|
return;
|
|
}
|
|
if (!Double.isFinite(rate) || rate < 0) {
|
|
msg.raw(sender, "&c利率必须为非负数。");
|
|
return;
|
|
}
|
|
plugin.getConfig().set("Interest_Rates." + key, rate);
|
|
plugin.saveConfig();
|
|
msg.raw(sender, "&a已将 &f" + key + " &a的日利率设置为 &e" + rate + " &7(" + (rate * 100) + "%)");
|
|
}
|
|
|
|
private void queryLog(CommandSender sender, String[] args) {
|
|
if (args.length < 2) {
|
|
msg.raw(sender, "&c用法: /bankadmin log <玩家> [页码]");
|
|
return;
|
|
}
|
|
String targetName = args[1];
|
|
int page = 1;
|
|
if (args.length >= 3) {
|
|
try {
|
|
page = Math.max(1, Integer.parseInt(args[2]));
|
|
} catch (NumberFormatException ignored) {
|
|
page = 1;
|
|
}
|
|
}
|
|
final int finalPage = page;
|
|
final int pageSize = 10;
|
|
|
|
plugin.runAsync(() -> {
|
|
@SuppressWarnings("deprecation")
|
|
OfflinePlayer target = Bukkit.getOfflinePlayer(targetName);
|
|
UUID uuid = target.getUniqueId();
|
|
if (uuid == null || (!target.hasPlayedBefore() && !target.isOnline())) {
|
|
msg.key(sender, "player-not-found", "&c找不到目标玩家。");
|
|
return;
|
|
}
|
|
var list = plugin.getTransactionLog().query(uuid, finalPage, pageSize);
|
|
if (list.isEmpty()) {
|
|
msg.raw(sender, "&7" + targetName + " 在第 " + finalPage + " 页没有交易记录。");
|
|
return;
|
|
}
|
|
EconomyManager econ = plugin.getEconomyManager();
|
|
java.text.SimpleDateFormat fmt = new java.text.SimpleDateFormat("MM-dd HH:mm");
|
|
msg.raw(sender, "&b&l" + targetName + " 的交易流水 &7- 第 " + finalPage + " 页");
|
|
for (var tx : list) {
|
|
String feePart = tx.getFee() > 0 ? " &8(费 " + econ.format(tx.getFee()) + ")" : "";
|
|
sender.sendMessage(com.craftbank.util.Text.color(
|
|
"&7[" + fmt.format(new java.util.Date(tx.getTimestamp())) + "] &f"
|
|
+ typeLabel(tx.getType()) + " &a" + econ.format(tx.getAmount())
|
|
+ feePart + " &8" + (tx.getDescription() == null ? "" : tx.getDescription())));
|
|
}
|
|
});
|
|
}
|
|
|
|
private String typeLabel(com.craftbank.model.Transaction.Type type) {
|
|
return switch (type) {
|
|
case PAY_OUT -> "转出";
|
|
case PAY_IN -> "转入";
|
|
case DEPOSIT -> "存活期";
|
|
case WITHDRAW -> "取活期";
|
|
case CHEQUE_ISSUE -> "开支票";
|
|
case CHEQUE_REDEEM -> "兑支票";
|
|
case TERM_CREATE -> "存定期";
|
|
case TERM_CLAIM -> "领定期";
|
|
case INTEREST -> "利息";
|
|
case ADMIN_GIVE -> "管理给予";
|
|
case ADMIN_TAKE -> "管理扣除";
|
|
case ADMIN_SET -> "管理设置";
|
|
};
|
|
}
|
|
|
|
private void sendHelp(CommandSender sender) {
|
|
msg.raw(sender, "&b&l工艺银行管理 &7指令帮助:");
|
|
sender.sendMessage(com.craftbank.util.Text.color("&7/bankadmin reload"));
|
|
sender.sendMessage(com.craftbank.util.Text.color("&7/bankadmin give <玩家> <金额>"));
|
|
sender.sendMessage(com.craftbank.util.Text.color("&7/bankadmin take <玩家> <金额>"));
|
|
sender.sendMessage(com.craftbank.util.Text.color("&7/bankadmin set <玩家> <金额>"));
|
|
sender.sendMessage(com.craftbank.util.Text.color("&7/bankadmin setinterest <类型> <利率>"));
|
|
sender.sendMessage(com.craftbank.util.Text.color("&7/bankadmin log <玩家> [页码]"));
|
|
}
|
|
|
|
@Override
|
|
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
|
if (!sender.hasPermission("craftbank.admin")) {
|
|
return List.of();
|
|
}
|
|
if (args.length == 1) {
|
|
List<String> base = new ArrayList<>(List.of("reload", "give", "take", "set", "setinterest", "log"));
|
|
base.removeIf(s -> !s.startsWith(args[0].toLowerCase()));
|
|
return base;
|
|
}
|
|
if (args.length == 2 && args[0].equalsIgnoreCase("setinterest")) {
|
|
return new ArrayList<>(List.of("savings", "term_7d", "term_15d", "term_30d"));
|
|
}
|
|
if (args.length == 2 && List.of("give", "take", "set", "log").contains(args[0].toLowerCase())) {
|
|
return null; // 在线玩家名
|
|
}
|
|
return List.of();
|
|
}
|
|
}
|