From ffc2ecc2ee3fd10dcef28bb8c6cc52e683ab59d8 Mon Sep 17 00:00:00 2001 From: MiniDay <372403923@qq.com> Date: Tue, 12 Mar 2024 19:40:43 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E7=B2=BE=E7=AE=80=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 +- core-bukkit/build.gradle.kts | 2 +- .../plugin/core/bukkit/HamsterCorePlugin.java | 17 +- .../plugin/core/bukkit/api/CoreBukkitAPI.java | 75 ++------ .../core/bukkit/constant/CoreMessage.java | 2 +- .../core/bukkit/util/CoreBukkitUtils.java | 4 +- .../core/bukkit/util/MinecraftVersion.java | 2 +- .../plugin/core/bungee/HamsterCorePlugin.java | 21 ++- .../plugin/core/bungee/api/CoreBungeeAPI.java | 72 ++------ .../core/bungee/util/CoreBungeeCordUtils.java | 29 ++- core-common/build.gradle.kts | 5 + .../mc/plugin/core/common/api/CoreAPI.java | 60 ++++++- .../core/common/config/ConfigSection.java | 170 ++++++++++++++++++ .../plugin/core/common/config/YamlConfig.java | 38 ++++ .../core/common/thread/CountdownThread.java | 27 +-- .../plugin/core/common/util/Calculator.java | 96 +++++----- .../mc/plugin/core/common/util/CoreUtils.java | 2 + 17 files changed, 401 insertions(+), 223 deletions(-) create mode 100644 core-common/src/main/java/cn/hamster3/mc/plugin/core/common/config/ConfigSection.java create mode 100644 core-common/src/main/java/cn/hamster3/mc/plugin/core/common/config/YamlConfig.java diff --git a/build.gradle.kts b/build.gradle.kts index 0eb33a0..b29cebc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } group = "cn.hamster3.mc.plugin" -version = "1.2.3" +version = "1.2.4" subprojects { apply { diff --git a/core-bukkit/build.gradle.kts b/core-bukkit/build.gradle.kts index f77dc5c..d3b41d9 100644 --- a/core-bukkit/build.gradle.kts +++ b/core-bukkit/build.gradle.kts @@ -4,7 +4,7 @@ dependencies { implementation(project(":core-common")) { isTransitive = false } - compileOnly("org.spigotmc:spigot-api:1.20.2-R0.1-SNAPSHOT") + compileOnly("org.spigotmc:spigot-api:1.20.4-R0.1-SNAPSHOT") implementation("de.tr7zw:item-nbt-api:2.12.3-SNAPSHOT") compileOnly("net.milkbowl.vault:VaultAPI:1.7") { diff --git a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/HamsterCorePlugin.java b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/HamsterCorePlugin.java index 3681a41..a8c2591 100644 --- a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/HamsterCorePlugin.java +++ b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/HamsterCorePlugin.java @@ -23,6 +23,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; +import java.io.File; import java.util.logging.Logger; @SuppressWarnings("CallToPrintStackTrace") @@ -56,17 +57,19 @@ public class HamsterCorePlugin extends JavaPlugin { @Override public void onLoad() { + instance = this; long start = System.currentTimeMillis(); Logger logger = getLogger(); logger.info("仓鼠核心正在初始化"); logger.info("Minecraft 版本: " + MinecraftVersion.getMCVersion()); - logger.info("nms 版本: " + MinecraftVersion.getNMSVersion()); - instance = this; - saveDefaultConfig(); - reloadConfig(); - logger.info("已读取配置文件"); + logger.info("NMS 版本: " + MinecraftVersion.getNMSVersion()); try { - CoreBukkitAPI.init(); + File dataFolder = getDataFolder(); + if (dataFolder.mkdir()) { + logger.info("已生成插件存档文件夹"); + } + File file = new File(dataFolder, "config.yml"); + CoreBukkitAPI.init(file); logger.info("已初始化 CoreAPI"); } catch (Exception e) { logger.warning("初始化 CoreAPI 出错"); @@ -108,7 +111,7 @@ public class HamsterCorePlugin extends JavaPlugin { Logger logger = getLogger(); CoreAPI.getInstance().getRedisClient().close(); logger.info("已关闭 Redis 连接池"); - CoreBukkitAPI.getInstance().getDataSource().close(); + CoreAPI.getInstance().getHikariDataSource().close(); logger.info("已关闭数据库连接池"); CoreAPI.getInstance().getExecutorService().shutdownNow(); logger.info("已关闭 ExecutorService 线程池"); diff --git a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/api/CoreBukkitAPI.java b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/api/CoreBukkitAPI.java index 8702fd1..8bcc78e 100644 --- a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/api/CoreBukkitAPI.java +++ b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/api/CoreBukkitAPI.java @@ -5,35 +5,32 @@ import cn.hamster3.mc.plugin.core.bukkit.impl.ItemStackAdapter; import cn.hamster3.mc.plugin.core.bukkit.impl.PotionEffectAdapter; import cn.hamster3.mc.plugin.core.bukkit.util.MinecraftVersion; import cn.hamster3.mc.plugin.core.common.api.CoreAPI; +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.data.DisplayMessage; import cn.hamster3.mc.plugin.core.common.impl.ComponentTypeAdapter; import cn.hamster3.mc.plugin.core.common.impl.MessageTypeAdapter; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import de.tr7zw.changeme.nbtapi.utils.nmsmappings.ClassWrapper; -import io.lettuce.core.RedisClient; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.Component; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.jetbrains.annotations.NotNull; +import java.io.File; +import java.io.IOException; +import java.util.logging.Logger; + @SuppressWarnings("unused") public final class CoreBukkitAPI extends CoreAPI { @NotNull private final Gson gson; @NotNull private final Gson humanGson; - @NotNull - private final RedisClient redisClient; - @NotNull - private final HikariDataSource datasource; - private CoreBukkitAPI() { + private CoreBukkitAPI(@NotNull ConfigSection config) { + super(config); gson = new GsonBuilder() .registerTypeAdapter(Component.class, ComponentTypeAdapter.INSTANCE) .registerTypeAdapter(DisplayMessage.class, MessageTypeAdapter.INSTANCE) @@ -45,67 +42,28 @@ public final class CoreBukkitAPI extends CoreAPI { .registerTypeAdapter(Component.class, ComponentTypeAdapter.INSTANCE) .registerTypeAdapter(DisplayMessage.class, MessageTypeAdapter.INSTANCE) .registerTypeAdapter(ItemStack.class, ItemStackAdapter.INSTANCE) - .registerTypeAdapter(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), ItemStackAdapter.INSTANCE) + .registerTypeAdapter(MinecraftVersion.getCraftBukkitClassSilent("inventory.CraftItemStack"), ItemStackAdapter.INSTANCE) .registerTypeAdapter(PotionEffect.class, PotionEffectAdapter.INSTANCE) .serializeNulls() .setPrettyPrinting() .create(); - - HamsterCorePlugin plugin = HamsterCorePlugin.getInstance(); - FileConfiguration config = plugin.getConfig(); - - HamsterCorePlugin.getInstance().getLogger().info("正在创建 redis 客户端"); - redisClient = RedisClient.create(config.getString("redis-url")); - HamsterCorePlugin.getInstance().getLogger().info("redis 客户端创建完成"); - - ConfigurationSection datasourceConfig = config.getConfigurationSection("datasource"); - if (datasourceConfig == null) { - throw new IllegalArgumentException("配置文件中未找到 datasource 节点"); - } - HamsterCorePlugin.getInstance().getLogger().info("正在创建数据库连接池"); - 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); - } - 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("HamsterCore-Pool"); - datasource = new HikariDataSource(hikariConfig); - HamsterCorePlugin.getInstance().getLogger().info("数据库连接池创建完成"); } public static CoreBukkitAPI getInstance() { return (CoreBukkitAPI) instance; } - public static void init() { + public static void init(@NotNull File configFile) throws IOException { if (instance != null) { return; } - instance = new CoreBukkitAPI(); + YamlConfig config = YamlConfig.load(configFile); + instance = new CoreBukkitAPI(config); } @Override - public @NotNull BukkitAudiences getAudienceProvider() { - return HamsterCorePlugin.getInstance().getAudienceProvider(); - } - - @Override - public @NotNull HikariDataSource getDataSource() { - return datasource; - } - - @Override - public @NotNull RedisClient getRedisClient() { - return redisClient; + public @NotNull Logger getLogger() { + return HamsterCorePlugin.getInstance().getLogger(); } @Override @@ -117,4 +75,9 @@ public final class CoreBukkitAPI extends CoreAPI { public @NotNull Gson getHumanGson() { return humanGson; } + + @Override + public @NotNull BukkitAudiences getAudienceProvider() { + return HamsterCorePlugin.getInstance().getAudienceProvider(); + } } diff --git a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/constant/CoreMessage.java b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/constant/CoreMessage.java index 719a746..8337548 100644 --- a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/constant/CoreMessage.java +++ b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/constant/CoreMessage.java @@ -74,7 +74,7 @@ public enum CoreMessage { public static void init(@NotNull Plugin plugin) { File dataFolder = plugin.getDataFolder(); if (dataFolder.mkdirs()) { - plugin.getLogger().info("已生成插件存档文件夹 " + dataFolder.getName()); + plugin.getLogger().info("已生成插件存档文件夹"); } File file = new File(dataFolder, "messages.yml"); YamlConfiguration config = new YamlConfiguration(); diff --git a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/util/CoreBukkitUtils.java b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/util/CoreBukkitUtils.java index 25d428d..9bcf789 100644 --- a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/util/CoreBukkitUtils.java +++ b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/util/CoreBukkitUtils.java @@ -307,7 +307,7 @@ public final class CoreBukkitUtils { File file = new File(plugin.getDataFolder(), filename); File parentFile = file.getParentFile(); if (parentFile.mkdirs()) { - plugin.getLogger().info("已生成插件存档文件夹 " + parentFile.getName()); + plugin.getLogger().info("已生成插件存档文件夹"); } if (!file.exists()) { plugin.getLogger().info("生成配置文件: " + filename); @@ -367,6 +367,7 @@ public final class CoreBukkitUtils { } @NotNull + @SuppressWarnings("deprecation") public static JsonObject serializePotionEffect(@NotNull PotionEffect effect) { JsonObject object = new JsonObject(); object.addProperty("type", effect.getType().getName()); @@ -376,6 +377,7 @@ public final class CoreBukkitUtils { } @NotNull + @SuppressWarnings("deprecation") public static PotionEffect deserializePotionEffect(@NotNull JsonObject object) { //noinspection ConstantConditions return new PotionEffect( diff --git a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/util/MinecraftVersion.java b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/util/MinecraftVersion.java index bc2bcda..1369664 100644 --- a/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/util/MinecraftVersion.java +++ b/core-bukkit/src/main/java/cn/hamster3/mc/plugin/core/bukkit/util/MinecraftVersion.java @@ -22,7 +22,7 @@ public class MinecraftVersion { } /** - * 与当前服务端运行的 mc 版本号对比 + * 与当前服务端运行的 Minecraft 版本号对比 *

* 1: 当前版本高于输入版本号 *

diff --git a/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/HamsterCorePlugin.java b/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/HamsterCorePlugin.java index f88f554..87f30ee 100644 --- a/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/HamsterCorePlugin.java +++ b/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/HamsterCorePlugin.java @@ -6,6 +6,9 @@ import lombok.Getter; import net.kyori.adventure.platform.bungeecord.BungeeAudiences; import net.md_5.bungee.api.plugin.Plugin; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.logging.Logger; @SuppressWarnings("CallToPrintStackTrace") @@ -17,12 +20,24 @@ public class HamsterCorePlugin extends Plugin { @Override public void onLoad() { - long start = System.currentTimeMillis(); instance = this; + long start = System.currentTimeMillis(); Logger logger = getLogger(); logger.info("仓鼠核心正在初始化"); try { - CoreBungeeAPI.init(); + File dataFolder = getDataFolder(); + if (dataFolder.mkdir()) { + logger.info("已生成插件存档文件夹"); + } + File configFile = new File(dataFolder, "config.yml"); + if (!configFile.exists()) { + Files.copy( + getResourceAsStream("config.yml"), + configFile.toPath(), + StandardCopyOption.REPLACE_EXISTING + ); + } + CoreBungeeAPI.init(configFile); logger.info("已初始化 CoreAPI"); } catch (Exception e) { logger.warning("初始化 CoreAPI 出错"); @@ -49,7 +64,7 @@ public class HamsterCorePlugin extends Plugin { Logger logger = getLogger(); CoreAPI.getInstance().getRedisClient().close(); logger.info("已关闭 Redis 连接池"); - CoreBungeeAPI.getInstance().getDataSource().close(); + CoreAPI.getInstance().getHikariDataSource().close(); logger.info("已关闭数据库连接池"); CoreAPI.getInstance().getExecutorService().shutdownNow(); logger.info("已关闭 ExecutorService 线程池"); diff --git a/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/api/CoreBungeeAPI.java b/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/api/CoreBungeeAPI.java index 07b45b2..cb8c4da 100644 --- a/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/api/CoreBungeeAPI.java +++ b/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/api/CoreBungeeAPI.java @@ -1,33 +1,31 @@ package cn.hamster3.mc.plugin.core.bungee.api; import cn.hamster3.mc.plugin.core.bungee.HamsterCorePlugin; -import cn.hamster3.mc.plugin.core.bungee.util.CoreBungeeCordUtils; import cn.hamster3.mc.plugin.core.common.api.CoreAPI; +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.data.DisplayMessage; import cn.hamster3.mc.plugin.core.common.impl.ComponentTypeAdapter; import cn.hamster3.mc.plugin.core.common.impl.MessageTypeAdapter; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import io.lettuce.core.RedisClient; import net.kyori.adventure.platform.bungeecord.BungeeAudiences; import net.kyori.adventure.text.Component; -import net.md_5.bungee.config.Configuration; import org.jetbrains.annotations.NotNull; +import java.io.File; +import java.io.IOException; +import java.util.logging.Logger; + @SuppressWarnings("unused") public final class CoreBungeeAPI extends CoreAPI { @NotNull private final Gson gson; @NotNull private final Gson humanGson; - @NotNull - private final RedisClient redisClient; - @NotNull - private final HikariDataSource datasource; - private CoreBungeeAPI() { + private CoreBungeeAPI(@NotNull ConfigSection config) { + super(config); gson = new GsonBuilder() .registerTypeAdapter(Component.class, ComponentTypeAdapter.INSTANCE) .registerTypeAdapter(DisplayMessage.class, MessageTypeAdapter.INSTANCE) @@ -38,62 +36,23 @@ public final class CoreBungeeAPI extends CoreAPI { .serializeNulls() .setPrettyPrinting() .create(); - - HamsterCorePlugin plugin = HamsterCorePlugin.getInstance(); - Configuration config = CoreBungeeCordUtils.getPluginConfig(plugin); - - HamsterCorePlugin.getInstance().getLogger().info("正在创建 redis 客户端"); - redisClient = RedisClient.create(config.getString("redis-url")); - HamsterCorePlugin.getInstance().getLogger().info("redis 客户端创建完成"); - - Configuration datasourceConfig = config.getSection("datasource"); - if (datasourceConfig == null) { - throw new IllegalArgumentException("配置文件中未找到 datasource 节点"); - } - HamsterCorePlugin.getInstance().getLogger().info("正在创建数据库连接池"); - 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); - } - 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("HamsterCore-Pool"); - datasource = new HikariDataSource(hikariConfig); - HamsterCorePlugin.getInstance().getLogger().info("数据库连接池创建完成"); } public static CoreBungeeAPI getInstance() { return (CoreBungeeAPI) instance; } - public static void init() { + public static void init(@NotNull File configFile) throws IOException { if (instance != null) { return; } - instance = new CoreBungeeAPI(); + YamlConfig config = YamlConfig.load(configFile); + instance = new CoreBungeeAPI(config); } @Override - public @NotNull BungeeAudiences getAudienceProvider() { - return HamsterCorePlugin.getInstance().getAudienceProvider(); - } - - @Override - public @NotNull HikariDataSource getDataSource() { - return datasource; - } - - @Override - public @NotNull RedisClient getRedisClient() { - return redisClient; + public @NotNull Logger getLogger() { + return HamsterCorePlugin.getInstance().getLogger(); } @Override @@ -105,4 +64,9 @@ public final class CoreBungeeAPI extends CoreAPI { public @NotNull Gson getHumanGson() { return humanGson; } + + @Override + public @NotNull BungeeAudiences getAudienceProvider() { + return HamsterCorePlugin.getInstance().getAudienceProvider(); + } } diff --git a/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/util/CoreBungeeCordUtils.java b/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/util/CoreBungeeCordUtils.java index 83c666e..5526be1 100644 --- a/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/util/CoreBungeeCordUtils.java +++ b/core-bungee/src/main/java/cn/hamster3/mc/plugin/core/bungee/util/CoreBungeeCordUtils.java @@ -8,8 +8,8 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Files; +import java.nio.file.StandardCopyOption; @SuppressWarnings("unused") public final class CoreBungeeCordUtils { @@ -32,7 +32,7 @@ public final class CoreBungeeCordUtils { public static Configuration getPluginConfig(@NotNull Plugin plugin) { File configFile = new File(plugin.getDataFolder(), "config.yml"); if (!configFile.exists()) { - return saveDefaultConfig(plugin); + return saveConfig(plugin); } try { return ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); @@ -45,7 +45,7 @@ public final class CoreBungeeCordUtils { public static Configuration getPluginConfig(@NotNull Plugin plugin, @NotNull String filename) { File configFile = new File(plugin.getDataFolder(), filename); if (!configFile.exists()) { - return saveDefaultConfig(plugin, filename); + return saveConfig(plugin, filename); } try { return ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); @@ -55,29 +55,22 @@ public final class CoreBungeeCordUtils { } @NotNull - public static Configuration saveDefaultConfig(@NotNull Plugin plugin) { - if (plugin.getDataFolder().mkdir()) { - plugin.getLogger().info("已生成插件存档文件夹"); - } - File configFile = new File(plugin.getDataFolder(), "config.yml"); - try { - InputStream in = plugin.getResourceAsStream("config.yml"); - Files.copy(in, configFile.toPath()); - return ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); - } catch (Exception e) { - throw new RuntimeException(e); - } + public static Configuration saveConfig(@NotNull Plugin plugin) { + return saveConfig(plugin, "config.yml"); } @NotNull - public static Configuration saveDefaultConfig(@NotNull Plugin plugin, @NotNull String filename) { + public static Configuration saveConfig(@NotNull Plugin plugin, @NotNull String filename) { if (plugin.getDataFolder().mkdir()) { plugin.getLogger().info("已生成插件存档文件夹"); } File configFile = new File(plugin.getDataFolder(), filename); try { - InputStream in = plugin.getResourceAsStream(filename); - Files.copy(in, configFile.toPath()); + Files.copy( + plugin.getResourceAsStream(filename), + configFile.toPath(), + StandardCopyOption.REPLACE_EXISTING + ); return ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile); } catch (Exception e) { throw new RuntimeException(e); diff --git a/core-common/build.gradle.kts b/core-common/build.gradle.kts index 9445066..9e9a824 100644 --- a/core-common/build.gradle.kts +++ b/core-common/build.gradle.kts @@ -2,6 +2,8 @@ dependencies { compileOnly("com.google.code.gson:gson:2.8.0") + // https://mvnrepository.com/artifact/org.yaml/snakeyaml + compileOnly("org.yaml:snakeyaml:1.19") implementation("net.kyori:adventure-platform-api:4.3.2") { exclude(group = "org.jetbrains") @@ -11,6 +13,9 @@ dependencies { exclude(group = "com.google.code.gson") } + + // https://mvnrepository.com/artifact/com.zaxxer/HikariCP + compileOnly("com.zaxxer:HikariCP:5.1.0") { isTransitive = false } // https://mvnrepository.com/artifact/io.lettuce/lettuce-core implementation("io.lettuce:lettuce-core:6.3.1.RELEASE") { exclude(group = "io.netty") diff --git a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/api/CoreAPI.java b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/api/CoreAPI.java index 191e319..f318522 100644 --- a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/api/CoreAPI.java +++ b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/api/CoreAPI.java @@ -1,7 +1,10 @@ package cn.hamster3.mc.plugin.core.common.api; +import cn.hamster3.mc.plugin.core.common.config.ConfigSection; import cn.hamster3.mc.plugin.core.common.thread.NamedThreadFactory; import com.google.gson.Gson; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import io.lettuce.core.RedisClient; import lombok.Getter; import net.kyori.adventure.platform.AudienceProvider; @@ -13,11 +16,24 @@ import java.sql.SQLException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.logging.Logger; @SuppressWarnings("unused") public abstract class CoreAPI { @Getter protected static CoreAPI instance; + /** + * lettuce redis 客户端 + */ + @Getter + @NotNull + private final RedisClient redisClient; + /** + * HamsterCore 公用数据库连接池 + */ + @Getter + @NotNull + private final HikariDataSource hikariDataSource; /** * 异步线程池 */ @@ -29,13 +45,37 @@ public abstract class CoreAPI { @Getter private final ScheduledExecutorService scheduledService; - public CoreAPI() { + public CoreAPI(@NotNull ConfigSection config) { executorService = Executors.newCachedThreadPool(new NamedThreadFactory("HamsterCore - Executor")); scheduledService = Executors.newScheduledThreadPool(1, new NamedThreadFactory("HamsterCore - Scheduler")); - } - @NotNull - public abstract AudienceProvider getAudienceProvider(); + getLogger().info("正在创建 redis 客户端"); + redisClient = RedisClient.create(config.getString("redis-url")); + getLogger().info("redis 客户端创建完成"); + + ConfigSection datasourceConfig = config.getSection("datasource"); + if (datasourceConfig == null) { + throw new IllegalArgumentException("配置文件中未找到 datasource 节点"); + } + getLogger().info("正在创建数据库连接池"); + 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); + } + 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("HamsterCore-Pool"); + hikariDataSource = new HikariDataSource(hikariConfig); + getLogger().info("数据库连接池创建完成"); + } /** * 获取 HamsterCore 公用数据库连接池 @@ -43,7 +83,9 @@ public abstract class CoreAPI { * @return 公用数据库连接池 */ @NotNull - public abstract DataSource getDataSource(); + public DataSource getDataSource() { + return hikariDataSource; + } /** * 获取 HamsterCore 公用数据库连接 @@ -56,11 +98,8 @@ public abstract class CoreAPI { return getDataSource().getConnection(); } - /** - * @return lettuce redis 客户端 - */ @NotNull - public abstract RedisClient getRedisClient(); + public abstract Logger getLogger(); /** * @return GSON 工具 @@ -73,4 +112,7 @@ public abstract class CoreAPI { */ @NotNull public abstract Gson getHumanGson(); + + @NotNull + public abstract AudienceProvider getAudienceProvider(); } diff --git a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/config/ConfigSection.java b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/config/ConfigSection.java new file mode 100644 index 0000000..4b6bb40 --- /dev/null +++ b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/config/ConfigSection.java @@ -0,0 +1,170 @@ +package cn.hamster3.mc.plugin.core.common.config; + +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@SuppressWarnings({"unused", "unchecked"}) +@Getter +public class ConfigSection { + @NotNull + protected final Map map; + + public ConfigSection() { + this(new HashMap<>()); + } + + public ConfigSection(@NotNull Map map) { + this.map = map; + } + + public boolean hasKey(@NotNull String key) { + return map.containsKey(key); + } + + @Nullable + public ConfigSection getSection(@NotNull String key) { + Object o = map.get(key); + if (o instanceof Map) { + return new ConfigSection((Map) o); + } + return null; + } + + @NotNull + public ConfigSection getSectionOrCreate(@NotNull String key) { + Object o = map.get(key); + if (o instanceof Map) { + return new ConfigSection((Map) o); + } + ConfigSection section = new ConfigSection(); + map.put(key, section.map); + return section; + } + + @Nullable + public String getString(@NotNull String key) { + Object o = map.get(key); + if (o == null) { + return null; + } + return o.toString(); + } + + @NotNull + public String getString(@NotNull String key, @NotNull String defaultValue) { + Object o = map.get(key); + if (o == null) { + return defaultValue; + } + return o.toString(); + } + + public List getStringList(@NotNull String key) { + Object o = map.get(key); + if (o instanceof List) { + return (List) o; + } + ArrayList list = new ArrayList<>(); + map.put(key, list); + return list; + } + + public boolean getBoolean(@NotNull String key) { + String string = getString(key); + if (string == null) { + return false; + } + return Boolean.parseBoolean(string); + } + + public boolean getBoolean(@NotNull String key, boolean defaultValue) { + String string = getString(key); + if (string == null) { + return defaultValue; + } + return Boolean.parseBoolean(string); + } + + public int getInt(@NotNull String key) { + String string = getString(key); + if (string == null) { + return 0; + } + return Integer.parseInt(string); + } + + public int getInt(@NotNull String key, int defaultValue) { + String string = getString(key); + if (string == null) { + return defaultValue; + } + return Integer.parseInt(string); + } + + public float getFloat(@NotNull String key) { + String string = getString(key); + if (string == null) { + return 0; + } + return Float.parseFloat(string); + } + + public float getFloat(@NotNull String key, float defaultValue) { + String string = getString(key); + if (string == null) { + return defaultValue; + } + return Float.parseFloat(string); + } + + public double getDouble(@NotNull String key) { + String string = getString(key); + if (string == null) { + return 0; + } + return Double.parseDouble(string); + } + + public double getDouble(@NotNull String key, double defaultValue) { + String string = getString(key); + if (string == null) { + return defaultValue; + } + return Double.parseDouble(string); + } + + public long getLong(@NotNull String key) { + String string = getString(key); + if (string == null) { + return 0L; + } + return Long.parseLong(string); + } + + public long getLong(@NotNull String key, long defaultValue) { + String string = getString(key); + if (string == null) { + return defaultValue; + } + return Long.parseLong(string); + } + + public void set(@NotNull String key, @Nullable Object value) { + if (value == null) { + map.remove(key); + return; + } + if (value instanceof ConfigSection) { + ConfigSection section = (ConfigSection) value; + map.put(key, section.map); + return; + } + map.put(key, value); + } +} diff --git a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/config/YamlConfig.java b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/config/YamlConfig.java new file mode 100644 index 0000000..28d8311 --- /dev/null +++ b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/config/YamlConfig.java @@ -0,0 +1,38 @@ +package cn.hamster3.mc.plugin.core.common.config; + +import org.jetbrains.annotations.NotNull; +import org.yaml.snakeyaml.Yaml; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +@SuppressWarnings("unused") +public class YamlConfig extends ConfigSection { + public static final Yaml YAML_LOADER = new Yaml(); + + public YamlConfig() { + super(); + } + + public YamlConfig(@NotNull Map map) { + super(map); + } + + public static YamlConfig load(@NotNull File file) throws IOException { + try (FileInputStream stream = new FileInputStream(file)) { + try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) { + Map load = YAML_LOADER.load(reader); + return new YamlConfig(load); + } + } + } + + public void save(@NotNull File file) throws IOException { + try (FileOutputStream stream = new FileOutputStream(file)) { + try (OutputStreamWriter writer = new OutputStreamWriter(stream, StandardCharsets.UTF_8)) { + YAML_LOADER.dump(map, writer); + } + } + } +} diff --git a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/thread/CountdownThread.java b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/thread/CountdownThread.java index 9f9cc6d..f8fc4f9 100644 --- a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/thread/CountdownThread.java +++ b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/thread/CountdownThread.java @@ -1,11 +1,13 @@ package cn.hamster3.mc.plugin.core.common.thread; import cn.hamster3.mc.plugin.core.common.api.CoreAPI; +import lombok.Data; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -@SuppressWarnings("unused") +@Data +@SuppressWarnings({"unused", "CallToPrintStackTrace"}) public abstract class CountdownThread implements Runnable { private final long interval; private final long totalTicks; @@ -59,27 +61,4 @@ public abstract class CountdownThread implements Runnable { future.cancel(false); } - public long getInterval() { - return interval; - } - - public long getTotalTicks() { - return totalTicks; - } - - public int getNowTicks() { - return nowTicks; - } - - public void setNowTicks(int nowTicks) { - this.nowTicks = nowTicks; - } - - public ScheduledFuture getFuture() { - return future; - } - - public void setFuture(ScheduledFuture future) { - this.future = future; - } } diff --git a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/util/Calculator.java b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/util/Calculator.java index babb6ea..cb386ed 100644 --- a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/util/Calculator.java +++ b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/util/Calculator.java @@ -1,5 +1,7 @@ package cn.hamster3.mc.plugin.core.common.util; +import org.jetbrains.annotations.NotNull; + import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Collections; @@ -14,17 +16,17 @@ import java.util.Stack; */ @SuppressWarnings("unused") public final class Calculator { + /** + * 这个单例线程不安全,如果要在异步线程使用,请自行新建一个实例 + */ public static final Calculator INSTANCE = new Calculator(); // 默认除法运算精度 private static final int DEF_DIV_SCALE = 16; private final Stack postfixStack = new Stack<>();// 后缀式栈 - private final Stack opStack = new Stack<>();// 运算符栈 + private final Stack operateStack = new Stack<>();// 运算符栈 private final int[] operaPriority = new int[]{0, 3, 2, 1, -1, 1, 0, 2};// 运用运算符ASCII码-40做索引的运算符优先级 - private Calculator() { - } - /** * 按照给定的表达式计算 * @@ -62,7 +64,7 @@ public final class Calculator { * @param expression 表达式 */ private void prepare(String expression) { - opStack.push(',');// 运算符放入栈底元素逗号,此符号优先级最低 + operateStack.push(',');// 运算符放入栈底元素逗号,此符号优先级最低 char[] arr = expression.toCharArray(); int currentIndex = 0;// 当前字符的位置 int count = 0;// 上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值 @@ -73,18 +75,18 @@ public final class Calculator { if (count > 0) { postfixStack.push(new String(arr, currentIndex, count));// 取两个运算符之间的数字 } - peekOp = opStack.peek(); + peekOp = operateStack.peek(); if (currentOp == ')') {// 遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号 - while (opStack.peek() != '(') { - postfixStack.push(String.valueOf(opStack.pop())); + while (operateStack.peek() != '(') { + postfixStack.push(String.valueOf(operateStack.pop())); } - opStack.pop(); + operateStack.pop(); } else { while (currentOp != '(' && peekOp != ',' && compare(currentOp, peekOp)) { - postfixStack.push(String.valueOf(opStack.pop())); - peekOp = opStack.peek(); + postfixStack.push(String.valueOf(operateStack.pop())); + peekOp = operateStack.peek(); } - opStack.push(currentOp); + operateStack.push(currentOp); } count = 0; currentIndex = i + 1; @@ -96,8 +98,8 @@ public final class Calculator { postfixStack.push(new String(arr, currentIndex, count)); } - while (opStack.peek() != ',') { - postfixStack.push(String.valueOf(opStack.pop()));// 将操作符栈中的剩余的元素添加到后缀式栈中 + while (operateStack.peek() != ',') { + postfixStack.push(String.valueOf(operateStack.pop()));// 将操作符栈中的剩余的元素添加到后缀式栈中 } } @@ -114,36 +116,36 @@ public final class Calculator { /** * 利用ASCII码-40做下标去算术符号优先级 * - * @param cur 字符1 - * @param peek 字符2 + * @param char1 字符1 + * @param char2 字符2 * @return 如果是peek优先级高于cur,返回true,默认都是peek优先级要低 */ - private boolean compare(char cur, char peek) { - return operaPriority[(peek) - 40] >= operaPriority[(cur) - 40]; + private boolean compare(char char1, char char2) { + return operaPriority[(char2) - 40] >= operaPriority[(char1) - 40]; } /** * 按照给定的算术运算符做计算 * - * @param firstValue 第一个值 - * @param secondValue 第二个值 - * @param currentOp 算数运算符 + * @param value1 第一个值 + * @param value2 第二个值 + * @param operate 算数运算符 * @return 运算结果 */ - private String calculate(String firstValue, String secondValue, char currentOp) { + private String calculate(@NotNull String value1, @NotNull String value2, char operate) { String result = ""; - switch (currentOp) { + switch (operate) { case '+': - result = String.valueOf(add(firstValue, secondValue)); + result = String.valueOf(add(value1, value2)); break; case '-': - result = String.valueOf(sub(firstValue, secondValue)); + result = String.valueOf(sub(value1, value2)); break; case '*': - result = String.valueOf(mul(firstValue, secondValue)); + result = String.valueOf(mul(value1, value2)); break; case '/': - result = String.valueOf(div(firstValue, secondValue)); + result = String.valueOf(div(value1, value2)); break; } return result; @@ -152,52 +154,52 @@ public final class Calculator { /** * 提供精确的加法运算。 * - * @param v1 被加数 - * @param v2 加数 + * @param value1 被加数 + * @param value2 加数 * @return 两个参数的和 */ - private double add(String v1, String v2) { - BigDecimal b1 = new BigDecimal(v1); - BigDecimal b2 = new BigDecimal(v2); + private double add(@NotNull String value1, @NotNull String value2) { + BigDecimal b1 = new BigDecimal(value1); + BigDecimal b2 = new BigDecimal(value2); return b1.add(b2).doubleValue(); } /** * 提供精确的减法运算。 * - * @param v1 被减数 - * @param v2 减数 + * @param value1 被减数 + * @param value2 减数 * @return 两个参数的差 */ - private double sub(String v1, String v2) { - BigDecimal b1 = new BigDecimal(v1); - BigDecimal b2 = new BigDecimal(v2); + private double sub(@NotNull String value1, @NotNull String value2) { + BigDecimal b1 = new BigDecimal(value1); + BigDecimal b2 = new BigDecimal(value2); return b1.subtract(b2).doubleValue(); } /** * 提供精确的乘法运算。 * - * @param v1 被乘数 - * @param v2 乘数 + * @param value1 被乘数 + * @param value2 乘数 * @return 两个参数的积 */ - private double mul(String v1, String v2) { - BigDecimal b1 = new BigDecimal(v1); - BigDecimal b2 = new BigDecimal(v2); + private double mul(@NotNull String value1, @NotNull String value2) { + BigDecimal b1 = new BigDecimal(value1); + BigDecimal b2 = new BigDecimal(value2); return b1.multiply(b2).doubleValue(); } /** * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。 * - * @param v1 被除数 - * @param v2 除数 + * @param value1 被除数 + * @param value2 除数 * @return 两个参数的商 */ - private double div(String v1, String v2) { - BigDecimal b1 = new BigDecimal(v1); - BigDecimal b2 = new BigDecimal(v2); + private double div(@NotNull String value1, @NotNull String value2) { + BigDecimal b1 = new BigDecimal(value1); + BigDecimal b2 = new BigDecimal(value2); return b1.divide(b2, DEF_DIV_SCALE, RoundingMode.HALF_UP).doubleValue(); } } diff --git a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/util/CoreUtils.java b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/util/CoreUtils.java index 084575e..17d2c72 100644 --- a/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/util/CoreUtils.java +++ b/core-common/src/main/java/cn/hamster3/mc/plugin/core/common/util/CoreUtils.java @@ -148,6 +148,8 @@ public final class CoreUtils { /** * 按照给定的表达式计算 + *

+ * 如果要在异步线程使用,请自行新建一个 Calculator 实例 * * @param expression 要计算的表达式例如:5+12*(3+5)/7 * @return 计算结果