Skip to content

Commit

Permalink
tax-account
Browse files Browse the repository at this point in the history
  • Loading branch information
angushushu committed Nov 15, 2023
1 parent e4f2ed2 commit 858c30c
Show file tree
Hide file tree
Showing 19 changed files with 123 additions and 125 deletions.
101 changes: 54 additions & 47 deletions src/main/java/org/cubexmc/ecobalancer/EcoBalancer.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.cubexmc.ecobalancer.commands.CheckAllCommand;
Expand All @@ -30,23 +32,26 @@

import java.util.zip.GZIPOutputStream;

import org.cubexmc.ecobalancer.listeners.AdminLoginListener;
import org.cubexmc.ecobalancer.metrics.Metrics;

public final class EcoBalancer extends JavaPlugin {

private static Economy econ = null;
private static Permission perms = null;
private static Chat chat = null;
private boolean deductBasedOnTime;
private int inactiveDaysToDeduct;
private TreeMap<Integer, Double> taxBrackets = new TreeMap<>();
private int inactiveDaysToClear;
private Logger fileLogger = Logger.getLogger("EcoBalancerFileLogger");
private FileHandler fileHandler;
private Logger fileLogger = Logger.getLogger("EcoBalancerFileLogger");
private String scheduleType;
private List<Integer> scheduleDaysOfWeek;
private List<Integer> scheduleDatesOfMonth;
private FileConfiguration langConfig;
private boolean taxAccount;
private String taxAccountName;
private String messagePrefix;

@Override
public void onEnable() {
Expand Down Expand Up @@ -77,9 +82,9 @@ public void onEnable() {
fileHandler = new FileHandler(getDataFolder() + File.separator + "logs" + File.separator + "latest.log", true);
fileHandler.setFormatter(new SimpleFormatter());
fileLogger.addHandler(fileHandler);
fileLogger.setUseParentHandlers(false); // 不将日志转发到父处理器,即不在控制台输出
fileLogger.setUseParentHandlers(false);
} catch (IOException e) {
getLogger().severe("Could not setup file logger for EcoBalancer");
getLogger().severe("Could not create the log file handler for EcoBalancer.");
e.printStackTrace();
}

Expand All @@ -89,18 +94,36 @@ public void onEnable() {
// Optional: Add custom charts
metrics.addCustomChart(new Metrics.SimplePie("chart_id", () -> "My value"));

// getCommand("ecobalancer").setExecutor(new UtilCommand(this));
// 创建虚拟账户
if (taxAccount && !econ.hasAccount(taxAccountName)) {
econ.createPlayerAccount(taxAccountName);
}

getServer().getPluginManager().registerEvents(new AdminLoginListener(this), this);
getCommand("ecobal").setExecutor(new UtilCommand(this));
getCommand("checkall").setExecutor(new CheckAllCommand(this));
getCommand("checkplayer").setExecutor(new CheckPlayerCommand(this));
getLogger().info("EcoBalancer enabled!");
}

public boolean useTaxAccount() {
return taxAccount;
}

public String getTaxAccountName() {
return taxAccountName;
}

public String getTaxAccountBalance() {
return String.format("%.2f", econ.getBalance(taxAccountName));
}

public void loadConfiguration() {
// Cancel all scheduled tasks
Bukkit.getScheduler().cancelTasks(this);
// load language config
loadLangFile();
messagePrefix = langConfig.getString("prefix", "&7[&6EcoBalancer&7]&r");
// Load the new scheduling configuration
scheduleType = getConfig().getString("schedule.type", "daily");
scheduleDaysOfWeek = getConfig().getIntegerList("schedule.days-of-week");
Expand All @@ -125,6 +148,8 @@ public void loadConfiguration() {
inactiveDaysToDeduct = getConfig().getInt("inactive-days-to-deduct", 50);
inactiveDaysToClear = getConfig().getInt("inactive-days-to-clear", 500);
List<Map<?, ?>> rawTaxBrackets = getConfig().getMapList("tax-brackets");
taxAccount = getConfig().getBoolean("tax-account", false);
taxAccountName = taxAccount ? getConfig().getString("tax-account-name", "tax") : null;

for (Map<?, ?> bracket : rawTaxBrackets) {
Integer threshold = bracket.get("threshold") == null ? Integer.MAX_VALUE : (Integer) bracket.get("threshold");
Expand All @@ -142,6 +167,10 @@ private void loadLangFile() {
}

public String getFormattedMessage(String path, Map<String, String> placeholders) {
if (placeholders == null) {
placeholders = new HashMap<>();
}
placeholders.put("prefix", messagePrefix);
String message = langConfig.getString(path, "Message not found!");
if (placeholders != null) {
for (Map.Entry<String, String> entry : placeholders.entrySet()) {
Expand Down Expand Up @@ -218,6 +247,8 @@ public void checkBalance(CommandSender sender, long currentTime, OfflinePlayer p
double balance = econ.hasAccount(player) ? econ.getBalance(player) : 0;
Double deductionRate = 0.0;

if (taxAccount && player.getName().equals(taxAccountName)) return;

Map.Entry<Integer, Double> entry = taxBrackets.higherEntry((int) balance);
if (entry != null) {
deductionRate = entry.getValue();
Expand All @@ -236,58 +267,44 @@ public void checkBalance(CommandSender sender, long currentTime, OfflinePlayer p
if (balance < 0.0) {
econ.depositPlayer(player, -1 * balance);
placeholders.put("new_balance", String.format("%.2f", econ.getBalance(player)));
if (sender != null) {
sender.sendMessage(getFormattedMessage("messages.set_balance.reason", placeholders));
sender.sendMessage(getFormattedMessage("messages.set_balance.balance_set", placeholders));
}
if (log)
fileLogger.info(getFormattedMessage("logs.negative_balance", placeholders));
} else if (deductionRate > 0.0) {

} else if (balance > 0.0) {
if (deductBasedOnTime) {
// 计算玩家离线天数
if (daysOffline > inactiveDaysToClear) {
// 清除超过inactiveDaysToClear天未上线的玩家
econ.withdrawPlayer(player, balance);
if (taxAccount) econ.depositPlayer(taxAccountName, balance); //
placeholders.put("new_balance", String.format("%.2f", econ.getBalance(player)));
if (sender != null) {
sender.sendMessage(getFormattedMessage("messages.offline_extreme.reason", placeholders));
sender.sendMessage(getFormattedMessage("messages.offline_extreme.balance_set", placeholders));
}
if (log)
fileLogger.info(getFormattedMessage("logs.offline_extreme", placeholders));
sendMessage(sender, "messages.offline_extreme", placeholders, log);
} else if (daysOffline > inactiveDaysToDeduct) {
// 对于超过50天未上线的玩家,按税率扣除
double deduction = min(balance, balance * deductionRate); // in case deductionRate is greater than 1
placeholders.put("deduction", String.format("%.2f", deduction));
econ.withdrawPlayer(player, deduction);
if (sender != null) {
sender.sendMessage(getFormattedMessage("messages.offline_moderate.reason", placeholders));
sender.sendMessage(getFormattedMessage("messages.offline_moderate.deduction_made", placeholders));
}
if (log)
fileLogger.info(getFormattedMessage("logs.offline_moderate", placeholders));
if (taxAccount) econ.depositPlayer(taxAccountName, deduction);
sendMessage(sender, "messages.offline_moderate", placeholders, log);
} else {
if (sender != null) {
sender.sendMessage(getFormattedMessage("messages.offline_active", placeholders));
}
sendMessage(sender, "messages.offline_active", placeholders, false);
}
} else {
double deduction = min(balance, balance * deductionRate); // in case deductionRate is greater than 1
placeholders.put("deduction", String.format("%.2f", deduction));
econ.withdrawPlayer(player, deduction);
if (sender != null)
sender.sendMessage(getFormattedMessage("messages.deduction_made", placeholders));
if (log)
fileLogger.info(getFormattedMessage("logs.deduction_made", placeholders));
if (taxAccount) econ.depositPlayer(taxAccountName, deduction);
sendMessage(sender, "messages.deduction_made", placeholders, log);
}
} else {
if (sender != null)
sender.sendMessage(getFormattedMessage("messages.zero_balance", placeholders));
if (log)
fileLogger.info(getFormattedMessage("logs.zero_balance", placeholders));
sendMessage(sender, "messages.zero_balance", placeholders, log);
}
}

private void sendMessage(CommandSender sender, String path, Map<String, String> placeholders, boolean isLog) {
String message = getFormattedMessage(path, placeholders);
if (sender != null) for (String str : message.split("\n")) sender.sendMessage(str);
if (isLog) for (String str : message.split("\n")) fileLogger.info(str);
}

private long calculateInitialDailyDelay(int hourOfDay, int minute) {
Calendar now = Calendar.getInstance();
Calendar nextCheck = (Calendar) now.clone();
Expand Down Expand Up @@ -408,25 +425,15 @@ public void run() {
placeholders.put("batch", Integer.toString(end - start));
placeholders.put("total_players", Integer.toString(players.length));

if (sender != null) {
// Send a message to the sender after each batch
Bukkit.getScheduler().runTask(EcoBalancer.this, () -> sender.sendMessage(getFormattedMessage("messages.players_processing", placeholders)));
} else {
getLogger().info(getFormattedMessage("logs.players_processed", placeholders));
}
sendMessage(sender, "messages.players_processing", placeholders, true);
if (index < players.length) {
// Schedule next batch
Bukkit.getScheduler().runTaskLaterAsynchronously(EcoBalancer.this, this, delay);
} else {
// All players have been processed, notify the sender
// Send a message to the sender after each batch
Bukkit.getScheduler().runTask(EcoBalancer.this, () -> {
if (sender != null) {
sender.sendMessage(getFormattedMessage("messages.all_players_processed", null));
} else {
getLogger().info(getFormattedMessage("logs.all_players_processed", null));
fileLogger.info(getFormattedMessage("logs.all_players_processed", null));
}
sendMessage(sender, "messages.all_players_processed", null, true);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public boolean onCommand(CommandSender sender, Command command, String s, String
}
}


return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
plugin.getFormattedMessage("messages.commands.reload", null),
plugin.getFormattedMessage("messages.help_footer", null)
};
sender.sendMessage(String.join("\n", commandMessages));
for (String str : commandMessages) sender.sendMessage(str);
return true;
}
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.cubexmc.ecobalancer.listeners;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.cubexmc.ecobalancer.EcoBalancer;

import java.util.HashMap;
import java.util.Map;

public class AdminLoginListener implements Listener {
EcoBalancer plugin;
public AdminLoginListener(EcoBalancer plugin) {
this.plugin = plugin;
}
@EventHandler
public void onAdminLogin(PlayerJoinEvent event) {
Player player = event.getPlayer();
if (player.hasPermission("ecobalance.admin")) {
if (plugin.useTaxAccount()) {
Map<String, String> placeholders = new HashMap<>();
placeholders.put("tax_account_name", plugin.getTaxAccountName());
placeholders.put("tax_account_balance", plugin.getTaxAccountBalance());
player.sendMessage(plugin.getFormattedMessage("messages.tax_account_enabled", placeholders));
} else {
player.sendMessage(plugin.getFormattedMessage("messages.tax_account_disabled", null));
}
}
}
}
4 changes: 3 additions & 1 deletion src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ tax-brackets:
- threshold: 1000000
rate: 0.01 # 税率 # Tax rate
- threshold: null # 无上限 # No limit
rate: 0.02 # 税率 # Tax rate
rate: 0.02 # 税率 # Tax rate
tax-account: true # 是否使用税金账户 # Whether to use tax account
tax-account-name: 'tax' # 税金账户名称 # Tax account name
27 changes: 8 additions & 19 deletions src/main/resources/lang.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
prefix: '&7[&6EcoBalancer&7]&r'
messages:
# reload
reload_success: '&a配置文件已成功重载。'
reload_success: '%prefix% &a配置文件已成功重载。'
# help
commands:
help: '&e/ecobal help &f- 帮助'
Expand All @@ -14,28 +15,16 @@ messages:
scanning_offline_players: '&a正在扫描离线玩家...'
enter_player_name_or_use_checkall: '&a请输入玩家名称或使用/checkall'
# ecobal
set_balance:
reason: "&e玩家 &6%player% &e的余额为 &6%balance%&e。"
balance_set: "&e已将余额置为 &6%new_balance%&e。"
offline_extreme:
reason: "&e玩家 &6%player% &e已经离线 &6%days_offline% &e天,极不活跃。"
balance_set: "&e已将余额置为 &6%new_balance%&e。"
offline_moderate:
reason: "&e玩家 &6%player% &e已经离线 &6%days_offline% &e天,较不活跃。"
deduction_made: "&e已从余额中扣除 &6%deduction%&e。"
negative_balance: "&e玩家 &6%player% &e的余额为 &6%balance%&e。\n&e已将余额置为 &6%new_balance%&e。"
offline_extreme: "&e玩家 &6%player% &e已经离线 &6%days_offline% &e天,极不活跃。\n&e已将余额置为 &6%new_balance%&e。"
offline_moderate: "&e玩家 &6%player% &e已经离线 &6%days_offline% &e天,较不活跃。\n&e已从余额中扣除 &6%deduction%&e。"
offline_active: "&e玩家 &6%player% &e仅离线 &6%days_offline% &e天,较活跃。"
deduction_made: "&e已从 &6%player% &e的余额中扣除 &6%deduction%&e。"
players_processing: "&7处理了 &6%batch% &7个玩家,共处理:&6%end%"
players_processed: "&7共&6%end% &7个玩家,处理总数:&6%end%"
all_players_processed: "&a所有玩家都已被洗劫。"
zero_balance: "&e玩家 &6%player% &e的余额为 &60&e。"
player_not_found: "&c没找到该玩家 (大小写敏感)。"
logs:
negative_balance: "[负额度] 已将 %player% 的余额置为%balance%。"
offline_extreme: "[及不活跃] 已将 %player% 的余额置为%new_balance%。"
offline_moderate: "[较不活跃] 已从 %player% 的余额中扣除 %deduction%。"
deduction_made: "已从 %player% 的余额中扣除 %deduction%。"
players_processed: "处理了 %start% 个玩家,共处理:%end%"
all_players_processed: "所有玩家都已被洗劫。"
batch_processed: "处理了 %total_players% 个玩家,共处理:%end%"
zero_balance: "&e玩家 &6%player% &e的余额为 &60&e。"
# taxaccount
tax_account_enabled: "&e税金账户已启用。\n&e税金账户名称为 &6%tax_account_name%&e。\n&e税金账户余额为 &6%tax_account_balance%&e。"
tax_account_disabled: "&e税金账户未启用。"
25 changes: 7 additions & 18 deletions src/main/resources/lang_en.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# to use English version, you need to rename this file to lang.yml
prefix: '&7[&6EcoBalancer&7]&r'
messages:
# reload
reload_success: '&aConfig file reloaded successfully.'
Expand All @@ -15,28 +16,16 @@ messages:
scanning_offline_players: '&aScanning offline players...'
enter_player_name_or_use_checkall: '&aPlease enter player name or use /checkall'
# ecobal
set_balance:
reason: "&ePlayer &6%player% &e's balance is &6%balance%&e."
balance_set: "&eBalance has been set to &6%new_balance%&e."
offline_extreme:
reason: "&ePlayer &6%player% &ehas been offline for &6%days_offline% &edays, extremely inactive."
balance_set: "&eBalance has been set to &6%new_balance%&e."
offline_moderate:
reason: "&ePlayer &6%player% &ehas been offline for &6%days_offline% &edays, moderately inactive."
deduction_made: "&e&6%deduction% &ehas been deducted from the balance."
set_balance: "&ePlayer &6%player% &e's balance is &6%balance%&e.\n&eBalance has been set to &6%new_balance%&e."
offline_extreme: "&ePlayer &6%player% &ehas been offline for &6%days_offline% &edays, extremely inactive.\n&eBalance has been set to &6%new_balance%&e."
offline_moderate: "&ePlayer &6%player% &ehas been offline for &6%days_offline% &edays, moderately inactive.\n&e&6%deduction% &ehas been deducted from the balance."
offline_active: "&ePlayer &6%player% &ehas only been offline &6%days_offline% &edays, moderately active."
deduction_made: "&e&6%deduction% &ehas been deducted from &6%player%&e's balance."
players_processing: "&7Processed &6%batch% &7players, total processed: &6%end%"
players_processed: "&7Total &6%end% &7players, total processed: &6%end%"
all_players_processed: "&aAll players have been cleaned."
zero_balance: "&ePlayer &6%player% &e's balance is &60&e."
player_not_found: "&cPlayer not found (case sensitive)."
logs:
negative_balance: "[Negative Balance] Set %player%'s balance to %balance%."
offline_extreme: "[Extremely Inactive] Set %player%'s balance to %new_balance%."
offline_moderate: "[Moderately Inactive] Deducted %deduction% from %player%'s balance."
deduction_made: "Deducted %deduction% from %player%'s balance."
players_processed: "Processed %start% players, total processed: %end%"
all_players_processed: "All players have been cleaned."
batch_processed: "Processed %total_players% players, total processed: %end%"
zero_balance: "&ePlayer &6%player% &e's balance is &60&e."
# taxaccount
tax_account_enabled: "&eTax account enabled.\n&eTax account name is &6%tax_account_name%&e.\n&eTax account balance is &6%tax_account_balance%&e."
tax_account_disabled: "&eTax account disabled."
Binary file not shown.
4 changes: 3 additions & 1 deletion target/classes/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ tax-brackets:
- threshold: 1000000
rate: 0.01 # 税率 # Tax rate
- threshold: null # 无上限 # No limit
rate: 0.02 # 税率 # Tax rate
rate: 0.02 # 税率 # Tax rate
tax-account: true # 是否使用税金账户 # Whether to use tax account
tax-account-name: 'tax' # 税金账户名称 # Tax account name
Loading

0 comments on commit 858c30c

Please sign in to comment.