Initial commit

This commit is contained in:
2021-09-10 22:52:05 +08:00
commit dd2ecca1a8
48 changed files with 3336 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/.gradle
/.idea
/build
*/build

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 叁只仓鼠
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

63
README.MD Normal file
View File

@@ -0,0 +1,63 @@
# HamsterCurrency
[![](https://jitpack.io/v/cn.hamster3/HamsterCurrency.svg)](https://jitpack.io/#cn.hamster3/HamsterCurrency)
仓鼠的多货币经济插件
# 依赖前置
- [HamsterAPI](https://github.com/MiniDay/HamsterAPI/releases)
- [HamsterService](https://github.com/MiniDay/HamsterService/releases) (仅跨服模式需要)
- [Vault](https://www.spigotmc.org/resources/vault.34315/) 仅开启Vault经济系统时需要
- [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) (非必须)
# 开发者
## 依赖导入
### Maven
添加仓库:
```xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
```
添加导入:
```xml
<dependency>
<groupId>cn.hamster3</groupId>
<artifactId>HamsterCurrency</artifactId>
<version>2.0.6-SNAPSHOT</version>
</dependency>
```
### Gradle
添加仓库:
```groovy
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
```
添加导入:
```groovy
dependencies {
implementation 'cn.hamster3:HamsterCurrency:1.3.7-SNAPSHOT'
}
```
## API
请参考[CurrencyAPI](/currency-plugin/src/main/java/cn/hamster3/currency/api/CurrencyAPI.java)

0
build.gradle Normal file
View File

View File

@@ -0,0 +1,42 @@
plugins {
id 'java'
}
group 'cn.hamster3'
version '2.0.6-SNAPSHOT'
repositories {
maven {
url = "https://maven.airgame.net/repository/maven-public/"
}
maven {
url = "https://repo.codemc.org/repository/maven-public"
}
}
dependencies {
compileOnly "org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT"
// https://mvnrepository.com/artifact/org.jetbrains/annotations
compileOnly group: 'org.jetbrains', name: 'annotations', version: '22.0.0'
compileOnly "cn.hamster3:HamsterService-Bukkit:2.6.2-SNAPSHOT"
compileOnly "cn.hamster3:HamsterAPI:2.4.0-SNAPSHOT"
compileOnly "com.github.MilkBowl:VaultAPI:1.7"
compileOnly "org.black_ixx:PlayerPoints:2.1.3"
compileOnly "me.clip:placeholderapi:2.10.9"
}
processResources {
filesMatching("plugin.yml") {
expand "version": project.version
}
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
jar {
archivesBaseName = "HamsterCurrency"
destinationDir(rootProject.buildDir)
}

View File

@@ -0,0 +1,159 @@
package cn.hamster3.currency;
import cn.hamster3.api.utils.LogUtils;
import cn.hamster3.currency.api.CurrencyAPI;
import cn.hamster3.currency.command.currency.CurrencyCommand;
import cn.hamster3.currency.command.vault.VaultCommand;
import cn.hamster3.currency.command.vault.VaultPayCommand;
import cn.hamster3.currency.command.vault.VaultSeeCommand;
import cn.hamster3.currency.command.vault.VaultTopCommand;
import cn.hamster3.currency.core.FileDataManager;
import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.SQLDataManager;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.hook.PlaceholderHook;
import cn.hamster3.currency.hook.VaultEconomyHook;
import cn.hamster3.currency.listener.CurrencyListener;
import cn.hamster3.currency.listener.SQLListener;
import cn.hamster3.service.bukkit.api.ServiceMessageAPI;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import java.sql.SQLException;
public final class HamsterCurrency extends JavaPlugin {
private static LogUtils logUtils;
private IDataManager dataManager;
private CurrencyListener listener;
private boolean loaded;
public static LogUtils getLogUtils() {
return logUtils;
}
@Override
public void onLoad() {
FileManager.reload(this);
logUtils = new LogUtils(this);
logUtils.infoDividingLine();
if (FileManager.isUseBC()) {
logUtils.info("使用多服务器模式...");
try {
SQLDataManager sqlDataManager = new SQLDataManager(this);
logUtils.info("SQL存档管理器初始化完成!");
listener = new SQLListener(this, sqlDataManager);
logUtils.info("事件监听器初始化完成!");
dataManager = sqlDataManager;
} catch (SQLException | ClassNotFoundException e) {
logUtils.error(e, "插件加载时遇到了一个错误: ");
loaded = false;
}
} else {
logUtils.info("使用单服务器模式...");
FileDataManager fileDataManager = new FileDataManager(this);
logUtils.info("文件存档管理器初始化完成!");
listener = new CurrencyListener(this, fileDataManager);
logUtils.info("事件监听器初始化完成!");
dataManager = fileDataManager;
}
CurrencyAPI.setDataManager(dataManager);
logUtils.info("API初始化完成!");
loaded = true;
logUtils.infoDividingLine();
}
@Override
public void onEnable() {
logUtils.infoDividingLine();
if (!loaded) {
logUtils.warning("插件未能成功启动!");
setEnabled(false);
return;
}
dataManager.loadConfig();
PluginCommand command = getCommand("HamsterCurrency");
new CurrencyCommand(command, dataManager);
logUtils.info("插件命令已注册!");
Bukkit.getPluginManager().registerEvents(listener, this);
logUtils.info("事件监听器已注册!");
registerVault();
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
dataManager.onEnable();
for (Player player : Bukkit.getOnlinePlayers()) {
dataManager.loadPlayerData(player.getUniqueId());
}
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
logUtils.info("检测到 PlaceholderAPI 已启动...");
new PlaceholderHook(dataManager).register();
logUtils.info("已挂载 PlaceholderAPI 变量!");
} else {
logUtils.info("未检测到 PlaceholderAPI!");
}
});
ServiceMessageAPI.subscribeTag("HamsterCurrency");
logUtils.info("插件已启动!");
logUtils.infoDividingLine();
}
private void registerVault() {
logUtils.infoDividingLine();
if (!FileManager.isVaultHook()) {
Bukkit.getServicesManager().unregister(this);
logUtils.info("不使用Vault经济系统挂接...");
return;
}
if (!Bukkit.getPluginManager().isPluginEnabled("Vault")) {
logUtils.warning("未找到 Vault 插件! 取消注册Vault经济系统...");
return;
}
String type = FileManager.getVaultCurrencyType();
logUtils.info("尝试以 %s 注册Vault经济系统...", type);
CurrencyType currencyType = dataManager.getCurrencyType(type);
if (currencyType == null) {
logUtils.warning("未找到经济类型 %s! 取消注册Vault经济系统...", type);
return;
}
VaultEconomyHook hook = new VaultEconomyHook(dataManager);
logUtils.info("已初始化Vault连接器...");
Bukkit.getServicesManager().register(Economy.class, hook, this, ServicePriority.Normal);
logUtils.info("Vault经济系统注册成功!");
new VaultPayCommand(getCommand("payMoney"), dataManager);
new VaultSeeCommand(getCommand("balance"), dataManager);
new VaultTopCommand(getCommand("balanceTop"), dataManager);
new VaultCommand(getCommand("economy"), dataManager);
logUtils.infoDividingLine();
}
@Override
public void onDisable() {
logUtils.infoDividingLine();
if (dataManager != null) {
dataManager.onDisable();
}
Bukkit.getServicesManager().unregister(this);
logUtils.info("插件已关闭!");
logUtils.infoDividingLine();
logUtils.close();
}
}

View File

@@ -0,0 +1,88 @@
package cn.hamster3.currency.api;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import org.black_ixx.playerpoints.PlayerPoints;
import org.bukkit.Bukkit;
import java.util.ArrayList;
import java.util.UUID;
/**
* 当 currencyID 为 PlayerPoints 且服务器安装了点券插件时,会自动更改为 PlayerPoints 接口
*/
@SuppressWarnings({"unused", "ConstantConditions"})
public abstract class CurrencyAPI {
private static IDataManager dataManager;
public static void setDataManager(IDataManager dataManager) {
CurrencyAPI.dataManager = dataManager;
}
public static double getPlayerCurrency(UUID uuid, String currencyID) {
if (currencyID.equals("PlayerPoints") && Bukkit.getPluginManager().isPluginEnabled("PlayerPoints")) {
return ((PlayerPoints) Bukkit.getPluginManager().getPlugin("PlayerPoints")).getAPI().look(uuid);
}
PlayerData data = dataManager.getPlayerData(uuid);
if (data == null) {
return 0;
}
return data.getPlayerCurrency(currencyID);
}
public static void setPlayerCurrency(UUID uuid, String currencyID, double amount) {
if (currencyID.equals("PlayerPoints") && Bukkit.getPluginManager().isPluginEnabled("PlayerPoints")) {
((PlayerPoints) Bukkit.getPluginManager().getPlugin("PlayerPoints")).getAPI().set(uuid, (int) amount);
return;
}
PlayerData data = dataManager.getPlayerData(uuid);
if (data == null) {
return;
}
data.setPlayerCurrency(currencyID, amount);
dataManager.savePlayerData(data);
}
public static void addPlayerCurrency(UUID uuid, String currencyID, double amount) {
if (currencyID.equals("PlayerPoints") && Bukkit.getPluginManager().isPluginEnabled("PlayerPoints")) {
((PlayerPoints) Bukkit.getPluginManager().getPlugin("PlayerPoints")).getAPI().give(uuid, (int) amount);
return;
}
PlayerData data = dataManager.getPlayerData(uuid);
if (data == null) {
return;
}
data.setPlayerCurrency(currencyID, data.getPlayerCurrency(currencyID) + amount);
dataManager.savePlayerData(data);
}
public static void takePlayerCurrency(UUID uuid, String currencyID, double amount) {
if (currencyID.equals("PlayerPoints") && Bukkit.getPluginManager().isPluginEnabled("PlayerPoints")) {
((PlayerPoints) Bukkit.getPluginManager().getPlugin("PlayerPoints")).getAPI().take(uuid, (int) amount);
return;
}
PlayerData data = dataManager.getPlayerData(uuid);
if (data == null) {
return;
}
data.setPlayerCurrency(currencyID, data.getPlayerCurrency(currencyID) - amount);
dataManager.savePlayerData(data);
}
public static boolean hasPlayerCurrency(UUID uuid, String currencyID, double amount) {
if (currencyID.equals("PlayerPoints") && Bukkit.getPluginManager().isPluginEnabled("PlayerPoints")) {
return ((PlayerPoints) Bukkit.getPluginManager().getPlugin("PlayerPoints")).getAPI().look(uuid) >= amount;
}
PlayerData data = dataManager.getPlayerData(uuid);
if (data == null) {
return false;
}
return data.getPlayerCurrency(currencyID) >= amount;
}
public ArrayList<CurrencyType> getAllCurrencyType() {
return new ArrayList<>(dataManager.getCurrencyTypes());
}
}

View File

@@ -0,0 +1,34 @@
package cn.hamster3.currency.command;
import cn.hamster3.api.command.CommandExecutor;
import cn.hamster3.currency.core.IDataManager;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.List;
public class ReloadCommand extends CommandExecutor {
private final IDataManager dataManager;
public ReloadCommand(IDataManager dataManager) {
super("reload", "重载服务器");
this.dataManager = dataManager;
}
@Override
public boolean isPlayerCommand() {
return false;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
dataManager.reloadConfig();
sender.sendMessage("§a插件重载完成!");
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return null;
}
}

View File

@@ -0,0 +1,106 @@
package cn.hamster3.currency.command.currency;
import cn.hamster3.api.HamsterAPI;
import cn.hamster3.api.command.CommandExecutor;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.List;
import java.util.stream.Collectors;
public abstract class CurrencyAdminSetCommand extends CommandExecutor {
protected final IDataManager dataManager;
public CurrencyAdminSetCommand(IDataManager dataManager, String name, String description, String permission) {
super(
name,
description,
permission,
Message.notHasPermission.toString(),
new String[]{
"玩家",
"货币类型",
"数额"
}
);
this.dataManager = dataManager;
}
@Override
public boolean isPlayerCommand() {
return false;
}
@Override
public String getPermissionMessage() {
return Message.notHasPermission.toString();
}
protected abstract void doSet(PlayerData data, CurrencyType type, double amount);
@Override
@SuppressWarnings("DuplicatedCode")
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length < 2) {
sender.sendMessage(Message.notInputPlayerName.toString());
return true;
}
PlayerData data = dataManager.getPlayerData(args[1]);
if (data == null) {
sender.sendMessage(Message.playerNotFound.toString());
return true;
}
if (args.length < 3) {
sender.sendMessage(Message.notInputCurrencyType.toString());
return true;
}
CurrencyType type = dataManager.getCurrencyType(args[2]);
if (type == null) {
sender.sendMessage(Message.currencyTypeNotFound.toString());
return true;
}
if (args.length < 4) {
sender.sendMessage(Message.notInputAmount.toString());
return true;
}
double amount;
try {
amount = Double.parseDouble(args[3]);
} catch (NumberFormatException e) {
sender.sendMessage(Message.amountNumberError.toString());
return true;
}
doSet(data, type, amount);
sender.sendMessage(
Message.playerCurrencySetSuccess.toString()
.replace("%player%", data.getPlayerName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", data.getPlayerCurrency(type.getId())))
);
dataManager.savePlayerData(data);
return true;
}
@Override
@SuppressWarnings("DuplicatedCode")
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
switch (args.length) {
case 2: {
return HamsterAPI.getOnlinePlayersName(args[1]);
}
case 3: {
List<String> types = dataManager.getCurrencyTypes().stream().map(CurrencyType::getId).collect(Collectors.toList());
types = HamsterAPI.startWithIgnoreCase(types, args[2]);
if (types.size() > 10) {
types = types.subList(0, 9);
}
return types;
}
}
return null;
}
}

View File

@@ -0,0 +1,34 @@
package cn.hamster3.currency.command.currency;
import cn.hamster3.api.command.CommandManager;
import cn.hamster3.currency.command.ReloadCommand;
import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.SQLDataManager;
import org.bukkit.command.PluginCommand;
public class CurrencyCommand extends CommandManager {
public CurrencyCommand(PluginCommand command, IDataManager dataManager) {
super(command);
addCommandExecutor(
new CurrencyGiveCommand(dataManager),
new CurrencyPayCommand(dataManager),
new ReloadCommand(dataManager),
new CurrencySeeCommand(dataManager),
new CurrencySetCommand(dataManager),
new CurrencyTakeCommand(dataManager),
new CurrencyTopCommand(dataManager)
);
if (FileManager.isUseBC()) {
addCommandExecutor(new CurrencyImportCommand((SQLDataManager) dataManager));
}
command.setExecutor(this);
command.setTabCompleter(this);
}
@Override
public boolean isPlayerCommand() {
return false;
}
}

View File

@@ -0,0 +1,22 @@
package cn.hamster3.currency.command.currency;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
public class CurrencyGiveCommand extends CurrencyAdminSetCommand {
public CurrencyGiveCommand(IDataManager dataManager) {
super(
dataManager,
"give",
"为玩家货币添加余额",
"currency.give"
);
}
@Override
protected void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), data.getPlayerCurrency(type.getId()) + amount);
}
}

View File

@@ -0,0 +1,52 @@
package cn.hamster3.currency.command.currency;
import cn.hamster3.api.command.CommandExecutor;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.core.SQLDataManager;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.List;
public class CurrencyImportCommand extends CommandExecutor {
private final SQLDataManager dataManager;
public CurrencyImportCommand(SQLDataManager dataManager) {
super(
"import",
"从其他插件中导入数据",
"currency.import",
Message.notHasPermission.toString(),
new String[]{
"数据库",
"数据表",
"uuid列名",
"name列名",
"money列名",
"货币类型"
}
);
this.dataManager = dataManager;
}
@Override
public boolean isPlayerCommand() {
return false;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length < 7) {
sender.sendMessage("§a/currency import [数据库] [数据表] [uuid列名] [name列名] [money列名] [货币类型]");
return true;
}
dataManager.importFromOtherPluginData(args[1], args[2], args[3], args[4], args[5], args[6]);
sender.sendMessage("§a已开始从其他插件的数据库存档中导入数据, 详情请查看控制台输出...");
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return null;
}
}

View File

@@ -0,0 +1,141 @@
package cn.hamster3.currency.command.currency;
import cn.hamster3.api.HamsterAPI;
import cn.hamster3.api.command.CommandExecutor;
import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import cn.hamster3.service.bukkit.api.ServiceMessageAPI;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.stream.Collectors;
public class CurrencyPayCommand extends CommandExecutor {
private final IDataManager dataManager;
public CurrencyPayCommand(IDataManager dataManager) {
super(
"pay",
"向其他玩家转账",
"currency.pay",
Message.notHasPermission.toString(),
new String[]{
"玩家",
"货币类型",
"数额"
}
);
this.dataManager = dataManager;
}
@Override
public boolean isPlayerCommand() {
return true;
}
@Override
@SuppressWarnings("DuplicatedCode")
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length < 2) {
sender.sendMessage(Message.notInputPlayerName.toString());
return true;
}
PlayerData toData = dataManager.getPlayerData(args[1]);
if (toData == null) {
sender.sendMessage(Message.playerNotFound.toString());
return true;
}
if (args.length < 3) {
sender.sendMessage(Message.notInputCurrencyType.toString());
return true;
}
CurrencyType type = dataManager.getCurrencyType(args[2]);
if (type == null) {
sender.sendMessage(Message.currencyTypeNotFound.toString());
return true;
}
if (!type.isCanTransfer()) {
sender.sendMessage(Message.currencyTypeCantTransfer.toString().replace("%type%", type.getId()));
return true;
}
if (args.length < 4) {
sender.sendMessage(Message.notInputPayAmount.toString());
return true;
}
double amount;
try {
amount = Double.parseDouble(args[3]);
} catch (NumberFormatException e) {
sender.sendMessage(Message.amountNumberError.toString());
return true;
}
if (amount <= 0) {
sender.sendMessage(Message.amountNumberError.toString());
return true;
}
Player player = (Player) sender;
PlayerData fromData = dataManager.getPlayerData(player.getUniqueId());
if (fromData.getPlayerCurrency(type.getId()) < amount) {
sender.sendMessage(
Message.currencyNotEnough.toString()
.replace("%type%", type.getId())
);
return true;
}
fromData.setPlayerCurrency(type.getId(), fromData.getPlayerCurrency(type.getId()) - amount);
toData.setPlayerCurrency(type.getId(), toData.getPlayerCurrency(type.getId()) + amount);
dataManager.savePlayerData(fromData);
dataManager.savePlayerData(toData);
sender.sendMessage(
Message.paySuccess.toString()
.replace("%player%", toData.getPlayerName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", amount))
);
if (FileManager.isUseBC()) {
ServiceMessageAPI.sendPlayerMessage(
toData.getUuid(),
Message.receivePay.toString()
.replace("%player%", player.getName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", amount))
);
} else {
Player toPlayer = Bukkit.getPlayer(toData.getUuid());
if (toPlayer != null) {
toPlayer.sendMessage(
Message.receivePay.toString()
.replace("%player%", player.getName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", amount))
);
}
}
return true;
}
@Override
@SuppressWarnings("DuplicatedCode")
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
switch (args.length) {
case 2: {
return HamsterAPI.getOnlinePlayersName(args[1]);
}
case 3: {
List<String> types = dataManager.getCurrencyTypes().stream().map(CurrencyType::getId).collect(Collectors.toList());
types = HamsterAPI.startWithIgnoreCase(types, args[2]);
if (types.size() > 10) {
types = types.subList(0, 9);
}
return types;
}
}
return null;
}
}

View File

@@ -0,0 +1,89 @@
package cn.hamster3.currency.command.currency;
import cn.hamster3.api.HamsterAPI;
import cn.hamster3.api.command.CommandExecutor;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.stream.Collectors;
public class CurrencySeeCommand extends CommandExecutor {
private final IDataManager dataManager;
public CurrencySeeCommand(IDataManager dataManager) {
super(
"see",
"查看玩家的货币余额",
"currency.see",
Message.notHasPermission.toString(),
new String[]{
"货币类型",
"玩家"
}
);
this.dataManager = dataManager;
}
@Override
public boolean isPlayerCommand() {
return false;
}
@Override
@SuppressWarnings("DuplicatedCode")
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length < 2) {
sender.sendMessage(Message.notInputCurrencyType.toString());
return true;
}
CurrencyType type = dataManager.getCurrencyType(args[1]);
if (type == null) {
sender.sendMessage(Message.currencyTypeNotFound.toString());
return true;
}
PlayerData data;
if (args.length < 3) {
if (!(sender instanceof Player)) {
sender.sendMessage(Message.notInputPlayerName.toString());
return true;
}
Player player = (Player) sender;
data = dataManager.getPlayerData(player.getUniqueId());
} else {
if (!sender.hasPermission("currency.see.other")) {
sender.sendMessage(Message.notHasPermission.toString());
return true;
}
data = dataManager.getPlayerData(args[2]);
if (data == null) {
sender.sendMessage(Message.playerNotFound.toString());
return true;
}
}
sender.sendMessage(
Message.seeCurrency.toString()
.replace("%player%", data.getPlayerName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", data.getPlayerCurrency(type.getId())))
);
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 2) {
List<String> types = dataManager.getCurrencyTypes().stream().map(CurrencyType::getId).collect(Collectors.toList());
return HamsterAPI.startWith(types, args[1]);
}
if (args.length == 3) {
return HamsterAPI.getOnlinePlayersName(args[2]);
}
return null;
}
}

View File

@@ -0,0 +1,22 @@
package cn.hamster3.currency.command.currency;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
public class CurrencySetCommand extends CurrencyAdminSetCommand {
public CurrencySetCommand(IDataManager dataManager) {
super(
dataManager,
"set",
"为玩家货币设置余额",
"currency.set"
);
}
@Override
protected void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), amount);
}
}

View File

@@ -0,0 +1,22 @@
package cn.hamster3.currency.command.currency;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
public class CurrencyTakeCommand extends CurrencyAdminSetCommand {
public CurrencyTakeCommand(IDataManager dataManager) {
super(
dataManager,
"take",
"为玩家货币扣除余额",
"currency.take"
);
}
@Override
protected void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), data.getPlayerCurrency(type.getId()) - amount);
}
}

View File

@@ -0,0 +1,102 @@
package cn.hamster3.currency.command.currency;
import cn.hamster3.api.HamsterAPI;
import cn.hamster3.api.command.CommandExecutor;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class CurrencyTopCommand extends CommandExecutor {
private final IDataManager dataManager;
public CurrencyTopCommand(IDataManager dataManager) {
super(
"top",
"查看玩家的货币余额排行榜",
"currency.top",
Message.notHasPermission.toString(),
new String[]{
"货币类型",
"页码"
}
);
this.dataManager = dataManager;
}
@Override
public boolean isPlayerCommand() {
return false;
}
@Override
@SuppressWarnings("DuplicatedCode")
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length < 2) {
sender.sendMessage(Message.notInputCurrencyType.toString());
return true;
}
CurrencyType type = dataManager.getCurrencyType(args[1]);
if (type == null) {
sender.sendMessage(Message.currencyTypeNotFound.toString());
return true;
}
int page = 1;
if (args.length >= 3) {
try {
page = Integer.parseInt(args[2]);
} catch (NumberFormatException e) {
sender.sendMessage(Message.pageError.toString());
return true;
}
}
page = page - 1;
String typeId = type.getId();
ArrayList<PlayerData> playerData = dataManager.getPlayerData();
playerData.sort((o1, o2) -> -Double.compare(o1.getPlayerCurrency(typeId), o2.getPlayerCurrency(typeId)));
sender.sendMessage(
Message.topRankPageHead.toString()
.replace("%type%", typeId)
.replace("%page%", String.valueOf(page + 1))
);
for (int i = page * 10; i < (page + 1) * 10; i++) {
if (i >= playerData.size()) {
break;
}
PlayerData data = playerData.get(i);
sender.sendMessage(
Message.topRankPageItem.toString()
.replace("%rank%", String.valueOf(i + 1))
.replace("%name%", data.getPlayerName())
.replace("%amount%", String.format("%.2f", data.getPlayerCurrency(typeId)))
);
}
return true;
}
@Override
@SuppressWarnings("DuplicatedCode")
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 2) {
List<String> types = dataManager.getPlayerData()
.stream()
.map(PlayerData::getPlayerName)
.collect(Collectors.toList());
types = HamsterAPI.startWithIgnoreCase(types, args[1]);
if (types.size() > 10) {
types = types.subList(0, 9);
}
return types;
}
return null;
}
}

View File

@@ -0,0 +1,86 @@
package cn.hamster3.currency.command.vault;
import cn.hamster3.api.HamsterAPI;
import cn.hamster3.api.command.CommandExecutor;
import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import java.util.List;
public abstract class VaultAdminSetCommand extends CommandExecutor {
protected final IDataManager dataManager;
public VaultAdminSetCommand(IDataManager dataManager, String name, String description, String permission) {
super(
name,
description,
permission,
Message.notHasPermission.toString(),
new String[]{
"玩家",
"数额"
}
);
this.dataManager = dataManager;
}
@Override
public boolean isPlayerCommand() {
return false;
}
public abstract void doSet(PlayerData data, CurrencyType type, double amount);
@Override
@SuppressWarnings("DuplicatedCode")
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
CurrencyType type = dataManager.getCurrencyType(FileManager.getVaultCurrencyType());
if (type == null) {
sender.sendMessage(Message.vaultEconomySetError.toString());
return true;
}
if (args.length < 2) {
sender.sendMessage(Message.notInputPlayerName.toString());
return true;
}
PlayerData data = dataManager.getPlayerData(args[1]);
if (data == null) {
sender.sendMessage(Message.playerNotFound.toString());
return true;
}
if (args.length < 3) {
sender.sendMessage(Message.notInputAmount.toString());
return true;
}
double amount;
try {
amount = Double.parseDouble(args[2]);
} catch (NumberFormatException e) {
sender.sendMessage(Message.amountNumberError.toString());
return true;
}
doSet(data, type, amount);
dataManager.savePlayerData(data);
sender.sendMessage(
Message.seeCurrency.toString()
.replace("%player%", data.getPlayerName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", data.getPlayerCurrency(type.getId())))
);
return true;
}
@Override
@SuppressWarnings("DuplicatedCode")
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 2) {
return HamsterAPI.getOnlinePlayersName(args[0]);
}
return null;
}
}

View File

@@ -0,0 +1,24 @@
package cn.hamster3.currency.command.vault;
import cn.hamster3.api.command.CommandManager;
import cn.hamster3.currency.core.IDataManager;
import org.bukkit.command.PluginCommand;
public class VaultCommand extends CommandManager {
public VaultCommand(PluginCommand command, IDataManager dataManager) {
super(command);
addCommandExecutor(
new VaultSetCommand(dataManager),
new VaultGiveCommand(dataManager),
new VaultTakeCommand(dataManager)
);
command.setExecutor(this);
command.setTabCompleter(this);
}
@Override
public boolean isPlayerCommand() {
return false;
}
}

View File

@@ -0,0 +1,22 @@
package cn.hamster3.currency.command.vault;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
public class VaultGiveCommand extends VaultAdminSetCommand {
public VaultGiveCommand(IDataManager dataManager) {
super(
dataManager,
"give",
"给予玩家金币",
"currency.give"
);
}
@Override
public void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), data.getPlayerCurrency(type.getId()) + amount);
}
}

View File

@@ -0,0 +1,132 @@
package cn.hamster3.currency.command.vault;
import cn.hamster3.api.HamsterAPI;
import cn.hamster3.api.command.CommandManager;
import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import cn.hamster3.service.bukkit.api.ServiceMessageAPI;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import java.util.List;
public class VaultPayCommand extends CommandManager {
private final IDataManager dataManager;
public VaultPayCommand(PluginCommand command, IDataManager dataManager) {
super(command);
this.dataManager = dataManager;
command.setExecutor(this);
command.setTabCompleter(this);
}
@Override
public boolean isPlayerCommand() {
return true;
}
@Override
public boolean checkPermission(CommandSender sender) {
return sender.hasPermission("currency.pay");
}
@Override
@SuppressWarnings("DuplicatedCode")
protected boolean defaultCommand(CommandSender sender, Command command, String label, String[] args) {
if (!FileManager.isVaultHook()) {
sender.sendMessage(Message.vaultEconomySetError.toString());
return true;
}
CurrencyType type = dataManager.getCurrencyType(FileManager.getVaultCurrencyType());
if (type == null) {
sender.sendMessage(Message.vaultEconomySetError.toString());
return true;
}
if (!type.isCanTransfer()) {
sender.sendMessage(Message.currencyTypeCantTransfer.toString().replace("%type%", type.getId()));
return true;
}
if (args.length < 1) {
sender.sendMessage(Message.notInputPlayerName.toString());
return true;
}
if (args.length < 2) {
sender.sendMessage(Message.notInputPayAmount.toString());
return true;
}
PlayerData toData = dataManager.getPlayerData(args[0]);
if (toData == null) {
sender.sendMessage(Message.playerNotFound.toString());
return true;
}
double amount;
try {
amount = Double.parseDouble(args[1]);
} catch (NumberFormatException e) {
sender.sendMessage(Message.amountNumberError.toString());
return true;
}
if (amount <= 0) {
sender.sendMessage(Message.amountNumberError.toString());
return true;
}
Player player = (Player) sender;
PlayerData fromData = dataManager.getPlayerData(player.getUniqueId());
if (fromData.getPlayerCurrency(type.getId()) < amount) {
sender.sendMessage(
Message.currencyNotEnough.toString()
.replace("%type%", type.getId())
);
return true;
}
fromData.setPlayerCurrency(type.getId(), fromData.getPlayerCurrency(type.getId()) - amount);
toData.setPlayerCurrency(type.getId(), toData.getPlayerCurrency(type.getId()) + amount);
dataManager.savePlayerData(fromData);
dataManager.savePlayerData(toData);
sender.sendMessage(
Message.paySuccess.toString()
.replace("%player%", toData.getPlayerName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", amount))
);
if (FileManager.isUseBC()) {
ServiceMessageAPI.sendPlayerMessage(
toData.getUuid(),
Message.receivePay.toString()
.replace("%player%", player.getName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", amount))
);
} else {
Player toPlayer = Bukkit.getPlayer(toData.getUuid());
if (toPlayer != null) {
toPlayer.sendMessage(
Message.receivePay.toString()
.replace("%player%", player.getName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", amount))
);
}
}
return true;
}
@Override
@SuppressWarnings("DuplicatedCode")
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 1) {
return HamsterAPI.getOnlinePlayersName(args[0]);
}
return null;
}
}

View File

@@ -0,0 +1,81 @@
package cn.hamster3.currency.command.vault;
import cn.hamster3.api.HamsterAPI;
import cn.hamster3.api.command.CommandManager;
import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import java.util.List;
public class VaultSeeCommand extends CommandManager {
private final IDataManager dataManager;
public VaultSeeCommand(PluginCommand command, IDataManager dataManager) {
super(command);
this.dataManager = dataManager;
command.setExecutor(this);
command.setTabCompleter(this);
}
@Override
public boolean isPlayerCommand() {
return false;
}
@Override
@SuppressWarnings("DuplicatedCode")
protected boolean defaultCommand(CommandSender sender, Command command, String label, String[] args) {
if (!FileManager.isVaultHook()) {
sender.sendMessage(Message.vaultEconomySetError.toString());
return true;
}
CurrencyType type = dataManager.getCurrencyType(FileManager.getVaultCurrencyType());
if (type == null) {
sender.sendMessage(Message.vaultEconomySetError.toString());
return true;
}
PlayerData data;
if (args.length < 1) {
if (!(sender instanceof Player)) {
sender.sendMessage(Message.notInputPlayerName.toString());
return true;
}
Player player = (Player) sender;
data = dataManager.getPlayerData(player.getUniqueId());
} else {
if (!sender.hasPermission("currency.see.other")) {
sender.sendMessage(Message.notHasPermission.toString());
return true;
}
data = dataManager.getPlayerData(args[0]);
if (data == null) {
sender.sendMessage(Message.playerNotFound.toString());
return true;
}
}
sender.sendMessage(
Message.seeCurrency.toString()
.replace("%player%", data.getPlayerName())
.replace("%type%", type.getId())
.replace("%amount%", String.format("%.2f", data.getPlayerCurrency(type.getId())))
);
return true;
}
@Override
@SuppressWarnings("DuplicatedCode")
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 1) {
return HamsterAPI.getOnlinePlayersName(args[0]);
}
return null;
}
}

View File

@@ -0,0 +1,21 @@
package cn.hamster3.currency.command.vault;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
public class VaultSetCommand extends VaultAdminSetCommand {
public VaultSetCommand(IDataManager dataManager) {
super(
dataManager,
"set",
"设置玩家的金币",
"currency.set"
);
}
@Override
public void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), amount);
}
}

View File

@@ -0,0 +1,21 @@
package cn.hamster3.currency.command.vault;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
public class VaultTakeCommand extends VaultAdminSetCommand {
public VaultTakeCommand(IDataManager dataManager) {
super(
dataManager,
"take",
"扣除玩家金币",
"currency.take"
);
}
@Override
public void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), data.getPlayerCurrency(type.getId()) - amount);
}
}

View File

@@ -0,0 +1,77 @@
package cn.hamster3.currency.command.vault;
import cn.hamster3.api.command.CommandManager;
import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import java.util.ArrayList;
public class VaultTopCommand extends CommandManager {
private final IDataManager dataManager;
public VaultTopCommand(PluginCommand command, IDataManager dataManager) {
super(command);
this.dataManager = dataManager;
command.setExecutor(this);
command.setTabCompleter(this);
}
@Override
public boolean isPlayerCommand() {
return false;
}
@Override
@SuppressWarnings("DuplicatedCode")
protected boolean defaultCommand(CommandSender sender, Command command, String label, String[] args) {
if (!FileManager.isVaultHook()) {
sender.sendMessage(Message.vaultEconomySetError.toString());
return true;
}
CurrencyType type = dataManager.getCurrencyType(FileManager.getVaultCurrencyType());
if (type == null) {
sender.sendMessage(Message.vaultEconomySetError.toString());
return true;
}
int page = 1;
if (args.length >= 1) {
try {
page = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
sender.sendMessage(Message.pageError.toString());
return true;
}
}
page = page - 1;
String typeId = type.getId();
ArrayList<PlayerData> playerData = dataManager.getPlayerData();
playerData.sort((o1, o2) -> -Double.compare(o1.getPlayerCurrency(typeId), o2.getPlayerCurrency(typeId)));
sender.sendMessage(
Message.topRankPageHead.toString()
.replace("%type%", typeId)
.replace("%page%", String.valueOf(page + 1))
);
for (int i = page * 10; i < (page + 1) * 10; i++) {
if (i >= playerData.size()) {
break;
}
PlayerData data = playerData.get(i);
sender.sendMessage(
Message.topRankPageItem.toString()
.replace("%rank%", String.valueOf(i + 1))
.replace("%name%", data.getPlayerName())
.replace("%amount%", String.format("%.2f", data.getPlayerCurrency(typeId)))
);
}
return true;
}
}

View File

@@ -0,0 +1,157 @@
package cn.hamster3.currency.core;
import cn.hamster3.currency.HamsterCurrency;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import static cn.hamster3.currency.HamsterCurrency.getLogUtils;
public class FileDataManager implements IDataManager {
private final HamsterCurrency plugin;
private final HashSet<PlayerData> playerData;
private final HashSet<CurrencyType> currencyTypes;
public FileDataManager(HamsterCurrency plugin) {
this.plugin = plugin;
playerData = new HashSet<>();
currencyTypes = new HashSet<>();
}
@Override
public void onEnable() {
getLogUtils().info("从本地磁盘中读取玩家数据...");
File dataFolder = new File(plugin.getDataFolder(), "PlayerData");
if (dataFolder.mkdirs()) {
getLogUtils().info("创建玩家存档文件夹...");
}
File[] files = dataFolder.listFiles();
if (files != null) {
for (File file : files) {
try {
PlayerData data = new PlayerData(YamlConfiguration.loadConfiguration(file));
playerData.add(data);
} catch (Exception e) {
getLogUtils().error(e, "加载玩家存档文件 %s 时出现了一个异常!", file.getName());
}
}
}
getLogUtils().info("从本地磁盘中读取玩家数据完成!");
}
@Override
public void onDisable() {
File dataFolder = new File(plugin.getDataFolder(), "PlayerData");
for (PlayerData data : playerData) {
File dataFile = new File(dataFolder, data.getUuid().toString() + ".yml");
try {
data.saveToConfig().save(dataFile);
} catch (IOException e) {
getLogUtils().error(e, "保存玩家 %s 的存档至文件时出现了一个异常!", data.getUuid());
}
}
}
@Override
public void loadConfig() {
reloadConfig();
}
@Override
@SuppressWarnings("ConstantConditions")
public void reloadConfig() {
getLogUtils().info("加载配置文件...");
plugin.saveDefaultConfig();
plugin.reloadConfig();
FileConfiguration config = plugin.getConfig();
currencyTypes.clear();
ConfigurationSection currencyTypesConfig = config.getConfigurationSection("currencyTypes");
for (String key : currencyTypesConfig.getKeys(false)) {
try {
currencyTypes.add(new CurrencyType(currencyTypesConfig.getConfigurationSection(key)));
getLogUtils().warning("已加载货币类型: %s", key);
} catch (Exception e) {
getLogUtils().error(e, "加载货币类型 %s 时出现了一个错误: ", key);
}
}
FileManager.setPluginConfig(config);
getLogUtils().info("配置文件加载完成!");
}
@Override
public void loadPlayerData(UUID uuid) {
// 由于服务器启动时已经加载了所有玩家的存档
// 所以当玩家进服时无需再加载
// 只需要给没有存档的新玩家初始化一个存档数据即可
PlayerData data = getPlayerData(uuid);
if (data == null) {
playerData.add(new PlayerData(uuid));
}
}
@Override
public void savePlayerData(PlayerData data) {
// 每一次修改存档都保存至磁盘一次会极大地浪费服务器性能
// 按照插件架构,我们只需要在关服的时候保存所有玩家的存档即可
// 所以这里什么都不做
}
@Override
public PlayerData getPlayerData(UUID uuid) {
synchronized (playerData) {
for (PlayerData data : playerData) {
if (uuid.equals(data.getUuid())) {
return data;
}
}
}
return null;
}
@Override
public PlayerData getPlayerData(String name) {
synchronized (playerData) {
for (PlayerData data : playerData) {
if (name.equalsIgnoreCase(data.getPlayerName())) {
return data;
}
}
}
return null;
}
@Override
public ArrayList<PlayerData> getPlayerData() {
synchronized (playerData) {
return new ArrayList<>(playerData);
}
}
@Override
public CurrencyType getCurrencyType(String id) {
for (CurrencyType type : currencyTypes) {
if (type.getId().equalsIgnoreCase(id)) {
return type;
}
}
return null;
}
@Override
public Set<CurrencyType> getCurrencyTypes() {
return currencyTypes;
}
}

View File

@@ -0,0 +1,61 @@
package cn.hamster3.currency.core;
import cn.hamster3.api.HamsterAPI;
import cn.hamster3.currency.HamsterCurrency;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
public abstract class FileManager {
private static boolean useBC;
private static boolean mainServer;
private static boolean vaultHook;
private static String vaultCurrencyType;
private static FileConfiguration pluginConfig;
public static void reload(HamsterCurrency plugin) {
plugin.saveDefaultConfig();
plugin.reloadConfig();
pluginConfig = plugin.getConfig();
useBC = pluginConfig.getBoolean("useBC", false);
mainServer = pluginConfig.getBoolean("datasource.template");
setPluginConfig(pluginConfig);
}
public static FileConfiguration getPluginConfig() {
return pluginConfig;
}
@SuppressWarnings("ConstantConditions")
public static void setPluginConfig(FileConfiguration pluginConfig) {
FileManager.pluginConfig = pluginConfig;
vaultHook = pluginConfig.getBoolean("vault.hook");
vaultCurrencyType = pluginConfig.getString("vault.type");
ConfigurationSection messagesConfig = pluginConfig.getConfigurationSection("messages");
for (String key : messagesConfig.getKeys(false)) {
try {
Message.valueOf(key).setMessage(HamsterAPI.replaceColorCode(messagesConfig.getString(key)));
} catch (IllegalArgumentException e) {
HamsterCurrency.getLogUtils().warning("初始化消息设置 %s 时发生了一个异常: ", key);
e.printStackTrace();
}
}
}
public static boolean isUseBC() {
return useBC;
}
public static boolean isMainServer() {
return mainServer;
}
public static boolean isVaultHook() {
return vaultHook;
}
public static String getVaultCurrencyType() {
return vaultCurrencyType;
}
}

View File

@@ -0,0 +1,54 @@
package cn.hamster3.currency.core;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;
public interface IDataManager {
/**
* 插件启动时调用
* 此时应该加载全部玩家的数据
*/
void onEnable();
/**
* 插件关闭时调用
* 此时应该保存全部玩家的数据
*/
void onDisable();
void loadConfig();
/**
* 重载服务器
*/
void reloadConfig();
/**
* 加载玩家的数据
*
* @param uuid -
*/
void loadPlayerData(UUID uuid);
/**
* 保存玩家的数据
*
* @param data -
*/
void savePlayerData(PlayerData data);
PlayerData getPlayerData(UUID uuid);
PlayerData getPlayerData(String name);
ArrayList<PlayerData> getPlayerData();
CurrencyType getCurrencyType(String id);
Set<CurrencyType> getCurrencyTypes();
}

View File

@@ -0,0 +1,43 @@
package cn.hamster3.currency.core;
public enum Message {
prefix("§a[仓鼠经济] "),
notHasPermission("§c你没有这个权限!"),
notInputPlayerName("请输入玩家名称!"),
playerNotFound("未找到该玩家!"),
notInputCurrencyType("请输入货币类型!"),
currencyTypeNotFound("未找到该货币类型!"),
notInputAmount("请输入货币额度!"),
notInputPayAmount("请输入转账金额!"),
amountNumberError("货币额度必须是一个数字!"),
playerCurrencySetSuccess("货币设置成功! 玩家 %player% 当前 %type% 余额为: %amount%"),
currencyTypeCantTransfer("%type% 不支持转账!"),
currencyNotEnough("你的 %type% 不足!"),
paySuccess("已将 %amount% %type% 转账至 %player% 账户!"),
receivePay("从 %player% 账户上收到 %amount% %type%."),
seeCurrency("玩家 %player% 当前货币 %type% 余额为: %amount%"),
pageError("页码必须是一个大于0的整数!"),
topRankPageHead("========== %type% 排行榜 第 %page% 页 =========="),
topRankPageItem("%rank%.%name% %amount%"),
currencyNamePlural("金币"),
currencyNameSingular("金币"),
vaultEconomySetError("服务器经济系统发生了一个错误, 请尝试联系服务器管理员汇报问题!");
private String message;
Message(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return prefix.message + message;
}
}

View File

@@ -0,0 +1,316 @@
package cn.hamster3.currency.core;
import cn.hamster3.api.HamsterAPI;
import cn.hamster3.currency.HamsterCurrency;
import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData;
import cn.hamster3.service.bukkit.api.ServiceMessageAPI;
import com.google.gson.JsonParser;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import static cn.hamster3.currency.HamsterCurrency.getLogUtils;
public class SQLDataManager implements IDataManager {
private final JsonParser parser;
private final Connection connection;
private final HamsterCurrency plugin;
private final HashSet<PlayerData> playerData;
private final HashSet<CurrencyType> currencyTypes;
@SuppressWarnings("ConstantConditions")
public SQLDataManager(HamsterCurrency plugin) throws SQLException, ClassNotFoundException {
this.plugin = plugin;
parser = new JsonParser();
playerData = new HashSet<>();
currencyTypes = new HashSet<>();
connection = HamsterAPI.getSQLConnection(FileManager.getPluginConfig().getConfigurationSection("datasource"));
Statement statement = connection.createStatement();
statement.execute("CREATE TABLE IF NOT EXISTS hamster_currency_player_data(" +
"uuid VARCHAR(36) PRIMARY KEY," +
"data TEXT" +
");");
statement.execute("CREATE TABLE IF NOT EXISTS hamster_currency_settings(" +
"title VARCHAR(64) PRIMARY KEY," +
"data TEXT" +
");");
statement.close();
}
public void uploadConfigToSQL() {
getLogUtils().info("重载配置文件...");
FileManager.reload(plugin);
FileConfiguration config = FileManager.getPluginConfig();
getLogUtils().info("配置文件重载完成!");
try {
getLogUtils().info("将配置文件上传至数据库...");
Statement statement = connection.createStatement();
String data = Base64.getEncoder().encodeToString(config.saveToString().getBytes(StandardCharsets.UTF_8));
statement.executeUpdate(String.format(
"REPLACE INTO hamster_currency_settings VALUES('%s', '%s');",
"pluginConfig",
data
));
statement.close();
getLogUtils().info("配置文件上传完成!");
} catch (SQLException e) {
getLogUtils().error(e, "插件上传 pluginConfig 至数据库时遇到了一个异常: ");
}
loadConfig(config);
ServiceMessageAPI.sendMessage("HamsterCurrency", "uploadConfigToSQL");
}
@SuppressWarnings("SwitchStatementWithTooFewBranches")
public void loadConfigFromSQL() {
try {
getLogUtils().info("从数据库中下载配置文件...");
Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery("SELECT * FROM hamster_currency_settings;");
while (set.next()) {
String title = set.getString("title");
String data = new String(Base64.getDecoder().decode(set.getString("data")), StandardCharsets.UTF_8);
switch (title) {
case "pluginConfig": {
YamlConfiguration config = new YamlConfiguration();
try {
config.loadFromString(data);
} catch (InvalidConfigurationException e) {
getLogUtils().error(e, "插件加载 %s 时遇到了一个异常: ", title);
}
loadConfig(config);
}
}
}
statement.close();
getLogUtils().info("配置文件下载完成!");
} catch (SQLException e) {
getLogUtils().error(e, "插件从数据库中下载 pluginConfig 时遇到了一个异常: ");
}
}
@SuppressWarnings("ConstantConditions")
private void loadConfig(FileConfiguration config) {
getLogUtils().info("加载配置文件...");
currencyTypes.clear();
ConfigurationSection currencyTypesConfig = config.getConfigurationSection("currencyTypes");
for (String key : currencyTypesConfig.getKeys(false)) {
try {
currencyTypes.add(new CurrencyType(currencyTypesConfig.getConfigurationSection(key)));
getLogUtils().warning("已加载货币类型: %s", key);
} catch (Exception e) {
getLogUtils().error(e, "加载货币类型 %s 时出现了一个错误: ", key);
}
}
FileManager.setPluginConfig(config);
getLogUtils().info("配置文件加载完成!");
}
public void importFromOtherPluginData(String database, String table, String uuidCol, String nameCol, String moneyCol, String currencyType) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
getLogUtils().info("开始从其他插件的数据库存档中导入数据: ");
getLogUtils().info("数据库名: %s", database);
getLogUtils().info("数据表名: %s", table);
getLogUtils().info("玩家uuid列名: %s", uuidCol);
getLogUtils().info("玩家名称列名: %s", nameCol);
getLogUtils().info("玩家经济列名: %s", moneyCol);
getLogUtils().info("导入至经济类型: %s", currencyType);
try {
Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery(String.format("SELECT * FROM %s.%s;", database, table));
synchronized (playerData) {
while (set.next()) {
try {
UUID uuid = UUID.fromString(set.getString(uuidCol));
String name = set.getString(nameCol);
double money = set.getDouble(moneyCol);
PlayerData data = getPlayerData(uuid);
if (data == null) {
data = new PlayerData(uuid, name);
playerData.add(data);
}
data.setPlayerCurrency(currencyType, money);
getLogUtils().info("已从其他插件中加载了玩家 %s 的存档数据.", data.getUuid());
} catch (Exception e) {
getLogUtils().error(e, "导入某一条数据时发生了一个错误: ");
}
}
}
for (PlayerData data : playerData) {
statement.executeUpdate(String.format(
"REPLACE INTO hamster_currency_player_data VALUES('%s', '%s');",
data.getUuid().toString(),
data.saveToJson().toString()
));
getLogUtils().info("已保存玩家 %s 的存档数据.", data.getUuid());
ServiceMessageAPI.sendMessage("HamsterCurrency", "savedPlayerData", data.getUuid().toString());
}
statement.close();
} catch (SQLException e) {
getLogUtils().error(e, "从其他插件中导入数据时发生了一个异常:");
}
});
}
@Override
public void onEnable() {
getLogUtils().info("从数据库中读取玩家数据...");
try {
Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery("SELECT * FROM hamster_currency_player_data;");
synchronized (playerData) {
while (set.next()) {
String uuid = set.getString("uuid");
String string = set.getString("data");
try {
PlayerData data = new PlayerData(parser.parse(string).getAsJsonObject());
playerData.add(data);
} catch (Exception e) {
getLogUtils().error(e, "从数据库中读取玩家 %s 的存档( %s )时出现了一个异常: ", uuid, string);
}
}
}
set.close();
statement.close();
} catch (SQLException e) {
getLogUtils().error(e, "从数据库中读取玩家数据时出现了一个异常:");
}
getLogUtils().info("从数据库中读取玩家数据完成!");
}
@Override
public void onDisable() {
// 因为SQL模式使用HamsterService前置
// 服务器之间数据实时同步
// 所以关服时无需保存任何数据
}
@Override
public void loadConfig() {
if (FileManager.isMainServer()) {
uploadConfigToSQL();
} else {
loadConfigFromSQL();
}
}
@Override
public void reloadConfig() {
ServiceMessageAPI.sendMessage("HamsterCurrency", "reload");
}
@Override
public void loadPlayerData(UUID uuid) {
try {
Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery(String.format(
"SELECT * FROM hamster_currency_player_data WHERE uuid='%s';",
uuid
));
PlayerData data;
if (set.next()) {
String string = set.getString("data");
try {
data = new PlayerData(parser.parse(string).getAsJsonObject());
} catch (Exception e) {
getLogUtils().error(e, "从数据库中读取玩家 %s 的存档( %s )时出现了一个异常: ", uuid, string);
statement.close();
return;
}
} else {
data = new PlayerData(uuid);
getLogUtils().info("初始化玩家 %s 的存档数据.", data.getUuid());
}
synchronized (playerData) {
playerData.remove(data);
playerData.add(data);
}
set.close();
statement.close();
getLogUtils().info("已加载玩家 %s 的存档数据.", data.getUuid());
} catch (SQLException e) {
getLogUtils().error(e, "加载玩家 %s 的存档数据时出错!", uuid);
}
}
@Override
public void savePlayerData(PlayerData data) {
Bukkit.getScheduler().runTaskAsynchronously(plugin,
() -> {
try {
Statement statement = connection.createStatement();
statement.executeUpdate(String.format(
"REPLACE INTO hamster_currency_player_data VALUES('%s', '%s');",
data.getUuid().toString(),
data.saveToJson().toString()
));
statement.close();
} catch (SQLException e) {
getLogUtils().error(e, "保存玩家 %s 的存档数据时出错!", data.getUuid());
}
getLogUtils().info("已保存玩家 %s 的存档数据.", data.getUuid());
ServiceMessageAPI.sendMessage(
"HamsterCurrency",
"savedPlayerData",
data.getUuid().toString()
);
});
}
@Override
public PlayerData getPlayerData(UUID uuid) {
synchronized (playerData) {
for (PlayerData data : playerData) {
if (uuid.equals(data.getUuid())) {
return data;
}
}
}
return null;
}
@Override
public PlayerData getPlayerData(String name) {
synchronized (playerData) {
for (PlayerData data : playerData) {
if (name.equalsIgnoreCase(data.getPlayerName())) {
return data;
}
}
}
return null;
}
@Override
public ArrayList<PlayerData> getPlayerData() {
synchronized (playerData) {
return new ArrayList<>(playerData);
}
}
@Override
public CurrencyType getCurrencyType(String id) {
for (CurrencyType type : currencyTypes) {
if (type.getId().equalsIgnoreCase(id)) {
return type;
}
}
return null;
}
@Override
public Set<CurrencyType> getCurrencyTypes() {
return currencyTypes;
}
}

View File

@@ -0,0 +1,46 @@
package cn.hamster3.currency.data;
import org.bukkit.configuration.ConfigurationSection;
/**
* 货币类型
*/
public class CurrencyType {
/**
* 货币识别符
*/
private final String id;
/**
* 是否允许转账
*/
private final boolean canTransfer;
public CurrencyType(ConfigurationSection config) {
id = config.getName();
canTransfer = config.getBoolean("canTransfer");
}
public String getId() {
return id;
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean isCanTransfer() {
return canTransfer;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CurrencyType that = (CurrencyType) o;
return id.equalsIgnoreCase(that.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
}

View File

@@ -0,0 +1,118 @@
package cn.hamster3.currency.data;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class PlayerData {
private final UUID uuid;
private final String playerName;
private final HashMap<String, Double> playerCurrencies;
public PlayerData(UUID uuid) {
this.uuid = uuid;
playerName = Bukkit.getOfflinePlayer(uuid).getName();
playerCurrencies = new HashMap<>();
}
public PlayerData(UUID uuid, String playerName) {
this.uuid = uuid;
this.playerName = playerName;
playerCurrencies = new HashMap<>();
}
public PlayerData(JsonObject object) {
uuid = UUID.fromString(object.get("uuid").getAsString());
OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
if (player.getName() != null) {
playerName = player.getName();
} else if (object.has("playerName") && !object.get("playerName").isJsonNull()) {
playerName = object.get("playerName").getAsString();
} else {
playerName = null;
}
playerCurrencies = new HashMap<>();
JsonObject playerCurrenciesJson = object.getAsJsonObject("playerCurrencies");
for (Map.Entry<String, JsonElement> entry : playerCurrenciesJson.entrySet()) {
playerCurrencies.put(entry.getKey(), entry.getValue().getAsDouble());
}
}
@SuppressWarnings("ConstantConditions")
public PlayerData(ConfigurationSection config) {
uuid = UUID.fromString(config.getString("uuid"));
OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
if (player.getName() != null) {
playerName = player.getName();
} else {
playerName = config.getString("playerName");
}
playerCurrencies = new HashMap<>();
ConfigurationSection playerCurrenciesConfig = config.getConfigurationSection("playerCurrencies");
for (String key : playerCurrenciesConfig.getKeys(false)) {
playerCurrencies.put(key, playerCurrenciesConfig.getDouble(key));
}
}
public JsonObject saveToJson() {
JsonObject object = new JsonObject();
object.addProperty("uuid", uuid.toString());
object.addProperty("playerName", playerName);
JsonObject playerCurrenciesJson = new JsonObject();
for (Map.Entry<String, Double> entry : playerCurrencies.entrySet()) {
playerCurrenciesJson.addProperty(entry.getKey(), entry.getValue());
}
object.add("playerCurrencies", playerCurrenciesJson);
return object;
}
public YamlConfiguration saveToConfig() {
YamlConfiguration config = new YamlConfiguration();
config.set("uuid", uuid.toString());
config.set("playerName", playerName);
YamlConfiguration playerCurrenciesConfig = new YamlConfiguration();
for (Map.Entry<String, Double> entry : playerCurrencies.entrySet()) {
playerCurrenciesConfig.set(entry.getKey(), entry.getValue());
}
config.set("playerCurrencies", playerCurrenciesConfig);
return config;
}
public UUID getUuid() {
return uuid;
}
public String getPlayerName() {
return playerName;
}
public void setPlayerCurrency(String type, double amount) {
playerCurrencies.put(type, amount);
}
public double getPlayerCurrency(String type) {
return playerCurrencies.getOrDefault(type, 0D);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PlayerData that = (PlayerData) o;
return uuid.equals(that.uuid);
}
@Override
public int hashCode() {
return uuid.hashCode();
}
}

View File

@@ -0,0 +1,45 @@
package cn.hamster3.currency.hook;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.PlayerData;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class PlaceholderHook extends PlaceholderExpansion {
private final IDataManager dataManager;
public PlaceholderHook(IDataManager dataManager) {
this.dataManager = dataManager;
}
@Override
@NotNull
public String getIdentifier() {
return "Currency";
}
@Override
@NotNull
public String getAuthor() {
return "Hamster3";
}
@Override
@NotNull
public String getVersion() {
return "1.0";
}
@Override
public String onRequest(OfflinePlayer player, @NotNull String params) {
PlayerData data = dataManager.getPlayerData(player.getUniqueId());
return String.format("%.2f", data.getPlayerCurrency(params));
}
@Override
public String onPlaceholderRequest(Player player, @NotNull String params) {
return onRequest(player, params);
}
}

View File

@@ -0,0 +1,247 @@
package cn.hamster3.currency.hook;
import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.PlayerData;
import net.milkbowl.vault.economy.AbstractEconomy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.OfflinePlayer;
import java.util.ArrayList;
import java.util.List;
public class VaultEconomyHook extends AbstractEconomy {
private static final EconomyResponse NOT_IMPLEMENTED_RESPONSE =
new EconomyResponse(
0,
0,
EconomyResponse.ResponseType.NOT_IMPLEMENTED,
"HamsterCurrency未实现该功能~"
);
private final IDataManager dataManager;
public VaultEconomyHook(IDataManager dataManager) {
this.dataManager = dataManager;
}
protected EconomyResponse depositPlayer(PlayerData data, double amount) {
if (data == null) {
return new EconomyResponse(amount, 0, EconomyResponse.ResponseType.FAILURE, "玩家账户不存在");
}
String type = FileManager.getVaultCurrencyType();
if (data.getPlayerCurrency(type) > 0 && data.getPlayerCurrency(type) + amount < 0) {
return new EconomyResponse(amount, 0, EconomyResponse.ResponseType.FAILURE, "玩家金额超出上限");
}
data.setPlayerCurrency(type, data.getPlayerCurrency(type) + amount);
dataManager.savePlayerData(data);
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.SUCCESS, "");
}
protected EconomyResponse withdrawPlayer(PlayerData data, double amount) {
if (data == null) {
return new EconomyResponse(amount, 0, EconomyResponse.ResponseType.FAILURE, "玩家账户不存在");
}
String type = FileManager.getVaultCurrencyType();
if (data.getPlayerCurrency(type) < amount) {
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.FAILURE, "余额不足");
}
data.setPlayerCurrency(type, data.getPlayerCurrency(type) - amount);
dataManager.savePlayerData(data);
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.SUCCESS, "扣款成功");
}
private boolean has(PlayerData data, double amount) {
if (data == null) {
return false;
}
return data.getPlayerCurrency(FileManager.getVaultCurrencyType()) >= amount;
}
private double getBalance(PlayerData data) {
if (data == null) {
return 0;
}
return data.getPlayerCurrency(FileManager.getVaultCurrencyType());
}
@Override
public boolean isEnabled() {
return FileManager.isVaultHook();
}
@Override
public String getName() {
return "HamsterCurrency";
}
@Override
public int fractionalDigits() {
return 2;
}
@Override
public String format(double amount) {
return String.format("%.2f", amount);
}
@Override
public String currencyNamePlural() {
return Message.currencyNamePlural.getMessage();
}
@Override
public String currencyNameSingular() {
return Message.currencyNameSingular.getMessage();
}
@Override
public double getBalance(String playerName) {
return getBalance(dataManager.getPlayerData(playerName));
}
@Override
public double getBalance(OfflinePlayer player) {
return getBalance(dataManager.getPlayerData(player.getUniqueId()));
}
@Override
public double getBalance(String playerName, String world) {
return getBalance(dataManager.getPlayerData(playerName));
}
@Override
public double getBalance(OfflinePlayer player, String world) {
return getBalance(dataManager.getPlayerData(player.getUniqueId()));
}
@Override
public boolean has(String playerName, double amount) {
return has(dataManager.getPlayerData(playerName), amount);
}
@Override
public boolean has(OfflinePlayer player, double amount) {
return has(dataManager.getPlayerData(player.getUniqueId()), amount);
}
@Override
public boolean has(String playerName, String worldName, double amount) {
return has(dataManager.getPlayerData(playerName), amount);
}
@Override
public boolean has(OfflinePlayer player, String worldName, double amount) {
return has(dataManager.getPlayerData(player.getUniqueId()), amount);
}
@Override
public EconomyResponse withdrawPlayer(String playerName, double amount) {
return withdrawPlayer(dataManager.getPlayerData(playerName), amount);
}
@Override
public EconomyResponse withdrawPlayer(OfflinePlayer player, double amount) {
return withdrawPlayer(dataManager.getPlayerData(player.getUniqueId()), amount);
}
@Override
public EconomyResponse withdrawPlayer(String playerName, String worldName, double amount) {
return withdrawPlayer(dataManager.getPlayerData(playerName), amount);
}
@Override
public EconomyResponse withdrawPlayer(OfflinePlayer player, String worldName, double amount) {
return withdrawPlayer(dataManager.getPlayerData(player.getUniqueId()), amount);
}
@Override
public EconomyResponse depositPlayer(String playerName, double amount) {
return depositPlayer(dataManager.getPlayerData(playerName), amount);
}
@Override
public EconomyResponse depositPlayer(OfflinePlayer player, double amount) {
return depositPlayer(dataManager.getPlayerData(player.getUniqueId()), amount);
}
@Override
public EconomyResponse depositPlayer(String playerName, String worldName, double amount) {
return depositPlayer(dataManager.getPlayerData(playerName), amount);
}
@Override
public EconomyResponse depositPlayer(OfflinePlayer player, String worldName, double amount) {
return depositPlayer(dataManager.getPlayerData(player.getUniqueId()), amount);
}
@Override
public boolean hasBankSupport() {
return false;
}
@Override
public boolean hasAccount(String playerName) {
return true;
}
@Override
public boolean hasAccount(String playerName, String worldName) {
return true;
}
@Override
public EconomyResponse createBank(String name, String player) {
return NOT_IMPLEMENTED_RESPONSE;
}
@Override
public EconomyResponse deleteBank(String name) {
return NOT_IMPLEMENTED_RESPONSE;
}
@Override
public EconomyResponse bankBalance(String name) {
return NOT_IMPLEMENTED_RESPONSE;
}
@Override
public EconomyResponse bankHas(String name, double amount) {
return NOT_IMPLEMENTED_RESPONSE;
}
@Override
public EconomyResponse bankWithdraw(String name, double amount) {
return NOT_IMPLEMENTED_RESPONSE;
}
@Override
public EconomyResponse bankDeposit(String name, double amount) {
return NOT_IMPLEMENTED_RESPONSE;
}
@Override
public EconomyResponse isBankOwner(String name, String playerName) {
return NOT_IMPLEMENTED_RESPONSE;
}
@Override
public EconomyResponse isBankMember(String name, String playerName) {
return NOT_IMPLEMENTED_RESPONSE;
}
@Override
public List<String> getBanks() {
return new ArrayList<>();
}
@Override
public boolean createPlayerAccount(String playerName) {
return true;
}
@Override
public boolean createPlayerAccount(String playerName, String worldName) {
return true;
}
}

View File

@@ -0,0 +1,23 @@
package cn.hamster3.currency.listener;
import cn.hamster3.currency.HamsterCurrency;
import cn.hamster3.currency.core.IDataManager;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
public class CurrencyListener implements Listener {
protected final HamsterCurrency plugin;
protected final IDataManager dataManager;
public CurrencyListener(HamsterCurrency plugin, IDataManager dataManager) {
this.plugin = plugin;
this.dataManager = dataManager;
}
@EventHandler(ignoreCancelled = true)
public void onPlayerJoin(PlayerJoinEvent event) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> dataManager.loadPlayerData(event.getPlayer().getUniqueId()));
}
}

View File

@@ -0,0 +1,55 @@
package cn.hamster3.currency.listener;
import cn.hamster3.currency.HamsterCurrency;
import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.SQLDataManager;
import cn.hamster3.service.bukkit.api.ServiceInfoAPI;
import cn.hamster3.service.bukkit.event.MessageReceivedEvent;
import cn.hamster3.service.common.entity.ServiceMessageInfo;
import org.bukkit.event.EventHandler;
import java.util.UUID;
/**
* 跨服模式时使用这个监听器
*/
public class SQLListener extends CurrencyListener {
public SQLListener(HamsterCurrency plugin, SQLDataManager dataManager) {
super(plugin, dataManager);
}
@EventHandler(ignoreCancelled = true)
public void onServiceReceive(MessageReceivedEvent event) {
ServiceMessageInfo info = event.getMessageInfo();
if (!"HamsterCurrency".equals(info.getTag())) {
return;
}
SQLDataManager dataManager = (SQLDataManager) super.dataManager;
switch (info.getAction()) {
case "reload": {
if (!FileManager.isMainServer()) {
return;
}
HamsterCurrency.getLogUtils().info("收到重载指令,开始重载服务器...");
dataManager.uploadConfigToSQL();
break;
}
case "uploadConfigToSQL": {
if (ServiceInfoAPI.getLocalSenderInfo().equals(info.getSenderInfo())) {
return;
}
HamsterCurrency.getLogUtils().info("主服务器已上传 pluginConfig, 准备从数据库中下载配置并重载插件...");
dataManager.loadConfigFromSQL();
break;
}
case "savedPlayerData": {
if (ServiceInfoAPI.getLocalSenderInfo().equals(info.getSenderInfo())) {
return;
}
UUID uuid = UUID.fromString(info.getContentAsString());
dataManager.loadPlayerData(uuid);
break;
}
}
}
}

View File

@@ -0,0 +1,60 @@
# 是否开启跨服模式
# 若false则使用本地文件存储模式
# 若true则需要HamsterService前置
useBC: true
# 若开启跨服模式则需要配置datasource
datasource:
driver: "com.mysql.jdbc.Driver"
url: "jdbc:mysql://test3.hamster3.cn:3306?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false"
user: Test
password: Test123..
database: Test
# 是否将这个服务器的配置文件设为模板
# 若设为trueconfig将会在服务器启动时自动上传至数据库
# 其他template为false的服务器将会在启动和重载时自动从数据库上下载config
# 可以节省一些config配置时的麻烦事情
# 但是请先保证template为true的服务器完全启动了再启动子服
# 如果觉得这样反而更麻烦也可以直接把所有服务器的template设为true
# 这样每个服务器都会使用自己本地的config文件了
template: true
currencyTypes:
# 货币ID
"金币":
# 是否允许转账
canTransfer: true
"一周年活动代币":
canTransfer: false
"比特币":
canTransfer: true
# 开启这个选项前请先确保服务器安装了Vault前置
vault:
# 是否挂接 Vault 经济系统
hook: true
# 使用哪一个货币来支持Vault的经济系统
type: "金币"
messages:
prefix: "§a[仓鼠经济] "
notHasPermission: "§c你没有这个权限!"
notInputPlayerName: "请输入玩家名称!"
playerNotFound: "未找到该玩家!"
notInputCurrencyType: "请输入货币类型!"
currencyTypeNotFound: "未找到该货币类型!"
notInputAmount: "请输入货币额度!"
notInputPayAmount: "请输入转账金额!"
amountNumberError: "货币额度必须是一个数字!"
playerCurrencySetSuccess: "货币设置成功! 玩家 %player% 当前 %type% 余额为: %amount%"
currencyTypeCantTransfer: "%type% 不支持转账!"
currencyNotEnough: "你的 %type% 不足!"
paySuccess: "已将 %amount% %type% 转账至 %player% 账户!"
receivePay: "从 %player% 账户上收到 %amount% %type%."
seeCurrency: "玩家 %player% 当前货币 %type% 余额为: %amount%"
pageError: "页码必须是一个大于0的整数!"
topRankPageHead: "========== %type% 排行榜 第 %page% 页 =========="
topRankPageItem: "%rank%.%name% %amount%"
currencyNamePlural: "金币"
currencyNameSingular: "金币"
vaultEconomySetError: "服务器经济系统发生了一个错误, 请尝试联系服务器管理员汇报问题!"

View File

@@ -0,0 +1,46 @@
name: HamsterCurrency
version: ${version}
main: cn.hamster3.currency.HamsterCurrency
authors: [ Hamster3 ]
description: 仓鼠的多货币支持
website: https://www.hamster3.cn/
load: STARTUP
api-version: "1.16"
depend:
- HamsterAPI
softdepend:
- HasmterService-Bukkit
- PlaceholderAPI
- PlayerPoints
- Vault
commands:
HamsterCurrency:
aliases: [ hcurrency, currency ]
balance:
aliases: [ bal, seemoney ]
balanceTop:
aliases: [ baltop ]
payMoney:
aliases: [ pay ]
economy:
aliases: [ eco, money ]
permissions:
currency.import:
default: op
currency.give:
default: op
currency.take:
default: op
currency.set:
default: op
currency.look:
default: true
currency.look.other:
default: op
currency.top:
default: op

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
gradlew vendored Normal file
View File

@@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MSYS* | MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

4
settings.gradle Normal file
View File

@@ -0,0 +1,4 @@
rootProject.name = 'HamsterCurrency-Parent'
include 'currency-plugin'
include 'transform-essentials'

View File

@@ -0,0 +1,3 @@
essentials 转换插件
放入服务端根目录的**上一级目录**,然后使用控制台启动即可

View File

@@ -0,0 +1,48 @@
plugins {
id 'java'
}
group 'cn.hamster3'
version '1.0.0-SNAPSHOT'
repositories {
maven {
url = "https://maven.airgame.net/repository/maven-public/"
}
}
configurations {
implementationShade
implementation.extendsFrom implementationShade
}
dependencies {
// https://mvnrepository.com/artifact/com.electronwill.night-config/core
implementationShade group: 'com.electronwill.night-config', name: 'core', version: '3.6.4'
// https://mvnrepository.com/artifact/com.electronwill.night-config/yaml
implementationShade group: 'com.electronwill.night-config', name: 'yaml', version: '3.6.4'
// https://mvnrepository.com/artifact/com.google.code.gson/gson
implementationShade group: 'com.google.code.gson', name: 'gson', version: '2.8.8'
// https://mvnrepository.com/artifact/mysql/mysql-connector-java
implementationShade group: 'mysql', name: 'mysql-connector-java', version: '8.0.26'
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
jar {
archivesBaseName = "HamsterCurrency-Transform-Essentials"
manifest.attributes('Main-Class': 'cn.hamster3.transform.essentials.Main')
from([
configurations.implementationShade.collect {
it.isDirectory() ? it : zipTree(it)
},
rootProject.file("LICENSE")
])
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
destinationDir(rootProject.buildDir)
}

View File

@@ -0,0 +1,159 @@
package cn.hamster3.transform.essentials;
import cn.hamster3.transform.essentials.data.PlayerData;
import com.electronwill.nightconfig.core.Config;
import com.electronwill.nightconfig.core.file.FileNotFoundAction;
import com.electronwill.nightconfig.yaml.YamlFormat;
import com.electronwill.nightconfig.yaml.YamlParser;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Scanner;
import java.util.UUID;
public class Main {
private static final YamlParser parser = new YamlParser(YamlFormat.defaultInstance());
private static final HashSet<PlayerData> playerData = new HashSet<>();
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入数据库主机名: ");
String host = scanner.nextLine();
System.out.println("请输入数据库端口号: ");
String port = scanner.nextLine();
System.out.println("请输入数据库用户名: ");
String user = scanner.nextLine();
System.out.println("请输入数据库密码: ");
String password = scanner.nextLine();
System.out.println("请输入数据库库名: ");
String database = scanner.nextLine();
File file = new File(System.getProperty("user.dir"));
File[] files = file.listFiles();
if (files == null) {
return;
}
for (File subFile : files) {
System.out.println("开始扫描文件夹: " + subFile.getAbsolutePath());
if (!subFile.isDirectory()) {
continue;
}
scanServer(subFile);
System.out.println("文件夹扫描完成: " + subFile.getAbsolutePath());
}
System.out.println("加载 MySQL 数据库驱动...");
Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("建立 MySQL 数据库连接...");
Connection connection = DriverManager.getConnection(
"jdbc:mysql://" + host + ":" + port + "?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false",
user,
password
);
Statement statement = connection.createStatement();
System.out.println("切换至数据库...");
statement.execute(String.format("CREATE DATABASE IF NOT EXISTS %s DEFAULT CHARACTER SET ='UTF8';", database));
statement.execute(String.format("USE %s;", database));
System.out.println("检查数据表...");
statement.execute("CREATE TABLE IF NOT EXISTS hamster_currency_player_data(" +
"uuid VARCHAR(36) PRIMARY KEY," +
"data TEXT" +
");");
System.out.println("开始更新数据库...");
for (PlayerData data : playerData) {
String sql = String.format(
"REPLACE INTO hamster_currency_player_data VALUES('%s', '%s');",
data.getUuid().toString(),
data.saveToJson().toString().replace("'", "\\'")
);
try {
statement.executeUpdate(sql);
} catch (SQLException e) {
System.out.println("执行 sql " + sql + " 时遇到了一个异常:");
e.printStackTrace();
}
}
statement.close();
connection.close();
}
private static void scanServer(File folder) {
if (!folder.isDirectory()) {
System.out.println(folder.getAbsolutePath() + " 不是一个文件夹. 跳过扫描.");
return;
}
File pluginFolder = new File(folder, "plugins");
if (!pluginFolder.isDirectory()) {
System.out.println(pluginFolder.getAbsolutePath() + " 不是一个文件夹. 跳过扫描.");
return;
}
File essentialFolder = new File(pluginFolder, "Essentials");
if (!essentialFolder.isDirectory()) {
System.out.println(essentialFolder.getAbsolutePath() + " 不是一个文件夹. 跳过扫描.");
return;
}
File userdataFolder = new File(essentialFolder, "userdata");
if (!userdataFolder.isDirectory()) {
System.out.println(userdataFolder.getAbsolutePath() + " 不是一个文件夹. 跳过扫描.");
return;
}
File[] files = userdataFolder.listFiles();
if (files == null) {
return;
}
for (int i = 0; i < files.length; i++) {
File file = files[i];
try {
scanUserData(file);
} catch (Exception e) {
System.out.println("读取文件 " + file.getAbsolutePath() + " 时出现了一个异常:");
e.printStackTrace();
}
if (i % 100 == 0) {
System.out.println("已完成: (" + i + "/" + files.length + ")");
}
}
}
private static void scanUserData(File file) {
UUID uuid = UUID.fromString(file.getName().substring(0, 36));
Config config = parser.parse(file, FileNotFoundAction.THROW_ERROR, StandardCharsets.UTF_8);
if (config.contains("npc")) {
boolean isNPC = config.get("npc");
if (isNPC) {
return;
}
}
if (!config.contains("lastAccountName")) {
return;
}
if (!config.contains("money")) {
return;
}
String lastAccountName = config.get("lastAccountName");
double money = Double.parseDouble(config.get("money"));
PlayerData data = getPlayerData(uuid, lastAccountName);
if (data.getPlayerCurrency("金币") >= money) {
return;
}
data.setPlayerCurrency("金币", money);
}
private static PlayerData getPlayerData(UUID uuid, String name) {
for (PlayerData data : playerData) {
if (data.getUuid().equals(uuid)) {
return data;
}
}
PlayerData data = new PlayerData(uuid, name);
playerData.add(data);
return data;
}
}

View File

@@ -0,0 +1,44 @@
package cn.hamster3.transform.essentials.data;
/**
* 货币类型
*/
public class CurrencyType {
/**
* 货币识别符
*/
private final String id;
/**
* 是否允许转账
*/
private final boolean canTransfer;
public CurrencyType(String id, boolean canTransfer) {
this.id = id;
this.canTransfer = canTransfer;
}
public String getId() {
return id;
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean isCanTransfer() {
return canTransfer;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CurrencyType that = (CurrencyType) o;
return id.equalsIgnoreCase(that.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
}

View File

@@ -0,0 +1,63 @@
package cn.hamster3.transform.essentials.data;
import com.google.gson.JsonObject;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class PlayerData {
private final UUID uuid;
private final String playerName;
private final HashMap<String, Double> playerCurrencies;
public PlayerData(UUID uuid, String playerName) {
this.uuid = uuid;
this.playerName = playerName;
playerCurrencies = new HashMap<>();
}
public JsonObject saveToJson() {
JsonObject object = new JsonObject();
object.addProperty("uuid", uuid.toString());
object.addProperty("playerName", playerName);
JsonObject playerCurrenciesJson = new JsonObject();
for (Map.Entry<String, Double> entry : playerCurrencies.entrySet()) {
playerCurrenciesJson.addProperty(entry.getKey(), entry.getValue());
}
object.add("playerCurrencies", playerCurrenciesJson);
return object;
}
public UUID getUuid() {
return uuid;
}
public String getPlayerName() {
return playerName;
}
public void setPlayerCurrency(String type, double amount) {
playerCurrencies.put(type, amount);
}
public double getPlayerCurrency(String type) {
return playerCurrencies.getOrDefault(type, 0D);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PlayerData that = (PlayerData) o;
return uuid.equals(that.uuid);
}
@Override
public int hashCode() {
return uuid.hashCode();
}
}