34 Commits

Author SHA1 Message Date
91817db007 fix: 修复事件错误 2024-11-05 15:23:40 +08:00
840cc6d238 feat: 添加 vault 相关事件 2024-11-05 13:27:13 +08:00
bcfb866da7 fix: 对于无注册存档的玩家现在会为其新建存档了 2024-05-10 13:21:25 +08:00
0743728cbf fix: 修复 eco 管理员指令无法补全玩家名称的问题 2024-05-08 02:15:32 +08:00
13b8a3ee73 feat: 现在通过指令修改的货币也会触发事件了 2024-04-24 13:38:56 +08:00
487da47e42 docs: 修改自述文件 2024-04-05 11:32:37 +08:00
fdeef5ed91 feat: 使用 ConcurrentHashMap 优化运行速度 2024-04-05 11:31:02 +08:00
fa656c9cbf Merge remote-tracking branch 'github_https/master' 2024-04-05 11:30:46 +08:00
250bd94e39 feat: 使用 ConcurrentHashMap 优化运行速度 2024-04-05 10:31:42 +08:00
2aa0aa27cb build: 修改 maven 仓库地址 2024-03-15 01:13:19 +08:00
2ff4e5a396 fix: 兼容 MySQL 5.5 版本 2024-03-15 01:12:30 +08:00
a093d411ec feat: 添加事件支持 2024-01-21 20:08:10 +08:00
c6bc7927ea feat: 修复启动报错 2023-11-13 16:19:01 +08:00
35f7eacee6 feat: 数据库日志添加玩家名称 2023-08-10 21:45:49 +08:00
d7e477dd3f feat: 添加数据库日志功能 2023-08-04 19:33:33 +08:00
0cadbd2ca3 修复加载玩家存档时报错的bug 2022-10-27 13:05:52 +08:00
5192b4bb15 fix: placeholder api 挂载失效
placeholder api 挂载失效
2022-08-25 20:03:50 +08:00
dfce58a945 fix: 高版本中启动报错
高版本中启动报错
2022-08-22 20:03:48 +08:00
29e87d06a2 修复加载玩家存档时报错的bug 2022-04-26 01:22:57 +08:00
5854335f43 - 2022-03-25 21:02:38 +08:00
3875f3634f - 2022-02-26 22:41:35 +08:00
67e0dd21f9 - 2022-01-30 22:47:31 +08:00
cd98126fbe - 2022-01-25 18:36:25 +08:00
9c1f4f204e - 2022-01-25 18:24:05 +08:00
ddd547bd7e - 2022-01-25 18:23:55 +08:00
616eee7b6a 修改默认配置 2022-01-18 20:26:31 +08:00
982d87f25d 优化代码 2022-01-18 12:47:27 +08:00
92affba287 更改构建脚本 2022-01-16 16:54:02 +08:00
eac536a971 使用 HikariCP 作为数据库连接池 2022-01-15 12:54:51 +08:00
870a3789f2 修复 reload 指令不需要权限也能执行的bug 2022-01-12 21:27:46 +08:00
eff200634d 修改建表语句,现在默认使用 utf8mb4 编码 2021-09-11 21:24:14 +08:00
59f1e02a6c 更新HamsterAPI前置 2021-09-11 00:38:22 +08:00
e6d95e0ba9 修复玩家名称中包含字符 ' 时执行SQL出错的异常 2021-09-10 23:54:51 +08:00
ca220775b6 修复玩家名称中包含字符 ' 时执行SQL出错的异常 2021-09-10 23:54:06 +08:00
38 changed files with 898 additions and 230 deletions

View File

@@ -1,4 +1,4 @@
# HamsterCurrency # [HamsterCurrency](https://github.com/MiniDay/HamsterCurrency-Parent)
[![](https://jitpack.io/v/cn.hamster3/HamsterCurrency.svg)](https://jitpack.io/#cn.hamster3/HamsterCurrency) [![](https://jitpack.io/v/cn.hamster3/HamsterCurrency.svg)](https://jitpack.io/#cn.hamster3/HamsterCurrency)
仓鼠的多货币经济插件 仓鼠的多货币经济插件
@@ -10,6 +10,12 @@
- [Vault](https://www.spigotmc.org/resources/vault.34315/) 仅开启Vault经济系统时需要 - [Vault](https://www.spigotmc.org/resources/vault.34315/) 仅开启Vault经济系统时需要
- [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) (非必须) - [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) (非必须)
# 变量列表
| 变量 | 描述 |
|:-----------------|:--------|
| %Currency_<货币名称% | 玩家的货币余额 |
# 开发者 # 开发者
## 依赖导入 ## 依赖导入
@@ -19,10 +25,11 @@
添加仓库: 添加仓库:
```xml ```xml
<repositories> <repositories>
<repository> <repository>
<id>jitpack.io</id> <id>airgame-repo</id>
<url>https://jitpack.io</url> <url>https://maven.airgame.net/maven-public/</url>
</repository> </repository>
</repositories> </repositories>
``` ```
@@ -30,10 +37,11 @@
添加导入: 添加导入:
```xml ```xml
<dependency> <dependency>
<groupId>cn.hamster3</groupId> <groupId>cn.hamster3</groupId>
<artifactId>HamsterCurrency</artifactId> <artifactId>HamsterCurrency</artifactId>
<version>2.0.6-SNAPSHOT</version> <version>2.2.2</version>
</dependency> </dependency>
``` ```
@@ -44,7 +52,7 @@
```groovy ```groovy
allprojects { allprojects {
repositories { repositories {
maven { url 'https://jitpack.io' } maven { url 'https://maven.airgame.net/maven-public/' }
} }
} }
``` ```
@@ -53,11 +61,10 @@ allprojects {
```groovy ```groovy
dependencies { dependencies {
implementation 'cn.hamster3:HamsterCurrency:1.3.7-SNAPSHOT' implementation 'cn.hamster3:HamsterCurrency:2.2.2'
} }
``` ```
## API ## API
请参考[CurrencyAPI](/currency-plugin/src/main/java/cn/hamster3/currency/api/CurrencyAPI.java) 请参考[CurrencyAPI](currency-plugin/src/main/java/cn/hamster3/currency/api/CurrencyAPI.java)

View File

@@ -0,0 +1,3 @@
plugins {
id 'java'
}

View File

@@ -1,16 +1,15 @@
//file:noinspection VulnerableLibrariesLocal
plugins { plugins {
id 'java' id 'java'
id 'maven-publish'
} }
group 'cn.hamster3' group 'cn.hamster3'
version '2.0.6-SNAPSHOT' version '2.2.6'
repositories { repositories {
maven { maven {
url = "https://maven.airgame.net/repository/maven-public/" url = "https://maven.airgame.net/maven-public/"
}
maven {
url = "https://repo.codemc.org/repository/maven-public"
} }
} }
@@ -18,11 +17,12 @@ dependencies {
compileOnly "org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT" compileOnly "org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT"
// https://mvnrepository.com/artifact/org.jetbrains/annotations // https://mvnrepository.com/artifact/org.jetbrains/annotations
compileOnly group: 'org.jetbrains', name: 'annotations', version: '22.0.0' compileOnly group: 'org.jetbrains', name: 'annotations', version: '22.0.0'
compileOnly "cn.hamster3:HamsterService-Bukkit:2.6.2-SNAPSHOT" compileOnly "cn.hamster3:HamsterService-Bukkit:2.8.3-SNAPSHOT"
compileOnly "cn.hamster3:HamsterAPI:2.4.0-SNAPSHOT" compileOnly "cn.hamster3:HamsterAPI:2.4.8-SNAPSHOT"
compileOnly "com.github.MilkBowl:VaultAPI:1.7" compileOnly 'net.milkbowl.vault:VaultAPI:1.7'
compileOnly "org.black_ixx:PlayerPoints:2.1.3"
compileOnly "me.clip:placeholderapi:2.10.9" compileOnly "me.clip:placeholderapi:2.10.9"
compileOnly rootProject.fileTree(dir: './libs', includes: ['*.jar'])
} }
processResources { processResources {
@@ -34,9 +34,37 @@ processResources {
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
withSourcesJar()
} }
jar { jar {
archivesBaseName = "HamsterCurrency" archivesBaseName = "HamsterCurrency"
destinationDir(rootProject.buildDir) destinationDir(rootProject.buildDir)
} }
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
options.compilerArgs << "-Xlint:unchecked"
}
publishing {
publications {
create("mavenJava", MavenPublication.class) {
artifactId = "HamsterCurrency"
artifact jar
artifact sourcesJar
//artifact javadocJar
}
}
repositories {
maven {
url = 'https://maven.airgame.net/public/'
credentials {
username maven_username
password maven_password
}
}
}
}

View File

@@ -27,19 +27,25 @@ import org.bukkit.plugin.java.JavaPlugin;
import java.sql.SQLException; import java.sql.SQLException;
public final class HamsterCurrency extends JavaPlugin { public final class HamsterCurrency extends JavaPlugin {
private static HamsterCurrency instance;
private static LogUtils logUtils; private static LogUtils logUtils;
private IDataManager dataManager; private IDataManager dataManager;
private CurrencyListener listener; private CurrencyListener listener;
private boolean loaded; private boolean loaded;
public static HamsterCurrency getInstance() {
return instance;
}
public static LogUtils getLogUtils() { public static LogUtils getLogUtils() {
return logUtils; return logUtils;
} }
@Override @Override
public void onLoad() { public void onLoad() {
FileManager.reload(this); instance = this;
logUtils = new LogUtils(this); logUtils = new LogUtils(this);
FileManager.reload(this);
logUtils.infoDividingLine(); logUtils.infoDividingLine();
if (FileManager.isUseBC()) { if (FileManager.isUseBC()) {
logUtils.info("使用多服务器模式..."); logUtils.info("使用多服务器模式...");
@@ -86,19 +92,19 @@ public final class HamsterCurrency extends JavaPlugin {
logUtils.info("事件监听器已注册!"); logUtils.info("事件监听器已注册!");
registerVault(); registerVault();
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
logUtils.info("检测到 PlaceholderAPI 已安装...");
new PlaceholderHook(dataManager).register();
logUtils.info("已挂载 PlaceholderAPI 变量!");
} else {
logUtils.info("未检测到 PlaceholderAPI!");
}
Bukkit.getScheduler().runTaskAsynchronously(this, () -> { Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
dataManager.onEnable(); dataManager.onEnable();
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
dataManager.loadPlayerData(player.getUniqueId()); 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"); ServiceMessageAPI.subscribeTag("HamsterCurrency");

View File

@@ -1,8 +1,11 @@
package cn.hamster3.currency.api; package cn.hamster3.currency.api;
import cn.hamster3.currency.HamsterCurrency;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
import cn.hamster3.currency.event.CurrencyChangeEvent;
import org.black_ixx.playerpoints.PlayerPoints; import org.black_ixx.playerpoints.PlayerPoints;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -12,7 +15,7 @@ import java.util.UUID;
/** /**
* 当 currencyID 为 PlayerPoints 且服务器安装了点券插件时,会自动更改为 PlayerPoints 接口 * 当 currencyID 为 PlayerPoints 且服务器安装了点券插件时,会自动更改为 PlayerPoints 接口
*/ */
@SuppressWarnings({"unused", "ConstantConditions"}) @SuppressWarnings("unused")
public abstract class CurrencyAPI { public abstract class CurrencyAPI {
private static IDataManager dataManager; private static IDataManager dataManager;
@@ -40,8 +43,11 @@ public abstract class CurrencyAPI {
if (data == null) { if (data == null) {
return; return;
} }
CurrencyChangeEvent event = new CurrencyChangeEvent(uuid, currencyID, data.getPlayerCurrency(currencyID), amount);
Bukkit.getScheduler().runTaskAsynchronously(HamsterCurrency.getInstance(), () -> Bukkit.getPluginManager().callEvent(event));
data.setPlayerCurrency(currencyID, amount); data.setPlayerCurrency(currencyID, amount);
dataManager.savePlayerData(data); dataManager.savePlayerData(data);
dataManager.insertLog(new CurrencyLog(uuid, data.getPlayerName(), currencyID, "set", amount, amount));
} }
public static void addPlayerCurrency(UUID uuid, String currencyID, double amount) { public static void addPlayerCurrency(UUID uuid, String currencyID, double amount) {
@@ -53,8 +59,12 @@ public abstract class CurrencyAPI {
if (data == null) { if (data == null) {
return; return;
} }
data.setPlayerCurrency(currencyID, data.getPlayerCurrency(currencyID) + amount); double balance = data.getPlayerCurrency(currencyID) + amount;
CurrencyChangeEvent event = new CurrencyChangeEvent(uuid, currencyID, data.getPlayerCurrency(currencyID), balance);
Bukkit.getScheduler().runTaskAsynchronously(HamsterCurrency.getInstance(), () -> Bukkit.getPluginManager().callEvent(event));
data.setPlayerCurrency(currencyID, balance);
dataManager.savePlayerData(data); dataManager.savePlayerData(data);
dataManager.insertLog(new CurrencyLog(uuid, data.getPlayerName(), currencyID, "add", amount, balance));
} }
public static void takePlayerCurrency(UUID uuid, String currencyID, double amount) { public static void takePlayerCurrency(UUID uuid, String currencyID, double amount) {
@@ -66,8 +76,12 @@ public abstract class CurrencyAPI {
if (data == null) { if (data == null) {
return; return;
} }
data.setPlayerCurrency(currencyID, data.getPlayerCurrency(currencyID) - amount); double balance = data.getPlayerCurrency(currencyID) - amount;
CurrencyChangeEvent event = new CurrencyChangeEvent(uuid, currencyID, data.getPlayerCurrency(currencyID), balance);
Bukkit.getScheduler().runTaskAsynchronously(HamsterCurrency.getInstance(), () -> Bukkit.getPluginManager().callEvent(event));
data.setPlayerCurrency(currencyID, balance);
dataManager.savePlayerData(data); dataManager.savePlayerData(data);
dataManager.insertLog(new CurrencyLog(uuid, data.getPlayerName(), currencyID, "take", amount, balance));
} }
public static boolean hasPlayerCurrency(UUID uuid, String currencyID, double amount) { public static boolean hasPlayerCurrency(UUID uuid, String currencyID, double amount) {

View File

@@ -2,6 +2,7 @@ package cn.hamster3.currency.command;
import cn.hamster3.api.command.CommandExecutor; import cn.hamster3.api.command.CommandExecutor;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -11,7 +12,7 @@ public class ReloadCommand extends CommandExecutor {
private final IDataManager dataManager; private final IDataManager dataManager;
public ReloadCommand(IDataManager dataManager) { public ReloadCommand(IDataManager dataManager) {
super("reload", "重载服务器"); super("reload", "重载服务器", "currency.reload");
this.dataManager = dataManager; this.dataManager = dataManager;
} }
@@ -20,6 +21,11 @@ public class ReloadCommand extends CommandExecutor {
return false; return false;
} }
@Override
public String getPermissionMessage() {
return Message.notHasPermission.toString();
}
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
dataManager.reloadConfig(); dataManager.reloadConfig();

View File

@@ -1,6 +1,7 @@
package cn.hamster3.currency.command.currency; package cn.hamster3.currency.command.currency;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
@@ -16,7 +17,9 @@ public class CurrencyGiveCommand extends CurrencyAdminSetCommand {
@Override @Override
protected void doSet(PlayerData data, CurrencyType type, double amount) { protected void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), data.getPlayerCurrency(type.getId()) + amount); double balance = data.getPlayerCurrency(type.getId()) + amount;
data.setPlayerCurrency(type.getId(), balance);
dataManager.insertLog(new CurrencyLog(data.getUuid(), data.getPlayerName(), type.getId(), "add", amount, balance));
} }
} }

View File

@@ -5,6 +5,7 @@ import cn.hamster3.api.command.CommandExecutor;
import cn.hamster3.currency.core.FileManager; import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message; import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
import cn.hamster3.service.bukkit.api.ServiceMessageAPI; import cn.hamster3.service.bukkit.api.ServiceMessageAPI;
@@ -25,11 +26,7 @@ public class CurrencyPayCommand extends CommandExecutor {
"向其他玩家转账", "向其他玩家转账",
"currency.pay", "currency.pay",
Message.notHasPermission.toString(), Message.notHasPermission.toString(),
new String[]{ new String[]{"玩家", "货币类型", "数额"}
"玩家",
"货币类型",
"数额"
}
); );
this.dataManager = dataManager; this.dataManager = dataManager;
} }
@@ -88,10 +85,14 @@ public class CurrencyPayCommand extends CommandExecutor {
); );
return true; return true;
} }
fromData.setPlayerCurrency(type.getId(), fromData.getPlayerCurrency(type.getId()) - amount); double fromBalance = fromData.getPlayerCurrency(type.getId()) - amount;
toData.setPlayerCurrency(type.getId(), toData.getPlayerCurrency(type.getId()) + amount); fromData.setPlayerCurrency(type.getId(), fromBalance);
double toBalance = toData.getPlayerCurrency(type.getId()) + amount;
toData.setPlayerCurrency(type.getId(), toBalance);
dataManager.savePlayerData(fromData); dataManager.savePlayerData(fromData);
dataManager.savePlayerData(toData); dataManager.savePlayerData(toData);
dataManager.insertLog(new CurrencyLog(fromData.getUuid(), fromData.getPlayerName(), type.getId(), "payOut", amount, fromBalance));
dataManager.insertLog(new CurrencyLog(toData.getUuid(), toData.getPlayerName(), type.getId(), "payIn", amount, toBalance));
sender.sendMessage( sender.sendMessage(
Message.paySuccess.toString() Message.paySuccess.toString()
.replace("%player%", toData.getPlayerName()) .replace("%player%", toData.getPlayerName())

View File

@@ -10,6 +10,7 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -22,10 +23,7 @@ public class CurrencySeeCommand extends CommandExecutor {
"查看玩家的货币余额", "查看玩家的货币余额",
"currency.see", "currency.see",
Message.notHasPermission.toString(), Message.notHasPermission.toString(),
new String[]{ new String[]{"玩家", "货币类型"}
"货币类型",
"玩家"
}
); );
this.dataManager = dataManager; this.dataManager = dataManager;
} }
@@ -38,17 +36,8 @@ public class CurrencySeeCommand extends CommandExecutor {
@Override @Override
@SuppressWarnings("DuplicatedCode") @SuppressWarnings("DuplicatedCode")
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { 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; PlayerData data;
if (args.length < 3) { if (args.length < 2) {
if (!(sender instanceof Player)) { if (!(sender instanceof Player)) {
sender.sendMessage(Message.notInputPlayerName.toString()); sender.sendMessage(Message.notInputPlayerName.toString());
return true; return true;
@@ -60,30 +49,51 @@ public class CurrencySeeCommand extends CommandExecutor {
sender.sendMessage(Message.notHasPermission.toString()); sender.sendMessage(Message.notHasPermission.toString());
return true; return true;
} }
data = dataManager.getPlayerData(args[2]); data = dataManager.getPlayerData(args[1]);
}
CurrencyType type = null;
if (args.length >= 3) {
type = dataManager.getCurrencyType(args[2]);
if (type == null) {
sender.sendMessage(Message.currencyTypeNotFound.toString());
return true;
}
}
if (data == null) { if (data == null) {
sender.sendMessage(Message.playerNotFound.toString()); sender.sendMessage(Message.playerNotFound.toString());
return true; return true;
} }
} if (type == null) {
for (CurrencyType currencyType : dataManager.getCurrencyTypes()) {
String typeId = currencyType.getId();
sender.sendMessage( sender.sendMessage(
Message.seeCurrency.toString() Message.seeCurrency.toString()
.replace("%player%", data.getPlayerName()) .replace("%player%", data.getPlayerName())
.replace("%type%", type.getId()) .replace("%type%", typeId)
.replace("%amount%", String.format("%.2f", data.getPlayerCurrency(type.getId()))) .replace("%amount%", String.format("%.2f", data.getPlayerCurrency(typeId)))
); );
}
} else {
String typeId = type.getId();
sender.sendMessage(
Message.seeCurrency.toString()
.replace("%player%", data.getPlayerName())
.replace("%type%", typeId)
.replace("%amount%", String.format("%.2f", data.getPlayerCurrency(typeId)))
);
}
return true; return true;
} }
@Override @Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) { public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 2) { if (args.length == 2) {
List<String> types = dataManager.getCurrencyTypes().stream().map(CurrencyType::getId).collect(Collectors.toList()); return HamsterAPI.getOnlinePlayersName(args[1]);
return HamsterAPI.startWith(types, args[1]);
} }
if (args.length == 3) { if (args.length == 3) {
return HamsterAPI.getOnlinePlayersName(args[2]); List<String> types = dataManager.getCurrencyTypes().stream().map(CurrencyType::getId).collect(Collectors.toList());
return HamsterAPI.startWith(types, args[2]);
} }
return null; return Collections.emptyList();
} }
} }

View File

@@ -1,5 +1,6 @@
package cn.hamster3.currency.command.currency; package cn.hamster3.currency.command.currency;
import cn.hamster3.currency.api.CurrencyAPI;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
@@ -16,7 +17,7 @@ public class CurrencySetCommand extends CurrencyAdminSetCommand {
@Override @Override
protected void doSet(PlayerData data, CurrencyType type, double amount) { protected void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), amount); CurrencyAPI.setPlayerCurrency(data.getUuid(), type.getId(), amount);
} }
} }

View File

@@ -1,6 +1,7 @@
package cn.hamster3.currency.command.currency; package cn.hamster3.currency.command.currency;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
@@ -16,7 +17,8 @@ public class CurrencyTakeCommand extends CurrencyAdminSetCommand {
@Override @Override
protected void doSet(PlayerData data, CurrencyType type, double amount) { protected void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), data.getPlayerCurrency(type.getId()) - amount); double balance = data.getPlayerCurrency(type.getId()) - amount;
data.setPlayerCurrency(type.getId(), balance);
dataManager.insertLog(new CurrencyLog(data.getUuid(), data.getPlayerName(), type.getId(), "take", amount, balance));
} }
} }

View File

@@ -10,6 +10,7 @@ import cn.hamster3.currency.data.PlayerData;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import java.util.Collections;
import java.util.List; import java.util.List;
public abstract class VaultAdminSetCommand extends CommandExecutor { public abstract class VaultAdminSetCommand extends CommandExecutor {
@@ -79,8 +80,8 @@ public abstract class VaultAdminSetCommand extends CommandExecutor {
@SuppressWarnings("DuplicatedCode") @SuppressWarnings("DuplicatedCode")
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) { public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (args.length == 2) { if (args.length == 2) {
return HamsterAPI.getOnlinePlayersName(args[0]); return HamsterAPI.getOnlinePlayersName(args[1]);
} }
return null; return Collections.emptyList();
} }
} }

View File

@@ -1,6 +1,7 @@
package cn.hamster3.currency.command.vault; package cn.hamster3.currency.command.vault;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
@@ -16,7 +17,8 @@ public class VaultGiveCommand extends VaultAdminSetCommand {
@Override @Override
public void doSet(PlayerData data, CurrencyType type, double amount) { public void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), data.getPlayerCurrency(type.getId()) + amount); double balance = data.getPlayerCurrency(type.getId()) + amount;
data.setPlayerCurrency(type.getId(), balance);
dataManager.insertLog(new CurrencyLog(data.getUuid(), data.getPlayerName(), type.getId(), "add", amount, balance));
} }
} }

View File

@@ -5,6 +5,7 @@ import cn.hamster3.api.command.CommandManager;
import cn.hamster3.currency.core.FileManager; import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message; import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
import cn.hamster3.service.bukkit.api.ServiceMessageAPI; import cn.hamster3.service.bukkit.api.ServiceMessageAPI;
@@ -88,11 +89,14 @@ public class VaultPayCommand extends CommandManager {
); );
return true; return true;
} }
double fromBalance = fromData.getPlayerCurrency(type.getId()) - amount;
fromData.setPlayerCurrency(type.getId(), fromData.getPlayerCurrency(type.getId()) - amount); fromData.setPlayerCurrency(type.getId(), fromBalance);
toData.setPlayerCurrency(type.getId(), toData.getPlayerCurrency(type.getId()) + amount); double toBalance = toData.getPlayerCurrency(type.getId()) + amount;
toData.setPlayerCurrency(type.getId(), toBalance);
dataManager.savePlayerData(fromData); dataManager.savePlayerData(fromData);
dataManager.savePlayerData(toData); dataManager.savePlayerData(toData);
dataManager.insertLog(new CurrencyLog(fromData.getUuid(), fromData.getPlayerName(), type.getId(), "payOut", amount, fromBalance));
dataManager.insertLog(new CurrencyLog(toData.getUuid(), toData.getPlayerName(), type.getId(), "payIn", amount, toBalance));
sender.sendMessage( sender.sendMessage(
Message.paySuccess.toString() Message.paySuccess.toString()
.replace("%player%", toData.getPlayerName()) .replace("%player%", toData.getPlayerName())

View File

@@ -1,6 +1,7 @@
package cn.hamster3.currency.command.vault; package cn.hamster3.currency.command.vault;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
@@ -17,5 +18,6 @@ public class VaultSetCommand extends VaultAdminSetCommand {
@Override @Override
public void doSet(PlayerData data, CurrencyType type, double amount) { public void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), amount); data.setPlayerCurrency(type.getId(), amount);
dataManager.insertLog(new CurrencyLog(data.getUuid(), data.getPlayerName(), type.getId(), "set", amount, amount));
} }
} }

View File

@@ -1,6 +1,7 @@
package cn.hamster3.currency.command.vault; package cn.hamster3.currency.command.vault;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
@@ -16,6 +17,8 @@ public class VaultTakeCommand extends VaultAdminSetCommand {
@Override @Override
public void doSet(PlayerData data, CurrencyType type, double amount) { public void doSet(PlayerData data, CurrencyType type, double amount) {
data.setPlayerCurrency(type.getId(), data.getPlayerCurrency(type.getId()) - amount); double balance = data.getPlayerCurrency(type.getId()) - amount;
data.setPlayerCurrency(type.getId(), balance);
dataManager.insertLog(new CurrencyLog(data.getUuid(), data.getPlayerName(), type.getId(), "take", amount, balance));
} }
} }

View File

@@ -1,6 +1,7 @@
package cn.hamster3.currency.core; package cn.hamster3.currency.core;
import cn.hamster3.currency.HamsterCurrency; import cn.hamster3.currency.HamsterCurrency;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
@@ -9,21 +10,19 @@ import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.*;
import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap;
import java.util.Set;
import java.util.UUID;
import static cn.hamster3.currency.HamsterCurrency.getLogUtils; import static cn.hamster3.currency.HamsterCurrency.getLogUtils;
public class FileDataManager implements IDataManager { public class FileDataManager implements IDataManager {
private final HamsterCurrency plugin; private final HamsterCurrency plugin;
private final HashSet<PlayerData> playerData; private final Map<UUID, PlayerData> playerData;
private final HashSet<CurrencyType> currencyTypes; private final HashSet<CurrencyType> currencyTypes;
public FileDataManager(HamsterCurrency plugin) { public FileDataManager(HamsterCurrency plugin) {
this.plugin = plugin; this.plugin = plugin;
playerData = new HashSet<>(); playerData = new ConcurrentHashMap<>();
currencyTypes = new HashSet<>(); currencyTypes = new HashSet<>();
} }
@@ -41,7 +40,7 @@ public class FileDataManager implements IDataManager {
for (File file : files) { for (File file : files) {
try { try {
PlayerData data = new PlayerData(YamlConfiguration.loadConfiguration(file)); PlayerData data = new PlayerData(YamlConfiguration.loadConfiguration(file));
playerData.add(data); playerData.put(data.getUuid(), data);
} catch (Exception e) { } catch (Exception e) {
getLogUtils().error(e, "加载玩家存档文件 %s 时出现了一个异常!", file.getName()); getLogUtils().error(e, "加载玩家存档文件 %s 时出现了一个异常!", file.getName());
} }
@@ -53,7 +52,7 @@ public class FileDataManager implements IDataManager {
@Override @Override
public void onDisable() { public void onDisable() {
File dataFolder = new File(plugin.getDataFolder(), "PlayerData"); File dataFolder = new File(plugin.getDataFolder(), "PlayerData");
for (PlayerData data : playerData) { for (PlayerData data : playerData.values()) {
File dataFile = new File(dataFolder, data.getUuid().toString() + ".yml"); File dataFile = new File(dataFolder, data.getUuid().toString() + ".yml");
try { try {
data.saveToConfig().save(dataFile); data.saveToConfig().save(dataFile);
@@ -98,7 +97,7 @@ public class FileDataManager implements IDataManager {
// 只需要给没有存档的新玩家初始化一个存档数据即可 // 只需要给没有存档的新玩家初始化一个存档数据即可
PlayerData data = getPlayerData(uuid); PlayerData data = getPlayerData(uuid);
if (data == null) { if (data == null) {
playerData.add(new PlayerData(uuid)); playerData.put(uuid, new PlayerData(uuid));
} }
} }
@@ -109,35 +108,28 @@ public class FileDataManager implements IDataManager {
// 所以这里什么都不做 // 所以这里什么都不做
} }
@Override
public void insertLog(CurrencyLog log) {
}
@Override @Override
public PlayerData getPlayerData(UUID uuid) { public PlayerData getPlayerData(UUID uuid) {
synchronized (playerData) { return playerData.computeIfAbsent(uuid, PlayerData::new);
for (PlayerData data : playerData) {
if (uuid.equals(data.getUuid())) {
return data;
}
}
}
return null;
} }
@Override @Override
public PlayerData getPlayerData(String name) { public PlayerData getPlayerData(String name) {
synchronized (playerData) { for (PlayerData data : playerData.values()) {
for (PlayerData data : playerData) {
if (name.equalsIgnoreCase(data.getPlayerName())) { if (name.equalsIgnoreCase(data.getPlayerName())) {
return data; return data;
} }
} }
}
return null; return null;
} }
@Override @Override
public ArrayList<PlayerData> getPlayerData() { public ArrayList<PlayerData> getPlayerData() {
synchronized (playerData) { return new ArrayList<>(playerData.values());
return new ArrayList<>(playerData);
}
} }
@Override @Override

View File

@@ -17,7 +17,7 @@ public abstract class FileManager {
plugin.reloadConfig(); plugin.reloadConfig();
pluginConfig = plugin.getConfig(); pluginConfig = plugin.getConfig();
useBC = pluginConfig.getBoolean("useBC", false); useBC = pluginConfig.getBoolean("useBC", false);
mainServer = pluginConfig.getBoolean("datasource.template"); mainServer = pluginConfig.getBoolean("datasource.template", true);
setPluginConfig(pluginConfig); setPluginConfig(pluginConfig);
} }
@@ -37,8 +37,7 @@ public abstract class FileManager {
try { try {
Message.valueOf(key).setMessage(HamsterAPI.replaceColorCode(messagesConfig.getString(key))); Message.valueOf(key).setMessage(HamsterAPI.replaceColorCode(messagesConfig.getString(key)));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
HamsterCurrency.getLogUtils().warning("初始化消息设置 %s 时发生了一个异常: ", key); HamsterCurrency.getLogUtils().error(e, "初始化消息设置 %s 时发生了一个异常: ", key);
e.printStackTrace();
} }
} }
} }

View File

@@ -1,5 +1,6 @@
package cn.hamster3.currency.core; package cn.hamster3.currency.core;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
@@ -42,6 +43,8 @@ public interface IDataManager {
*/ */
void savePlayerData(PlayerData data); void savePlayerData(PlayerData data);
void insertLog(CurrencyLog log);
PlayerData getPlayerData(UUID uuid); PlayerData getPlayerData(UUID uuid);
PlayerData getPlayerData(String name); PlayerData getPlayerData(String name);

View File

@@ -2,6 +2,7 @@ package cn.hamster3.currency.core;
import cn.hamster3.api.HamsterAPI; import cn.hamster3.api.HamsterAPI;
import cn.hamster3.currency.HamsterCurrency; import cn.hamster3.currency.HamsterCurrency;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.CurrencyType; import cn.hamster3.currency.data.CurrencyType;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
import cn.hamster3.service.bukkit.api.ServiceMessageAPI; import cn.hamster3.service.bukkit.api.ServiceMessageAPI;
@@ -12,41 +13,56 @@ import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import javax.sql.DataSource;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.Connection; import java.sql.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static cn.hamster3.currency.HamsterCurrency.getLogUtils; import static cn.hamster3.currency.HamsterCurrency.getLogUtils;
public class SQLDataManager implements IDataManager { public class SQLDataManager implements IDataManager {
private final JsonParser parser;
private final Connection connection;
private final HamsterCurrency plugin; private final HamsterCurrency plugin;
private final HashSet<PlayerData> playerData; private final JsonParser parser;
private final DataSource datasource;
private final Map<UUID, PlayerData> playerData;
private final HashSet<CurrencyType> currencyTypes; private final HashSet<CurrencyType> currencyTypes;
@SuppressWarnings("ConstantConditions")
public SQLDataManager(HamsterCurrency plugin) throws SQLException, ClassNotFoundException { public SQLDataManager(HamsterCurrency plugin) throws SQLException, ClassNotFoundException {
this.plugin = plugin; this.plugin = plugin;
parser = new JsonParser(); parser = new JsonParser();
playerData = new HashSet<>(); playerData = new ConcurrentHashMap<>();
currencyTypes = new HashSet<>(); currencyTypes = new HashSet<>();
connection = HamsterAPI.getSQLConnection(FileManager.getPluginConfig().getConfigurationSection("datasource")); ConfigurationSection datasourceConfig = FileManager.getPluginConfig().getConfigurationSection("datasource");
datasource = HamsterAPI.getHikariDataSource(datasourceConfig);
Connection connection = datasource.getConnection();
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
statement.execute("CREATE TABLE IF NOT EXISTS hamster_currency_player_data(" + statement.execute("CREATE TABLE IF NOT EXISTS hamster_currency_player_data(" +
"uuid VARCHAR(36) PRIMARY KEY," + "uuid VARCHAR(36) PRIMARY KEY," +
"data TEXT" + "data TEXT" +
");"); ") CHARACTER SET = utf8mb4;");
statement.execute("CREATE TABLE IF NOT EXISTS hamster_currency_logs(" +
"uuid VARCHAR(36) NOT NULL," +
"player_name VARCHAR(36) NOT NULL," +
"type VARCHAR(36) NOT NULL," +
"action VARCHAR(36) NOT NULL," +
"amount DOUBLE NOT NULL," +
"balance DOUBLE NOT NULL," +
"time DATETIME NOT NULL," +
"INDEX idx_uuid(uuid)," +
"INDEX idx_name(player_name)" +
") CHARACTER SET = utf8mb4;");
statement.execute("CREATE TABLE IF NOT EXISTS hamster_currency_settings(" + statement.execute("CREATE TABLE IF NOT EXISTS hamster_currency_settings(" +
"title VARCHAR(64) PRIMARY KEY," + "title VARCHAR(64) PRIMARY KEY," +
"data TEXT" + "data TEXT" +
");"); ") CHARACTER SET = utf8mb4;");
statement.close(); statement.close();
connection.close();
} }
public void uploadConfigToSQL() { public void uploadConfigToSQL() {
@@ -56,6 +72,7 @@ public class SQLDataManager implements IDataManager {
getLogUtils().info("配置文件重载完成!"); getLogUtils().info("配置文件重载完成!");
try { try {
getLogUtils().info("将配置文件上传至数据库..."); getLogUtils().info("将配置文件上传至数据库...");
Connection connection = datasource.getConnection();
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
String data = Base64.getEncoder().encodeToString(config.saveToString().getBytes(StandardCharsets.UTF_8)); String data = Base64.getEncoder().encodeToString(config.saveToString().getBytes(StandardCharsets.UTF_8));
statement.executeUpdate(String.format( statement.executeUpdate(String.format(
@@ -64,18 +81,20 @@ public class SQLDataManager implements IDataManager {
data data
)); ));
statement.close(); statement.close();
connection.close();
getLogUtils().info("配置文件上传完成!"); getLogUtils().info("配置文件上传完成!");
} catch (SQLException e) { } catch (SQLException e) {
getLogUtils().error(e, "插件上传 pluginConfig 至数据库时遇到了一个异常: "); getLogUtils().error(e, "插件上传 pluginConfig 至数据库时遇到了一个异常: ");
} }
loadConfig(config); loadConfig(config);
ServiceMessageAPI.sendMessage("HamsterCurrency", "uploadConfigToSQL"); ServiceMessageAPI.sendServiceMessage("HamsterCurrency", "uploadConfigToSQL");
} }
@SuppressWarnings("SwitchStatementWithTooFewBranches") @SuppressWarnings("SwitchStatementWithTooFewBranches")
public void loadConfigFromSQL() { public void loadConfigFromSQL() {
try { try {
getLogUtils().info("从数据库中下载配置文件..."); getLogUtils().info("从数据库中下载配置文件...");
Connection connection = datasource.getConnection();
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery("SELECT * FROM hamster_currency_settings;"); ResultSet set = statement.executeQuery("SELECT * FROM hamster_currency_settings;");
while (set.next()) { while (set.next()) {
@@ -94,13 +113,13 @@ public class SQLDataManager implements IDataManager {
} }
} }
statement.close(); statement.close();
connection.close();
getLogUtils().info("配置文件下载完成!"); getLogUtils().info("配置文件下载完成!");
} catch (SQLException e) { } catch (SQLException e) {
getLogUtils().error(e, "插件从数据库中下载 pluginConfig 时遇到了一个异常: "); getLogUtils().error(e, "插件从数据库中下载 pluginConfig 时遇到了一个异常: ");
} }
} }
@SuppressWarnings("ConstantConditions")
private void loadConfig(FileConfiguration config) { private void loadConfig(FileConfiguration config) {
getLogUtils().info("加载配置文件..."); getLogUtils().info("加载配置文件...");
currencyTypes.clear(); currencyTypes.clear();
@@ -127,9 +146,9 @@ public class SQLDataManager implements IDataManager {
getLogUtils().info("玩家经济列名: %s", moneyCol); getLogUtils().info("玩家经济列名: %s", moneyCol);
getLogUtils().info("导入至经济类型: %s", currencyType); getLogUtils().info("导入至经济类型: %s", currencyType);
try { try {
Connection connection = datasource.getConnection();
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery(String.format("SELECT * FROM %s.%s;", database, table)); ResultSet set = statement.executeQuery(String.format("SELECT * FROM %s.%s;", database, table));
synchronized (playerData) {
while (set.next()) { while (set.next()) {
try { try {
UUID uuid = UUID.fromString(set.getString(uuidCol)); UUID uuid = UUID.fromString(set.getString(uuidCol));
@@ -138,7 +157,7 @@ public class SQLDataManager implements IDataManager {
PlayerData data = getPlayerData(uuid); PlayerData data = getPlayerData(uuid);
if (data == null) { if (data == null) {
data = new PlayerData(uuid, name); data = new PlayerData(uuid, name);
playerData.add(data); playerData.put(data.getUuid(), data);
} }
data.setPlayerCurrency(currencyType, money); data.setPlayerCurrency(currencyType, money);
getLogUtils().info("已从其他插件中加载了玩家 %s 的存档数据.", data.getUuid()); getLogUtils().info("已从其他插件中加载了玩家 %s 的存档数据.", data.getUuid());
@@ -146,17 +165,17 @@ public class SQLDataManager implements IDataManager {
getLogUtils().error(e, "导入某一条数据时发生了一个错误: "); getLogUtils().error(e, "导入某一条数据时发生了一个错误: ");
} }
} }
} for (PlayerData data : playerData.values()) {
for (PlayerData data : playerData) {
statement.executeUpdate(String.format( statement.executeUpdate(String.format(
"REPLACE INTO hamster_currency_player_data VALUES('%s', '%s');", "REPLACE INTO " + database + ".hamster_currency_player_data VALUES('%s', '%s');",
data.getUuid().toString(), data.getUuid().toString(),
data.saveToJson().toString() data.saveToJson().toString()
)); ));
getLogUtils().info("已保存玩家 %s 的存档数据.", data.getUuid()); getLogUtils().info("已保存玩家 %s 的存档数据.", data.getUuid());
ServiceMessageAPI.sendMessage("HamsterCurrency", "savedPlayerData", data.getUuid().toString()); ServiceMessageAPI.sendServiceMessage("HamsterCurrency", "savedPlayerData", data.getUuid().toString());
} }
statement.close(); statement.close();
connection.close();
} catch (SQLException e) { } catch (SQLException e) {
getLogUtils().error(e, "从其他插件中导入数据时发生了一个异常:"); getLogUtils().error(e, "从其他插件中导入数据时发生了一个异常:");
} }
@@ -167,22 +186,22 @@ public class SQLDataManager implements IDataManager {
public void onEnable() { public void onEnable() {
getLogUtils().info("从数据库中读取玩家数据..."); getLogUtils().info("从数据库中读取玩家数据...");
try { try {
Connection connection = datasource.getConnection();
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery("SELECT * FROM hamster_currency_player_data;"); ResultSet set = statement.executeQuery("SELECT * FROM hamster_currency_player_data;");
synchronized (playerData) {
while (set.next()) { while (set.next()) {
String uuid = set.getString("uuid"); String uuid = set.getString("uuid");
String string = set.getString("data"); String string = set.getString("data");
try { try {
PlayerData data = new PlayerData(parser.parse(string).getAsJsonObject()); PlayerData data = new PlayerData(parser.parse(string).getAsJsonObject());
playerData.add(data); playerData.put(data.getUuid(), data);
} catch (Exception e) { } catch (Exception e) {
getLogUtils().error(e, "从数据库中读取玩家 %s 的存档( %s )时出现了一个异常: ", uuid, string); getLogUtils().error(e, "从数据库中读取玩家 %s 的存档( %s )时出现了一个异常: ", uuid, string);
} }
} }
}
set.close(); set.close();
statement.close(); statement.close();
connection.close();
} catch (SQLException e) { } catch (SQLException e) {
getLogUtils().error(e, "从数据库中读取玩家数据时出现了一个异常:"); getLogUtils().error(e, "从数据库中读取玩家数据时出现了一个异常:");
} }
@@ -207,12 +226,13 @@ public class SQLDataManager implements IDataManager {
@Override @Override
public void reloadConfig() { public void reloadConfig() {
ServiceMessageAPI.sendMessage("HamsterCurrency", "reload"); ServiceMessageAPI.sendServiceMessage("HamsterCurrency", "reload");
} }
@Override @Override
public void loadPlayerData(UUID uuid) { public void loadPlayerData(UUID uuid) {
try { try {
Connection connection = datasource.getConnection();
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery(String.format( ResultSet set = statement.executeQuery(String.format(
"SELECT * FROM hamster_currency_player_data WHERE uuid='%s';", "SELECT * FROM hamster_currency_player_data WHERE uuid='%s';",
@@ -232,12 +252,11 @@ public class SQLDataManager implements IDataManager {
data = new PlayerData(uuid); data = new PlayerData(uuid);
getLogUtils().info("初始化玩家 %s 的存档数据.", data.getUuid()); getLogUtils().info("初始化玩家 %s 的存档数据.", data.getUuid());
} }
synchronized (playerData) { playerData.remove(data.getUuid());
playerData.remove(data); playerData.put(data.getUuid(), data);
playerData.add(data);
}
set.close(); set.close();
statement.close(); statement.close();
connection.close();
getLogUtils().info("已加载玩家 %s 的存档数据.", data.getUuid()); getLogUtils().info("已加载玩家 %s 的存档数据.", data.getUuid());
} catch (SQLException e) { } catch (SQLException e) {
getLogUtils().error(e, "加载玩家 %s 的存档数据时出错!", uuid); getLogUtils().error(e, "加载玩家 %s 的存档数据时出错!", uuid);
@@ -246,9 +265,9 @@ public class SQLDataManager implements IDataManager {
@Override @Override
public void savePlayerData(PlayerData data) { public void savePlayerData(PlayerData data) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
() -> {
try { try {
Connection connection = datasource.getConnection();
Statement statement = connection.createStatement(); Statement statement = connection.createStatement();
statement.executeUpdate(String.format( statement.executeUpdate(String.format(
"REPLACE INTO hamster_currency_player_data VALUES('%s', '%s');", "REPLACE INTO hamster_currency_player_data VALUES('%s', '%s');",
@@ -256,11 +275,12 @@ public class SQLDataManager implements IDataManager {
data.saveToJson().toString() data.saveToJson().toString()
)); ));
statement.close(); statement.close();
connection.close();
} catch (SQLException e) { } catch (SQLException e) {
getLogUtils().error(e, "保存玩家 %s 的存档数据时出错!", data.getUuid()); getLogUtils().error(e, "保存玩家 %s 的存档数据时出错!", data.getUuid());
} }
getLogUtils().info("已保存玩家 %s 的存档数据.", data.getUuid()); getLogUtils().info("已保存玩家 %s 的存档数据.", data.getUuid());
ServiceMessageAPI.sendMessage( ServiceMessageAPI.sendServiceMessage(
"HamsterCurrency", "HamsterCurrency",
"savedPlayerData", "savedPlayerData",
data.getUuid().toString() data.getUuid().toString()
@@ -268,35 +288,45 @@ public class SQLDataManager implements IDataManager {
}); });
} }
@Override
public void insertLog(CurrencyLog log) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
try (Connection connection = datasource.getConnection()) {
try (PreparedStatement statement = connection.prepareStatement(
"INSERT INTO hamster_currency_logs VALUES(?, ?, ?, ?, ?, ?, NOW());"
)) {
statement.setString(1, log.getUuid().toString());
statement.setString(2, log.getPlayerName());
statement.setString(3, log.getType());
statement.setString(4, log.getAction());
statement.setDouble(5, log.getAmount());
statement.setDouble(6, log.getBalance());
statement.executeUpdate();
}
} catch (SQLException e) {
getLogUtils().error(e);
}
});
}
@Override @Override
public PlayerData getPlayerData(UUID uuid) { public PlayerData getPlayerData(UUID uuid) {
synchronized (playerData) { return playerData.computeIfAbsent(uuid, PlayerData::new);
for (PlayerData data : playerData) {
if (uuid.equals(data.getUuid())) {
return data;
}
}
}
return null;
} }
@Override @Override
public PlayerData getPlayerData(String name) { public PlayerData getPlayerData(String name) {
synchronized (playerData) { for (PlayerData data : playerData.values()) {
for (PlayerData data : playerData) {
if (name.equalsIgnoreCase(data.getPlayerName())) { if (name.equalsIgnoreCase(data.getPlayerName())) {
return data; return data;
} }
} }
}
return null; return null;
} }
@Override @Override
public ArrayList<PlayerData> getPlayerData() { public ArrayList<PlayerData> getPlayerData() {
synchronized (playerData) { return new ArrayList<>(playerData.values());
return new ArrayList<>(playerData);
}
} }
@Override @Override

View File

@@ -0,0 +1,63 @@
package cn.hamster3.currency.data;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class CurrencyLog {
@NotNull
private final UUID uuid;
@NotNull
private final String playerName;
/**
* 货币类型
*/
@NotNull
private final String type;
/**
* 执行的操作
*/
@NotNull
private final String action;
/**
* 执行操作的数额
*/
private final double amount;
/**
* 执行操作后的余额
*/
private final double balance;
public CurrencyLog(@NotNull UUID uuid, @NotNull String playerName, @NotNull String type, @NotNull String action, double amount, double balance) {
this.uuid = uuid;
this.playerName = playerName;
this.type = type;
this.action = action;
this.amount = amount;
this.balance = balance;
}
public @NotNull UUID getUuid() {
return uuid;
}
public @NotNull String getPlayerName() {
return playerName;
}
public @NotNull String getType() {
return type;
}
public @NotNull String getAction() {
return action;
}
public double getAmount() {
return amount;
}
public double getBalance() {
return balance;
}
}

View File

@@ -1,5 +1,6 @@
package cn.hamster3.currency.data; package cn.hamster3.currency.data;
import cn.hamster3.service.bukkit.api.ServiceInfoAPI;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -30,14 +31,12 @@ public class PlayerData {
public PlayerData(JsonObject object) { public PlayerData(JsonObject object) {
uuid = UUID.fromString(object.get("uuid").getAsString()); uuid = UUID.fromString(object.get("uuid").getAsString());
OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); if (object.has("playerName")) {
if (player.getName() != null) {
playerName = player.getName();
} else if (object.has("playerName") && !object.get("playerName").isJsonNull()) {
playerName = object.get("playerName").getAsString(); playerName = object.get("playerName").getAsString();
} else { } else {
playerName = null; playerName = ServiceInfoAPI.getPlayerInfo(uuid).getPlayerName();
} }
playerCurrencies = new HashMap<>(); playerCurrencies = new HashMap<>();
JsonObject playerCurrenciesJson = object.getAsJsonObject("playerCurrencies"); JsonObject playerCurrenciesJson = object.getAsJsonObject("playerCurrencies");
for (Map.Entry<String, JsonElement> entry : playerCurrenciesJson.entrySet()) { for (Map.Entry<String, JsonElement> entry : playerCurrenciesJson.entrySet()) {
@@ -45,14 +44,13 @@ public class PlayerData {
} }
} }
@SuppressWarnings("ConstantConditions")
public PlayerData(ConfigurationSection config) { public PlayerData(ConfigurationSection config) {
uuid = UUID.fromString(config.getString("uuid")); uuid = UUID.fromString(config.getString("uuid"));
OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
if (player.getName() != null) { if (player.getName() != null) {
playerName = player.getName(); playerName = player.getName();
} else { } else {
playerName = config.getString("playerName"); playerName = config.getString("playerName").replace("\\'", "'");
} }
playerCurrencies = new HashMap<>(); playerCurrencies = new HashMap<>();
ConfigurationSection playerCurrenciesConfig = config.getConfigurationSection("playerCurrencies"); ConfigurationSection playerCurrenciesConfig = config.getConfigurationSection("playerCurrencies");

View File

@@ -0,0 +1,63 @@
package cn.hamster3.currency.event;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
@SuppressWarnings("unused")
public class CurrencyChangeEvent extends Event {
private static final HandlerList handlerList = new HandlerList();
@NotNull
private final UUID playerUUID;
@NotNull
private final String currencyID;
private final double oldAmount;
private final double newAmount;
public CurrencyChangeEvent(@NotNull UUID playerUUID, @NotNull String currencyID, double oldAmount, double newAmount) {
super(true);
this.playerUUID = playerUUID;
this.currencyID = currencyID;
this.oldAmount = oldAmount;
this.newAmount = newAmount;
}
public static HandlerList getHandlerList() {
return handlerList;
}
@NotNull
public UUID getPlayerUUID() {
return playerUUID;
}
@NotNull
public String getCurrencyID() {
return currencyID;
}
public double getOldAmount() {
return oldAmount;
}
public double getNewAmount() {
return newAmount;
}
@Override
public HandlerList getHandlers() {
return handlerList;
}
@Override
public String toString() {
return "CurrencyChangeEvent{" +
"playerUUID=" + playerUUID +
", currencyID='" + currencyID + '\'' +
", oldAmount=" + oldAmount +
", newAmount=" + newAmount +
'}';
}
}

View File

@@ -0,0 +1,50 @@
package cn.hamster3.currency.event.vault;
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class VaultEconomyGiveEvent extends Event {
private static final HandlerList handlerList = new HandlerList();
@NotNull
private final UUID uuid;
@NotNull
private final String currencyID;
private double amount;
public VaultEconomyGiveEvent(@NotNull UUID uuid, @NotNull String currencyID, double amount) {
super(!Bukkit.getServer().isPrimaryThread());
this.uuid = uuid;
this.currencyID = currencyID;
this.amount = amount;
}
public static HandlerList getHandlerList() {
return handlerList;
}
public @NotNull UUID getUuid() {
return uuid;
}
public @NotNull String getCurrencyID() {
return currencyID;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

View File

@@ -0,0 +1,50 @@
package cn.hamster3.currency.event.vault;
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class VaultEconomySeeEvent extends Event {
private static final HandlerList handlerList = new HandlerList();
@NotNull
private final UUID uuid;
@NotNull
private final String currencyID;
private double result;
public VaultEconomySeeEvent(@NotNull UUID uuid, @NotNull String currencyID, double result) {
super(!Bukkit.getServer().isPrimaryThread());
this.uuid = uuid;
this.currencyID = currencyID;
this.result = result;
}
public static HandlerList getHandlerList() {
return handlerList;
}
public @NotNull UUID getUuid() {
return uuid;
}
public @NotNull String getCurrencyID() {
return currencyID;
}
public double getResult() {
return result;
}
public void setResult(double result) {
this.result = result;
}
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

View File

@@ -0,0 +1,50 @@
package cn.hamster3.currency.event.vault;
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class VaultEconomyTakeEvent extends Event {
private static final HandlerList handlerList = new HandlerList();
@NotNull
private final UUID uuid;
@NotNull
private final String currencyID;
private double amount;
public VaultEconomyTakeEvent(@NotNull UUID uuid, @NotNull String currencyID, double amount) {
super(!Bukkit.getServer().isPrimaryThread());
this.uuid = uuid;
this.currencyID = currencyID;
this.amount = amount;
}
public static HandlerList getHandlerList() {
return handlerList;
}
public @NotNull UUID getUuid() {
return uuid;
}
public @NotNull String getCurrencyID() {
return currencyID;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
@Override
public HandlerList getHandlers() {
return handlerList;
}
}

View File

@@ -3,21 +3,22 @@ package cn.hamster3.currency.hook;
import cn.hamster3.currency.core.FileManager; import cn.hamster3.currency.core.FileManager;
import cn.hamster3.currency.core.IDataManager; import cn.hamster3.currency.core.IDataManager;
import cn.hamster3.currency.core.Message; import cn.hamster3.currency.core.Message;
import cn.hamster3.currency.data.CurrencyLog;
import cn.hamster3.currency.data.PlayerData; import cn.hamster3.currency.data.PlayerData;
import cn.hamster3.currency.event.vault.VaultEconomyGiveEvent;
import cn.hamster3.currency.event.vault.VaultEconomySeeEvent;
import cn.hamster3.currency.event.vault.VaultEconomyTakeEvent;
import net.milkbowl.vault.economy.AbstractEconomy; import net.milkbowl.vault.economy.AbstractEconomy;
import net.milkbowl.vault.economy.EconomyResponse; import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class VaultEconomyHook extends AbstractEconomy { public class VaultEconomyHook extends AbstractEconomy {
private static final EconomyResponse NOT_IMPLEMENTED_RESPONSE = private static final EconomyResponse NOT_IMPLEMENTED_RESPONSE = new EconomyResponse(
new EconomyResponse( 0, 0, EconomyResponse.ResponseType.NOT_IMPLEMENTED, "HamsterCurrency未实现该功能~"
0,
0,
EconomyResponse.ResponseType.NOT_IMPLEMENTED,
"HamsterCurrency未实现该功能~"
); );
private final IDataManager dataManager; private final IDataManager dataManager;
@@ -30,12 +31,20 @@ public class VaultEconomyHook extends AbstractEconomy {
return new EconomyResponse(amount, 0, EconomyResponse.ResponseType.FAILURE, "玩家账户不存在"); return new EconomyResponse(amount, 0, EconomyResponse.ResponseType.FAILURE, "玩家账户不存在");
} }
String type = FileManager.getVaultCurrencyType(); String type = FileManager.getVaultCurrencyType();
if (data.getPlayerCurrency(type) > 0 && data.getPlayerCurrency(type) + amount < 0) { VaultEconomyGiveEvent event = new VaultEconomyGiveEvent(data.getUuid(), type, amount);
Bukkit.getPluginManager().callEvent(event);
amount = event.getAmount();
if (amount == 0) {
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.SUCCESS, null);
}
double balance = data.getPlayerCurrency(type) + amount;
if (data.getPlayerCurrency(type) > 0 && balance < 0) {
return new EconomyResponse(amount, 0, EconomyResponse.ResponseType.FAILURE, "玩家金额超出上限"); return new EconomyResponse(amount, 0, EconomyResponse.ResponseType.FAILURE, "玩家金额超出上限");
} }
data.setPlayerCurrency(type, data.getPlayerCurrency(type) + amount); data.setPlayerCurrency(type, balance);
dataManager.savePlayerData(data); dataManager.savePlayerData(data);
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.SUCCESS, ""); dataManager.insertLog(new CurrencyLog(data.getUuid(), data.getPlayerName(), type, "add", amount, balance));
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.SUCCESS, null);
} }
protected EconomyResponse withdrawPlayer(PlayerData data, double amount) { protected EconomyResponse withdrawPlayer(PlayerData data, double amount) {
@@ -43,26 +52,37 @@ public class VaultEconomyHook extends AbstractEconomy {
return new EconomyResponse(amount, 0, EconomyResponse.ResponseType.FAILURE, "玩家账户不存在"); return new EconomyResponse(amount, 0, EconomyResponse.ResponseType.FAILURE, "玩家账户不存在");
} }
String type = FileManager.getVaultCurrencyType(); String type = FileManager.getVaultCurrencyType();
VaultEconomyTakeEvent event = new VaultEconomyTakeEvent(data.getUuid(), type, amount);
Bukkit.getPluginManager().callEvent(event);
amount = event.getAmount();
if (amount == 0) {
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.SUCCESS, null);
}
if (data.getPlayerCurrency(type) < amount) { if (data.getPlayerCurrency(type) < amount) {
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.FAILURE, "余额不足"); return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.FAILURE, "余额不足");
} }
data.setPlayerCurrency(type, data.getPlayerCurrency(type) - amount); double balance = data.getPlayerCurrency(type) - amount;
data.setPlayerCurrency(type, balance);
dataManager.savePlayerData(data); dataManager.savePlayerData(data);
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.SUCCESS, "扣款成功"); dataManager.insertLog(new CurrencyLog(data.getUuid(), data.getPlayerName(), type, "take", amount, balance));
return new EconomyResponse(amount, data.getPlayerCurrency(type), EconomyResponse.ResponseType.SUCCESS, null);
} }
private boolean has(PlayerData data, double amount) { private boolean has(PlayerData data, double amount) {
if (data == null) { if (data == null) {
return false; return false;
} }
return data.getPlayerCurrency(FileManager.getVaultCurrencyType()) >= amount; return getBalance(data) >= amount;
} }
private double getBalance(PlayerData data) { private double getBalance(PlayerData data) {
if (data == null) { if (data == null) {
return 0; return 0;
} }
return data.getPlayerCurrency(FileManager.getVaultCurrencyType()); double currency = data.getPlayerCurrency(FileManager.getVaultCurrencyType());
VaultEconomySeeEvent event = new VaultEconomySeeEvent(data.getUuid(), FileManager.getVaultCurrencyType(), currency);
Bukkit.getPluginManager().callEvent(event);
return event.getResult();
} }
@Override @Override

View File

@@ -6,18 +6,9 @@ useBC: true
# 若开启跨服模式则需要配置datasource # 若开启跨服模式则需要配置datasource
datasource: datasource:
driver: "com.mysql.jdbc.Driver" driver: "com.mysql.jdbc.Driver"
url: "jdbc:mysql://test3.hamster3.cn:3306?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false" url: "jdbc:mysql://localhost:3306/mc1.12.2-germ?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true"
user: Test user: root
password: Test123.. password: Root123...
database: Test
# 是否将这个服务器的配置文件设为模板
# 若设为trueconfig将会在服务器启动时自动上传至数据库
# 其他template为false的服务器将会在启动和重载时自动从数据库上下载config
# 可以节省一些config配置时的麻烦事情
# 但是请先保证template为true的服务器完全启动了再启动子服
# 如果觉得这样反而更麻烦也可以直接把所有服务器的template设为true
# 这样每个服务器都会使用自己本地的config文件了
template: true
currencyTypes: currencyTypes:
# 货币ID # 货币ID

View File

@@ -12,7 +12,7 @@ depend:
- HamsterAPI - HamsterAPI
softdepend: softdepend:
- HasmterService-Bukkit - HamsterService-Bukkit
- PlaceholderAPI - PlaceholderAPI
- PlayerPoints - PlayerPoints
- Vault - Vault
@@ -38,9 +38,11 @@ permissions:
default: op default: op
currency.set: currency.set:
default: op default: op
currency.look: currency.reload:
default: op
currency.see:
default: true default: true
currency.look.other: currency.see.other:
default: op default: op
currency.top: currency.top:
default: op default: op

View File

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

BIN
libs/PlayerPoints-2.1.3.jar Normal file

Binary file not shown.

View File

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

View File

@@ -0,0 +1,44 @@
plugins {
id 'java'
}
group 'cn.hamster3'
version '1.0.0-SNAPSHOT'
repositories {
maven {
url = "https://maven.airgame.net/maven-public/"
}
}
configurations {
implementationShade
implementation.extendsFrom implementationShade
}
dependencies {
// 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/org.xerial/sqlite-jdbc
implementationShade group: 'org.xerial', name: 'sqlite-jdbc', version: '3.36.0.3'
// 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-CMI"
manifest.attributes('Main-Class': 'cn.hamster3.transform.cmi.Main')
from([
configurations.implementationShade.collect {
it.isDirectory() ? it : zipTree(it)
},
rootProject.file("LICENSE")
])
duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
destinationDir(rootProject.buildDir)
}

View File

@@ -0,0 +1,114 @@
package cn.hamster3.transform.cmi;
import cn.hamster3.transform.cmi.data.PlayerData;
import java.io.File;
import java.sql.*;
import java.util.HashSet;
import java.util.Scanner;
import java.util.UUID;
public class Main {
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("请输入 cmi 数据库路径:");
String databasePath = scanner.nextLine();
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 databaseFile = new File(databasePath);
System.out.println("开始读取 CMI 数据.");
scanData(databaseFile);
System.out.println("开始保存数据到 HamsterCurrency 中.");
uploadData(host, port, user, password, database);
System.out.printf("数据保存完成,共计转移了 %d 个玩家数据存档.%n", playerData.size());
}
private static void scanData(File database) throws ClassNotFoundException, SQLException {
System.out.println("加载 sqlite 数据库驱动...");
Class.forName("org.sqlite.JDBC");
System.out.println("建立 sqlite 数据库连接...");
Connection connection = DriverManager.getConnection("jdbc:sqlite://" + database.getAbsolutePath());
Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery("SELECT player_uuid, username, Balance FROM main.users;");
while (set.next()) {
try {
UUID uuid = UUID.fromString(set.getString("player_uuid"));
String username = set.getString("username");
PlayerData data = getPlayerData(uuid, username);
double balance = set.getDouble("Balance");
if (data.getPlayerCurrency("金币") >= balance) {
System.out.printf("跳过 %s(%s) 的存档: %.2f >= %.2f金币%n", uuid, username,
data.getPlayerCurrency("金币"),
balance);
continue;
}
data.setPlayerCurrency("金币", balance);
System.out.printf("已加载 %s(%s) 的存档: %.2f金币%n", uuid, username, balance);
} catch (Exception e) {
e.printStackTrace();
}
}
statement.close();
connection.close();
System.out.printf("已加载 %d 个玩家的数据存档.%n", playerData.size());
}
private static void uploadData(String host, String port, String user, String password, String database) throws ClassNotFoundException, SQLException {
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 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.cmi.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.cmi.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();
}
}

View File

@@ -7,12 +7,11 @@ version '1.0.0-SNAPSHOT'
repositories { repositories {
maven { maven {
url = "https://maven.airgame.net/repository/maven-public/" url = "https://maven.airgame.net/maven-public/"
} }
} }
configurations { configurations {
implementationShade implementationShade
implementation.extendsFrom implementationShade implementation.extendsFrom implementationShade
} }

View File

@@ -49,7 +49,6 @@ public class Main {
System.out.println("加载 MySQL 数据库驱动..."); System.out.println("加载 MySQL 数据库驱动...");
Class.forName("com.mysql.cj.jdbc.Driver"); Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("建立 MySQL 数据库连接..."); System.out.println("建立 MySQL 数据库连接...");
Connection connection = DriverManager.getConnection( Connection connection = DriverManager.getConnection(
"jdbc:mysql://" + host + ":" + port + "?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false", "jdbc:mysql://" + host + ":" + port + "?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false",
user, user,