perf: 精简代码
This commit is contained in:
@@ -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")
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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<String, Object> map;
|
||||
|
||||
public ConfigSection() {
|
||||
this(new HashMap<>());
|
||||
}
|
||||
|
||||
public ConfigSection(@NotNull Map<String, Object> 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<String, Object>) o);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ConfigSection getSectionOrCreate(@NotNull String key) {
|
||||
Object o = map.get(key);
|
||||
if (o instanceof Map) {
|
||||
return new ConfigSection((Map<String, Object>) 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<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) {
|
||||
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);
|
||||
}
|
||||
}
|
@@ -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<String, Object> 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<String, Object> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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<String> postfixStack = new Stack<>();// 后缀式栈
|
||||
private final Stack<Character> opStack = new Stack<>();// 运算符栈
|
||||
private final Stack<Character> 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();
|
||||
}
|
||||
}
|
||||
|
@@ -148,6 +148,8 @@ public final class CoreUtils {
|
||||
|
||||
/**
|
||||
* 按照给定的表达式计算
|
||||
* <p>
|
||||
* 如果要在异步线程使用,请自行新建一个 Calculator 实例
|
||||
*
|
||||
* @param expression 要计算的表达式例如:5+12*(3+5)/7
|
||||
* @return 计算结果
|
||||
|
Reference in New Issue
Block a user