15 Commits

Author SHA1 Message Date
a4638be898 Merge branch 'refs/heads/dev' 2024-10-28 00:29:24 +08:00
e03ad98272 feat: 更新 NBT 前置版本 2024-10-28 00:29:04 +08:00
fbd6608864 feat(core-bukkit): 预加载 NBT API 2024-09-09 13:13:14 +08:00
85e9130575 fix: 修复日志问题 2024-08-17 09:46:57 +08:00
b17ad022d3 fix: 修复日志问题 2024-08-17 09:46:49 +08:00
85ce774752 style(core-bukkit): 精简代码 2024-08-12 11:38:46 +08:00
05b83dd248 feat: 优化代码 2024-08-09 06:07:35 +08:00
3955f352c6 feat: 添加 loadTranslation API 2024-08-09 04:15:23 +08:00
00d582a5ea perf: 优化 NBT API 调用 2024-08-09 04:15:05 +08:00
6beabf4ec4 build: 优化依赖 2024-08-09 04:14:35 +08:00
608a6ef289 feat: 增强部分API 2024-07-28 12:10:48 +08:00
a75853187c style: 移除无效异常信息 2024-07-25 20:23:04 +08:00
2263a74a77 feat: 兼容1.21 2024-07-25 20:22:32 +08:00
865812c524 Merge pull request 'Revert "perf: 优化代码"' (#4) from dev into master
Reviewed-on: #4
2024-03-24 13:42:34 +08:00
02836c9086 Merge pull request '1.3.3 稳定版' (#3) from dev into master
Reviewed-on: #3
2024-03-24 13:36:54 +08:00
19 changed files with 284 additions and 177 deletions

View File

@@ -38,6 +38,11 @@ subprojects {
}
tasks {
processResources {
filesMatching("update.yml") {
expand(rootProject.properties)
}
}
withType<JavaCompile> {
options.encoding = "UTF-8"
}
@@ -45,11 +50,6 @@ subprojects {
from(rootProject.file("LICENSE"))
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
processResources {
filesMatching("update.yml") {
expand(rootProject.properties)
}
}
build {
dependsOn(shadowJar)
}

View File

@@ -19,21 +19,15 @@ dependencies {
exclude(group = "org.jetbrains")
}
// https://mvnrepository.com/artifact/redis.clients/jedis
api("redis.clients:jedis:5.1.2") {
api("redis.clients:jedis:5.1.4") {
exclude(group = "com.google.code.gson")
exclude(group = "org.slf4j")
}
// https://mvnrepository.com/artifact/org.quartz-scheduler/quartz
api("org.quartz-scheduler:quartz:2.3.2") { isTransitive = false }
// https://mvnrepository.com/artifact/com.sun.mail/jakarta.mail
api("com.sun.mail:jakarta.mail:2.0.1")
// https://www.spigotmc.org/resources/nbt-api.7939/
implementation("de.tr7zw:item-nbt-api:+")
implementation("de.tr7zw:item-nbt-api:2.13.2")
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
implementation("com.zaxxer:HikariCP:4.0.3") { exclude(group = "org.slf4j") }
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib-jdk8
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.23") { exclude(group = "org.jetbrains") }
}
tasks {

View File

@@ -18,6 +18,7 @@ import cn.hamster3.mc.plugin.core.common.config.ConfigSection;
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
import cn.hamster3.mc.plugin.core.common.util.UpdateCheckUtils;
import com.zaxxer.hikari.HikariDataSource;
import de.tr7zw.changeme.nbtapi.NBT;
import lombok.Getter;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.Bukkit;
@@ -35,7 +36,6 @@ import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.logging.Level;
public class HamsterCorePlugin extends JavaPlugin {
@Getter
@@ -91,7 +91,7 @@ public class HamsterCorePlugin extends JavaPlugin {
CoreBukkitAPI.init(configFile);
simpleLogger.info("已初始化 CoreAPI");
} catch (Exception e) {
simpleLogger.log(Level.WARNING, "初始化 CoreAPI 出错", e);
simpleLogger.error(e, "初始化 CoreAPI 出错");
}
CoreMessage.init(this);
simpleLogger.info("已初始化语言文本");
@@ -103,6 +103,7 @@ public class HamsterCorePlugin extends JavaPlugin {
public void onEnable() {
long start = System.currentTimeMillis();
simpleLogger.info("仓鼠核心正在启动");
NBT.preloadApi();
audienceProvider = BukkitAudiences.create(this);
simpleLogger.info("已创建 AudienceProvider");
CoreCommand.INSTANCE.register();
@@ -114,6 +115,9 @@ public class HamsterCorePlugin extends JavaPlugin {
simpleLogger.info("已注册 CallbackListener");
Bukkit.getPluginManager().registerEvents(DebugListener.INSTANCE, this);
simpleLogger.info("已注册 DebugListener");
simpleLogger.info("Redis 启用状态: %b", CoreAPI.getInstance().isEnableRedis());
simpleLogger.info("Database 启用状态: %b", CoreAPI.getInstance().isEnableDatabase());
simpleLogger.info("已注册 DebugListener");
long time = System.currentTimeMillis() - start;
sync(() -> {
PointAPI.reloadPlayerPointAPIHook();

View File

@@ -11,6 +11,10 @@ public abstract class ChildCommand implements TabExecutor {
@NotNull
public abstract String getUsage();
public int getArgumentCount() {
return 0;
}
@NotNull
public abstract String getDescription();

View File

@@ -14,10 +14,10 @@ import java.util.stream.Collectors;
@SuppressWarnings("unused")
public abstract class ParentCommand extends ChildCommand {
@NotNull
private final List<ChildCommand> childCommands;
private final Map<String, ChildCommand> childCommands;
public ParentCommand() {
childCommands = new ArrayList<>();
childCommands = new LinkedHashMap<>();
}
@NotNull
@@ -33,8 +33,8 @@ public abstract class ParentCommand extends ChildCommand {
}
@NotNull
public List<ChildCommand> getChildCommands() {
return childCommands;
public Collection<ChildCommand> getChildCommands() {
return childCommands.values();
}
@NotNull
@@ -78,7 +78,7 @@ public abstract class ParentCommand extends ChildCommand {
@NotNull
public List<ChildCommand> getEndChildCommands() {
ArrayList<ChildCommand> list = new ArrayList<>();
for (ChildCommand command : childCommands) {
for (ChildCommand command : getChildCommands()) {
if (command instanceof ParentCommand) {
list.addAll(((ParentCommand) command).getEndChildCommands());
} else {
@@ -89,13 +89,16 @@ public abstract class ParentCommand extends ChildCommand {
}
public void addChildCommand(@NotNull ChildCommand command) {
childCommands.add(command);
if (childCommands.containsKey(command.getName())) {
throw new IllegalArgumentException("command " + command.getName() + " already exists!");
}
childCommands.put(command.getName(), command);
}
@NotNull
public Map<String, String> getCommandHelp(CommandSender sender) {
HashMap<String, String> map = new HashMap<>();
for (ChildCommand child : childCommands) {
Map<String, String> map = new LinkedHashMap<>();
for (ChildCommand child : getChildCommands()) {
if (!child.hasPermission(sender)) {
continue;
}
@@ -111,14 +114,12 @@ public abstract class ParentCommand extends ChildCommand {
public void sendHelp(@NotNull CommandSender sender) {
sender.sendMessage("§e==================== [ " + getName() + " 使用帮助] ====================");
Map<String, String> helpMap = getCommandHelp(sender);
int maxLength = helpMap.keySet().stream()
Map<String, String> map = getCommandHelp(sender);
int maxLength = map.keySet().stream()
.map(String::length)
.max(Integer::compareTo)
.orElse(-1);
ArrayList<Map.Entry<String, String>> list = new ArrayList<>(helpMap.entrySet());
list.sort(Map.Entry.comparingByKey());
for (Map.Entry<String, String> entry : list) {
for (Map.Entry<String, String> entry : map.entrySet()) {
sender.sendMessage(String.format("§a%-" + maxLength + "s - %s", entry.getKey(), entry.getValue()));
}
}
@@ -133,7 +134,7 @@ public abstract class ParentCommand extends ChildCommand {
sendHelp(sender);
return true;
}
for (ChildCommand childCommand : childCommands) {
for (ChildCommand childCommand : getChildCommands()) {
if (!childCommand.getName().equalsIgnoreCase(args[0])) {
continue;
}
@@ -141,6 +142,10 @@ public abstract class ParentCommand extends ChildCommand {
CoreMessage.COMMAND_NOT_HAS_PERMISSION.show(sender);
return true;
}
if (args.length - 1 < getArgumentCount()) {
sender.sendMessage(getUsage() + " " + childCommand.getUsage());
return true;
}
return childCommand.onCommand(sender, command, label, Arrays.copyOfRange(args, 1, args.length));
}
CoreMessage.COMMAND_NOT_FOUND.show(sender);
@@ -150,18 +155,18 @@ public abstract class ParentCommand extends ChildCommand {
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
if (args.length == 0) {
return childCommands.stream()
return getChildCommands().stream()
.filter(o -> o.hasPermission(sender))
.map(ChildCommand::getName)
.collect(Collectors.toList());
}
for (ChildCommand child : childCommands) {
for (ChildCommand child : getChildCommands()) {
if (args[0].equalsIgnoreCase(child.getName())) {
return child.onTabComplete(sender, command, alias, Arrays.copyOfRange(args, 1, args.length));
}
}
args[0] = args[0].toLowerCase();
return childCommands.stream()
return getChildCommands().stream()
.filter(o -> o.hasPermission(sender))
.map(ChildCommand::getName)
.filter(o -> o.toLowerCase().startsWith(args[0].toLowerCase()))

View File

@@ -5,6 +5,9 @@ import cn.hamster3.mc.plugin.core.bukkit.command.ParentCommand;
import cn.hamster3.mc.plugin.core.bukkit.constant.CoreMessage;
import cn.hamster3.mc.plugin.core.bukkit.util.CoreBukkitUtils;
import de.tr7zw.changeme.nbtapi.*;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBT;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTCompoundList;
import de.tr7zw.changeme.nbtapi.iface.ReadWriteNBTList;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -62,13 +65,12 @@ public class NBTCommand extends ParentCommand {
sender.sendMessage("§c你的手持物品为空");
return true;
}
NBTItem nbtItem = new NBTItem(stack);
sendNBTCompound(nbtItem, sender, 0);
ReadWriteNBT readWriteNBT = NBT.itemStackToNBT(stack);
sendNBTCompound(readWriteNBT, sender, 0);
return true;
}
@SuppressWarnings("ForLoopReplaceableByForEach")
private void sendNBTCompound(NBTCompound compound, CommandSender sender, int level) {
private void sendNBTCompound(ReadWriteNBT compound, CommandSender sender, int level) {
StringBuilder prefixBuilder = new StringBuilder();
for (int i = 0; i < level; i++) {
prefixBuilder.append(" ");
@@ -78,31 +80,31 @@ public class NBTCommand extends ParentCommand {
NBTType type = compound.getType(key);
switch (type) {
case NBTTagByte: {
sender.sendMessage(String.format("%s- %s:%d §e§l[%s]", space, key, compound.getByte(key), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%d §e§l[%s]", space, key, compound.getByte(key), NBT_TYPE_NAME.get(type)));
break;
}
case NBTTagShort: {
sender.sendMessage(String.format("%s- %s:%d §e§l[%s]", space, key, compound.getShort(key), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%d §e§l[%s]", space, key, compound.getShort(key), NBT_TYPE_NAME.get(type)));
break;
}
case NBTTagInt: {
sender.sendMessage(String.format("%s- %s:%d §e§l[%s]", space, key, compound.getInteger(key), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%d §e§l[%s]", space, key, compound.getInteger(key), NBT_TYPE_NAME.get(type)));
break;
}
case NBTTagLong: {
sender.sendMessage(String.format("%s- %s:%d §e§l[%s]", space, key, compound.getLong(key), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%d §e§l[%s]", space, key, compound.getLong(key), NBT_TYPE_NAME.get(type)));
break;
}
case NBTTagFloat: {
sender.sendMessage(String.format("%s- %s:%f §e§l[%s]", space, key, compound.getFloat(key), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%f §e§l[%s]", space, key, compound.getFloat(key), NBT_TYPE_NAME.get(type)));
break;
}
case NBTTagDouble: {
sender.sendMessage(String.format("%s- %s:%f §e§l[%s]", space, key, compound.getDouble(key), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%f §e§l[%s]", space, key, compound.getDouble(key), NBT_TYPE_NAME.get(type)));
break;
}
case NBTTagString: {
sender.sendMessage(String.format("%s- %s:%s §e§l[%s]", space, key, compound.getString(key), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%s §e§l[%s]", space, key, compound.getString(key), NBT_TYPE_NAME.get(type)));
break;
}
case NBTTagCompound: {
@@ -112,20 +114,20 @@ public class NBTCommand extends ParentCommand {
}
case NBTTagByteArray: {
byte[] array = compound.getByteArray(key);
sender.sendMessage(String.format("%s- %s:%s §e§l[%s]", space, key, Arrays.toString(array), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%s §e§l[%s]", space, key, Arrays.toString(array), NBT_TYPE_NAME.get(type)));
break;
}
case NBTTagIntArray: {
int[] array = compound.getIntArray(key);
sender.sendMessage(String.format("%s- %s:%s §e§l[%s]", space, key, Arrays.toString(array), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%s §e§l[%s]", space, key, Arrays.toString(array), NBT_TYPE_NAME.get(type)));
if (array != null && array.length == 4) {
sender.sendMessage(String.format("%s- %s:%s §e§l[uuid]", space, key, compound.getUUID(key)));
sender.sendMessage(String.format("%s- %s=%s §e§l[uuid]", space, key, compound.getUUID(key)));
}
break;
}
case NBTTagLongArray: {
long[] array = compound.getLongArray(key);
sender.sendMessage(String.format("%s- %s:%s §e§l[%s]", space, key, Arrays.toString(array), NBT_TYPE_NAME.get(type)));
sender.sendMessage(String.format("%s- %s=%s §e§l[%s]", space, key, Arrays.toString(array), NBT_TYPE_NAME.get(type)));
break;
}
case NBTTagList: {
@@ -137,7 +139,7 @@ public class NBTCommand extends ParentCommand {
String listSpace = space + " ";
switch (listType) {
case NBTTagString: {
NBTList<String> list = compound.getStringList(key);
ReadWriteNBTList<String> list = compound.getStringList(key);
for (String string : list) {
sender.sendMessage(String.format("%s- %s", listSpace, string));
}
@@ -145,7 +147,7 @@ public class NBTCommand extends ParentCommand {
}
case NBTTagIntArray: {
boolean all4Length = true;
NBTList<int[]> list = compound.getIntArrayList(key);
ReadWriteNBTList<int[]> list = compound.getIntArrayList(key);
for (int[] intArray : list) {
if (intArray.length != 4) {
all4Length = false;
@@ -153,7 +155,7 @@ public class NBTCommand extends ParentCommand {
}
}
if (all4Length) {
NBTList<UUID> uuidList = compound.getUUIDList(key);
ReadWriteNBTList<UUID> uuidList = compound.getUUIDList(key);
for (int i = 0; i < list.size(); i++) {
int[] intArray = list.get(i);
UUID uuid = uuidList.get(i);
@@ -169,37 +171,37 @@ public class NBTCommand extends ParentCommand {
break;
}
case NBTTagInt: {
NBTList<Integer> list = compound.getIntegerList(key);
ReadWriteNBTList<Integer> list = compound.getIntegerList(key);
for (Integer value : list) {
sender.sendMessage(String.format("%s- %d", listSpace, value));
}
break;
}
case NBTTagLong: {
NBTList<Long> list = compound.getLongList(key);
ReadWriteNBTList<Long> list = compound.getLongList(key);
for (Long value : list) {
sender.sendMessage(String.format("%s- %d", listSpace, value));
}
break;
}
case NBTTagFloat: {
NBTList<Float> list = compound.getFloatList(key);
ReadWriteNBTList<Float> list = compound.getFloatList(key);
for (Float value : list) {
sender.sendMessage(String.format("%s- %f", listSpace, value));
}
break;
}
case NBTTagDouble: {
NBTList<Double> list = compound.getDoubleList(key);
ReadWriteNBTList<Double> list = compound.getDoubleList(key);
for (Double value : list) {
sender.sendMessage(String.format("%s- %f", listSpace, value));
}
break;
}
case NBTTagCompound: {
NBTCompoundList compoundList = compound.getCompoundList(key);
ReadWriteNBTCompoundList compoundList = compound.getCompoundList(key);
for (int i = 0; i < compoundList.size(); i++) {
NBTListCompound listCompound = compoundList.get(i);
ReadWriteNBT listCompound = compoundList.get(i);
sendNBTCompound(listCompound, sender, level + 1);
}
}

View File

@@ -27,11 +27,10 @@ public class PointAPI {
public static void reloadPlayerPointAPIHook() {
Plugin plugin = Bukkit.getPluginManager().getPlugin("PlayerPoints");
if (plugin == null) {
HamsterCorePlugin.getSimpleLogger().warn("未检测到 PlayerPointAPI 插件");
return;
}
playerPointsAPI = ((PlayerPoints) plugin).getAPI();
HamsterCorePlugin.getSimpleLogger().info("PlayerPointAPI 挂接成功");
HamsterCorePlugin.getSimpleLogger().info("已挂接 PlayerPointAPI");
}
/**

View File

@@ -34,34 +34,23 @@ public class VaultAPI {
vaultEnabled = Bukkit.getPluginManager().isPluginEnabled("Vault");
BukkitSimpleLogger logger = HamsterCorePlugin.getSimpleLogger();
if (!vaultEnabled) {
logger.warn("未检测到 Vault 插件");
return;
}
logger.info("已连接 Vault");
logger.info("检测到服务器已安装 Vault 插件");
RegisteredServiceProvider<Chat> chatProvider = Bukkit.getServer().getServicesManager().getRegistration(Chat.class);
if (chatProvider != null) {
chat = chatProvider.getProvider();
logger.info("聊天系统挂接成功");
} else {
logger.warn("未检测到聊天系统");
}
RegisteredServiceProvider<Economy> economyProvider = Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
if (economyProvider != null) {
economy = economyProvider.getProvider();
logger.info("经济系统挂接成功");
} else {
logger.warn("未检测到经济系统");
}
RegisteredServiceProvider<Permission> permissionProvider = Bukkit.getServer().getServicesManager().getRegistration(Permission.class);
if (permissionProvider != null) {
permission = permissionProvider.getProvider();
logger.info("权限系统挂接成功");
} else {
logger.warn("未检测到权限插件");
}
logger.info("已完成 VaultAPI 挂载");
}

View File

@@ -3,10 +3,10 @@ package cn.hamster3.mc.plugin.core.bukkit.util;
import cn.hamster3.mc.plugin.core.bukkit.listener.CallbackListener;
import cn.hamster3.mc.plugin.core.common.data.DisplayMessage;
import com.google.gson.JsonObject;
import de.tr7zw.changeme.nbtapi.NBTContainer;
import de.tr7zw.changeme.nbtapi.NBTItem;
import de.tr7zw.changeme.nbtapi.NBT;
import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.title.Title;
import org.bukkit.Bukkit;
@@ -241,14 +241,35 @@ public final class CoreBukkitUtils {
@NotNull
public static DisplayMessage loadDisplayMessage(@NotNull ConfigurationSection config) {
DisplayMessage displayMessage = new DisplayMessage();
String miniMessage = config.getString("mini-message");
if (miniMessage != null) {
displayMessage.setMessage(MiniMessage.miniMessage().deserialize(miniMessage));
} else {
String message = config.getString("message");
if (message != null) {
displayMessage.setMessage(LegacyComponentSerializer.legacySection().deserialize(message));
}
}
String miniActionbar = config.getString("mini-actionbar");
if (miniActionbar != null) {
displayMessage.setActionbar(MiniMessage.miniMessage().deserialize(miniActionbar));
} else {
String actionbar = config.getString("actionbar");
if (actionbar != null) {
displayMessage.setActionbar(LegacyComponentSerializer.legacySection().deserialize(actionbar));
}
}
String miniTitle = config.getString("mini-title");
String miniSubtitle = config.getString("mini-subtitle");
if (miniTitle != null || miniSubtitle != null) {
displayMessage.setTitle(
MiniMessage.miniMessage().deserialize(miniTitle == null ? "" : miniTitle),
MiniMessage.miniMessage().deserialize(miniSubtitle == null ? "" : miniSubtitle),
config.getInt("fade-in", 10),
config.getInt("stay", 70),
config.getInt("fade-out", 20)
);
} else {
String title = config.getString("title");
String subtitle = config.getString("subtitle");
if (title != null || subtitle != null) {
@@ -259,6 +280,7 @@ public final class CoreBukkitUtils {
config.getInt("fade-out", 20)
);
}
}
String sound = config.getString("sound");
if (sound != null) {
displayMessage.setSound(sound,
@@ -330,7 +352,7 @@ public final class CoreBukkitUtils {
*/
@NotNull
public static String serializeItemStack(@NotNull ItemStack stack) {
return NBTItem.convertItemtoNBT(stack).toString();
return NBT.itemStackToNBT(stack).toString();
}
/**
@@ -341,7 +363,7 @@ public final class CoreBukkitUtils {
*/
@Nullable
public static ItemStack deserializeItemStack(@NotNull String string) {
return NBTItem.convertNBTtoItem(new NBTContainer(string));
return NBT.itemStackFromNBT(NBT.parseNBT(string));
}
/**

View File

@@ -61,9 +61,11 @@ public class MinecraftVersion {
@NotNull
public static Class<?> getNMSClass(@NotNull String className) throws ClassNotFoundException {
if (version1 >= 1 && version2 >= 17) {
if (version1 >= 1) {
if (version2 >= 17) {
return Class.forName("net.minecraft.server." + className);
}
}
String nmsVersion = getNMSVersion();
return Class.forName("net.minecraft.server." + nmsVersion + "." + className);
}
@@ -79,9 +81,14 @@ public class MinecraftVersion {
@NotNull
public static Class<?> getCraftBukkitClass(@NotNull String className) throws ClassNotFoundException {
if (version1 >= 1 && version2 >= 20 && version3 >= 6) {
if (version1 >= 1) {
if (version2 >= 21) {
return Class.forName("org.bukkit.craftbukkit." + className);
}
if (version2 == 20 && version3 >= 6) {
return Class.forName("org.bukkit.craftbukkit." + className);
}
}
String nmsVersion = getNMSVersion();
return Class.forName("org.bukkit.craftbukkit." + nmsVersion + "." + className);
}

View File

@@ -15,18 +15,12 @@ dependencies {
exclude(group = "org.jetbrains")
}
// https://mvnrepository.com/artifact/redis.clients/jedis
api("redis.clients:jedis:5.1.2") {
api("redis.clients:jedis:5.1.4") {
exclude(group = "com.google.code.gson")
exclude(group = "org.slf4j")
}
// https://mvnrepository.com/artifact/org.quartz-scheduler/quartz
api("org.quartz-scheduler:quartz:2.3.2") { isTransitive = false }
// https://mvnrepository.com/artifact/com.sun.mail/jakarta.mail
api("com.sun.mail:jakarta.mail:2.0.1")
implementation("com.zaxxer:HikariCP:4.0.3") { exclude(group = "org.slf4j") }
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib-jdk8
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.23") { exclude(group = "org.jetbrains") }
}
tasks {

View File

@@ -19,7 +19,6 @@ import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.logging.Level;
public class HamsterCorePlugin extends Plugin {
@Getter
@@ -51,7 +50,7 @@ public class HamsterCorePlugin extends Plugin {
CoreBungeeAPI.init(configFile);
simpleLogger.info("已初始化 CoreAPI");
} catch (Exception e) {
simpleLogger.log(Level.WARNING, "初始化 CoreAPI 出错", e);
simpleLogger.error(e, "初始化 CoreAPI 出错");
}
long time = System.currentTimeMillis() - start;
simpleLogger.info("仓鼠核心初始化完成,总计耗时 " + time + " ms");

View File

@@ -18,13 +18,10 @@ dependencies {
}
// https://mvnrepository.com/artifact/redis.clients/jedis
compileOnlyApi("redis.clients:jedis:5.1.2") {
compileOnlyApi("redis.clients:jedis:5.1.4") {
exclude(group = "com.google.code.gson")
exclude(group = "org.slf4j")
}
compileOnlyApi("org.quartz-scheduler:quartz:2.3.2") { isTransitive = false }
// https://mvnrepository.com/artifact/com.sun.mail/jakarta.mail
compileOnlyApi("com.sun.mail:jakarta.mail:2.0.1")
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
compileOnly("com.zaxxer:HikariCP:4.0.3") { isTransitive = false }

View File

@@ -5,6 +5,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
@SuppressWarnings({"unused", "unchecked"})
@Getter
@@ -71,16 +73,6 @@ public class ConfigSection {
return o.toString();
}
public List<String> getStringList(@NotNull String key) {
Object o = map.get(key);
if (o instanceof List) {
return (List<String>) o;
}
ArrayList<String> list = new ArrayList<>();
map.put(key, list);
return list;
}
public boolean getBoolean(@NotNull String key) {
String string = getString(key);
if (string == null) {
@@ -161,6 +153,45 @@ public class ConfigSection {
return Long.parseLong(string);
}
public <T> List<T> getList(@NotNull String key, Function<Object, T> function) {
ArrayList<T> list = new ArrayList<>();
Object object = map.get(key);
if (object instanceof List) {
List<?> mapList = (List<?>) object;
for (Object o : mapList) {
T result = function.apply(o);
list.add(result);
}
}
return list;
}
public List<String> getStringList(@NotNull String key) {
return getList(key, Object::toString);
}
public List<Integer> getIntegerList(@NotNull String key) {
return getList(key, o -> Integer.parseInt(o.toString()));
}
public <T> List<T> toList(BiFunction<ConfigSection, String, T> function) {
ArrayList<T> list = new ArrayList<>();
for (String key : getKeys()) {
T result = function.apply(this, key);
list.add(result);
}
return list;
}
public <T> Map<String, T> toMap(BiFunction<ConfigSection, String, T> function) {
HashMap<String, T> map = new HashMap<>();
for (String key : getKeys()) {
T result = function.apply(this, key);
map.put(key, result);
}
return map;
}
public void set(@NotNull String key, @Nullable Object value) {
if (value == null) {
map.remove(key);

View File

@@ -5,9 +5,12 @@ import org.yaml.snakeyaml.Yaml;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Consumer;
@SuppressWarnings({"unused", "VulnerableCodeUsages"})
@SuppressWarnings("unused")
public class YamlConfig extends ConfigSection {
public static final Yaml YAML_LOADER = new Yaml();
@@ -19,24 +22,83 @@ public class YamlConfig extends ConfigSection {
super(map);
}
public static List<YamlConfig> loadFolder(@NotNull File file) throws IOException {
if (file.isDirectory()) {
ArrayList<YamlConfig> list = new ArrayList<>();
for (File subFile : Objects.requireNonNull(file.listFiles())) {
list.addAll(loadFolder(subFile));
}
return list;
}
if (file.isFile() && file.getName().endsWith(".yml")) {
return Collections.singletonList(load(file));
}
return Collections.emptyList();
}
public static List<YamlConfig> loadFolder(@NotNull File file, @NotNull Consumer<Exception> exceptionHandler) {
if (file.isDirectory()) {
ArrayList<YamlConfig> list = new ArrayList<>();
for (File subFile : Objects.requireNonNull(file.listFiles())) {
list.addAll(loadFolder(subFile, exceptionHandler));
}
return list;
}
if (file.isFile() && file.getName().endsWith(".yml")) {
try {
YamlConfig load = load(file);
return Collections.singletonList(load);
} catch (IOException e) {
exceptionHandler.accept(e);
}
}
return Collections.emptyList();
}
public static YamlConfig load(@NotNull Path path) {
try {
return load(Files.newInputStream(path));
} catch (IOException e) {
return new YamlConfig();
}
}
public static YamlConfig load(@NotNull File file) throws IOException {
try (FileInputStream stream = new FileInputStream(file)) {
return load(stream);
}
}
public static YamlConfig load(@NotNull InputStream stream) throws IOException {
try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
return load(reader);
}
}
}
public static YamlConfig load(@NotNull Reader reader) {
Map<String, Object> load = YAML_LOADER.load(reader);
return new YamlConfig(load);
}
public void save(@NotNull Path path) throws IOException {
try (OutputStream stream = Files.newOutputStream(path)) {
save(stream);
}
}
public void save(@NotNull File file) throws IOException {
try (FileOutputStream stream = new FileOutputStream(file)) {
save(stream);
}
}
public void save(@NotNull OutputStream stream) throws IOException {
try (OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8)) {
save(writer);
}
}
public void save(@NotNull Writer writer) {
YAML_LOADER.dump(map, writer);
}
}
}
}

View File

@@ -1,6 +1,7 @@
package cn.hamster3.mc.plugin.core.common.util;
import cn.hamster3.mc.plugin.core.common.config.ConfigSection;
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
import com.google.gson.JsonObject;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@@ -8,42 +9,42 @@ import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.title.Title;
import net.kyori.adventure.translation.TranslationRegistry;
import org.jetbrains.annotations.NotNull;
import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.MessageFormat;
import java.time.Duration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
@SuppressWarnings("unused")
public final class CoreUtils {
private CoreUtils() {
}
public static void zipCompressionFolder(@NotNull File folder, @NotNull File zipFile) throws IOException {
try (ZipOutputStream stream = new ZipOutputStream(Files.newOutputStream(zipFile.toPath()))) {
putFileToZipStream(stream, "", folder);
@NotNull
public static DataSource getDataSource(@NotNull ConfigSection datasourceConfig) {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(datasourceConfig.getString("driver"));
hikariConfig.setJdbcUrl(datasourceConfig.getString("url"));
hikariConfig.setUsername(datasourceConfig.getString("username"));
hikariConfig.setPassword(datasourceConfig.getString("password"));
hikariConfig.setMaximumPoolSize(datasourceConfig.getInt("maximum-pool-size", 3));
hikariConfig.setMinimumIdle(datasourceConfig.getInt("minimum-idle", 1));
long keepAliveTime = datasourceConfig.getLong("keep-alive-time", 0);
if (keepAliveTime > 5000) {
hikariConfig.setKeepaliveTime(keepAliveTime);
}
}
public static void putFileToZipStream(@NotNull ZipOutputStream stream, @NotNull String path, @NotNull File file) throws IOException {
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files == null) {
throw new IOException();
}
for (File subFile : files) {
putFileToZipStream(stream, path + file.getName() + "/", subFile);
}
return;
}
ZipEntry entry = new ZipEntry(path + file.getName());
stream.putNextEntry(entry);
stream.write(Files.readAllBytes(file.toPath()));
stream.closeEntry();
hikariConfig.setIdleTimeout(datasourceConfig.getLong("idle-timeout", 10 * 60 * 1000));
hikariConfig.setMaxLifetime(datasourceConfig.getLong("max-lifetime", 30 * 60 * 1000));
hikariConfig.setValidationTimeout(datasourceConfig.getLong("validation-timeout", 5000));
hikariConfig.setPoolName(datasourceConfig.getString("name", "HamsterCore-Pool"));
return new HikariDataSource(hikariConfig);
}
/**
@@ -125,24 +126,30 @@ public final class CoreUtils {
);
}
@NotNull
public static DataSource getDataSource(@NotNull ConfigSection datasourceConfig) {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(datasourceConfig.getString("driver"));
hikariConfig.setJdbcUrl(datasourceConfig.getString("url"));
hikariConfig.setUsername(datasourceConfig.getString("username"));
hikariConfig.setPassword(datasourceConfig.getString("password"));
hikariConfig.setMaximumPoolSize(datasourceConfig.getInt("maximum-pool-size", 3));
hikariConfig.setMinimumIdle(datasourceConfig.getInt("minimum-idle", 1));
long keepAliveTime = datasourceConfig.getLong("keep-alive-time", 0);
if (keepAliveTime > 5000) {
hikariConfig.setKeepaliveTime(keepAliveTime);
public static void loadTranslation(@NotNull TranslationRegistry registry, @NotNull File folder) throws IOException {
for (File subFile : Objects.requireNonNull(folder.listFiles())) {
String filename = subFile.getName().split("\\.")[0];
String[] args = filename.split("_");
Locale locale = new Locale.Builder().setLanguage(args[0]).setRegion(args[1]).build();
YamlConfig config = YamlConfig.load(subFile);
Map<String, MessageFormat> map = loadTranslation(locale, config, "");
registry.registerAll(locale, map);
}
hikariConfig.setIdleTimeout(datasourceConfig.getLong("idle-timeout", 10 * 60 * 1000));
hikariConfig.setMaxLifetime(datasourceConfig.getLong("max-lifetime", 30 * 60 * 1000));
hikariConfig.setValidationTimeout(datasourceConfig.getLong("validation-timeout", 5000));
hikariConfig.setPoolName(datasourceConfig.getString("name", "HamsterCore-Pool"));
return new HikariDataSource(hikariConfig);
}
public static Map<String, MessageFormat> loadTranslation(@NotNull Locale locale, @NotNull ConfigSection config, @NotNull String prefix) {
HashMap<String, MessageFormat> result = new HashMap<>();
for (Map.Entry<String, Object> entry : config.getMap().entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof String) {
String string = (String) value;
result.put(prefix + key, new MessageFormat(string, locale));
} else if (value instanceof Map) {
loadTranslation(locale, config.getSectionOrCreate(key), "$prefix$key.");
}
}
return result;
}
/**

View File

@@ -19,20 +19,16 @@ public abstract class SimpleLogger {
try {
log(level, String.format(msg, args));
} catch (Exception e) {
log(Level.WARNING, "输出日志 " + msg + " 时遇到一个异常");
log(Level.WARNING, "日志参数: " + Arrays.toString(args));
log(Level.WARNING, "异常信息: ", e);
log(Level.WARNING, "输出日志 " + msg + Arrays.toString(args) + " 时遇到一个异常", e);
}
}
public void log(@NotNull Level level, @NotNull Throwable throwable, @NotNull String msg, @NotNull Object... args) {
try {
log(level, String.format(msg, args), throwable);
log(level, throwable, String.format(msg, args));
} catch (Exception e) {
log(Level.WARNING, "输出日志 " + msg + " 时遇到一个异常");
log(Level.WARNING, "日志参数: " + Arrays.toString(args));
log(Level.WARNING, "异常参数: ", throwable);
log(Level.WARNING, "异常信息: ", e);
log(Level.WARNING, "输出日志 " + msg + Arrays.toString(args) + " 时遇到一个异常", e);
log(Level.WARNING, "异常参数: ", e);
}
}

View File

@@ -8,23 +8,18 @@ dependencies {
annotationProcessor("com.velocitypowered:velocity-api:3.3.0-SNAPSHOT")
compileOnlyApi("net.kyori:adventure-platform-api:4.3.2") { isTransitive = false }
// https://mvnrepository.com/artifact/redis.clients/jedis
api("redis.clients:jedis:5.1.2") {
api("redis.clients:jedis:5.1.4") {
exclude(group = "com.google.code.gson")
exclude(group = "org.slf4j")
}
// https://mvnrepository.com/artifact/org.quartz-scheduler/quartz
api("org.quartz-scheduler:quartz:2.3.2") { isTransitive = false }
// https://mvnrepository.com/artifact/com.sun.mail/jakarta.mail
api("com.sun.mail:jakarta.mail:2.0.1")
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
implementation("com.zaxxer:HikariCP:5.1.0") { isTransitive = false }
// https://mvnrepository.com/artifact/com.mysql/mysql-connector-j
runtimeOnly("com.mysql:mysql-connector-j:8.3.0")
// https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-stdlib
runtimeOnly("org.jetbrains.kotlin:kotlin-stdlib:1.9.23") { exclude(group = "org.jetbrains") }
}
sourceSets.create("templates") {

View File

@@ -65,7 +65,7 @@ public class HamsterCorePlugin {
CoreVelocityAPI.init(configFile);
simpleLogger.info("已初始化 CoreAPI");
} catch (Exception e) {
simpleLogger.error("初始化 CoreAPI 出错", e);
simpleLogger.error(e, "初始化 CoreAPI 出错");
}
long time = System.currentTimeMillis() - start;
simpleLogger.info("仓鼠核心初始化完成,总计耗时 " + time + " ms");