diff --git a/.idea/dictionaries/csh20.xml b/.idea/dictionaries/csh20.xml
new file mode 100644
index 0000000..7fec0b9
--- /dev/null
+++ b/.idea/dictionaries/csh20.xml
@@ -0,0 +1,8 @@
+
+
+
+ unserialize
+ unserializer
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/ilummc/tlib/ExampleMain.java b/src/main/java/com/ilummc/tlib/ExampleMain.java
index 46af092..ed4022f 100644
--- a/src/main/java/com/ilummc/tlib/ExampleMain.java
+++ b/src/main/java/com/ilummc/tlib/ExampleMain.java
@@ -1,7 +1,6 @@
package com.ilummc.tlib;
import com.ilummc.tlib.annotations.Config;
-import com.ilummc.tlib.annotations.ConfigNode;
import com.ilummc.tlib.bean.Property;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
@@ -9,7 +8,6 @@ import org.bukkit.plugin.java.JavaPlugin;
@Config(name = "cfg.yml", charset = "GBK")
public class ExampleMain extends JavaPlugin {
- @ConfigNode("enableUpdate")
private Property update = Property.of(false);
@Override
diff --git a/src/main/java/com/ilummc/tlib/TLib.java b/src/main/java/com/ilummc/tlib/TLib.java
index e193b09..f9919a2 100644
--- a/src/main/java/com/ilummc/tlib/TLib.java
+++ b/src/main/java/com/ilummc/tlib/TLib.java
@@ -1,5 +1,6 @@
package com.ilummc.tlib;
+import com.ilummc.tlib.annotations.Config;
import com.ilummc.tlib.annotations.Dependency;
import com.ilummc.tlib.annotations.Logger;
import com.ilummc.tlib.inject.DependencyInjector;
@@ -20,9 +21,15 @@ public class TLib {
@Logger("§3[§6TLib§3|{1}§3] §f{2}")
private TLogger tLogger;
+ private TLibConfig config;
+
private TLib() {
}
+ public TLibConfig getConfig() {
+ return config;
+ }
+
public TLogger getLogger() {
return tLogger;
}
@@ -48,4 +55,14 @@ public class TLib {
}
}
+ @Config(name = "tlib.yml")
+ public class TLibConfig {
+
+ private int downloadPoolSize = 4;
+
+ public int getDownloadPoolSize() {
+ return downloadPoolSize;
+ }
+ }
+
}
diff --git a/src/main/java/com/ilummc/tlib/annotations/Config.java b/src/main/java/com/ilummc/tlib/annotations/Config.java
index ca16a4f..03b792a 100644
--- a/src/main/java/com/ilummc/tlib/annotations/Config.java
+++ b/src/main/java/com/ilummc/tlib/annotations/Config.java
@@ -4,6 +4,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.reflect.Modifier;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@@ -15,12 +16,10 @@ public @interface Config {
boolean saveOnExit() default false;
- boolean readOnly() default true;
-
- boolean fixUnicode() default true;
-
String charset() default "UTF-8";
boolean listenChanges() default false;
+ int excludeModifiers() default Modifier.STATIC | Modifier.TRANSIENT;
+
}
diff --git a/src/main/java/com/ilummc/tlib/annotations/ConfigNode.java b/src/main/java/com/ilummc/tlib/annotations/ConfigNode.java
deleted file mode 100644
index 7e2478d..0000000
--- a/src/main/java/com/ilummc/tlib/annotations/ConfigNode.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.ilummc.tlib.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Target(ElementType.FIELD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ConfigNode {
-
- String value();
-}
diff --git a/src/main/java/com/ilummc/tlib/bean/PropertyTypeAdaptor.java b/src/main/java/com/ilummc/tlib/bean/PropertyTypeAdaptor.java
new file mode 100644
index 0000000..f802433
--- /dev/null
+++ b/src/main/java/com/ilummc/tlib/bean/PropertyTypeAdaptor.java
@@ -0,0 +1,16 @@
+package com.ilummc.tlib.bean;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+
+import java.lang.reflect.Type;
+
+public class PropertyTypeAdaptor implements JsonDeserializer {
+
+ @Override
+ public Property deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
+ return null;
+ }
+}
diff --git a/src/main/java/com/ilummc/tlib/dependency/TDependency.java b/src/main/java/com/ilummc/tlib/dependency/TDependency.java
index 5488a45..b4bbcf2 100644
--- a/src/main/java/com/ilummc/tlib/dependency/TDependency.java
+++ b/src/main/java/com/ilummc/tlib/dependency/TDependency.java
@@ -55,7 +55,7 @@ public class TDependency {
.url(dl == null ? url + "/" + groupId.replace('.', '/') + "/" +
artifactId + "/" + version + "/" + artifactId + "-" + version + ".jar" : dl)
.file(target)
- .setThreads(8)
+ .setThreads(TLib.getTLib().getConfig().getDownloadPoolSize())
.setOnStart(event -> lock.lock())
.setOnConnected(event -> TLib.getTLib().getLogger().info(" 正在下载 " + String.join(":",
new String[]{groupId, artifactId, version}) +
diff --git a/src/main/java/com/ilummc/tlib/inject/DependencyInjector.java b/src/main/java/com/ilummc/tlib/inject/DependencyInjector.java
index faca285..e09a874 100644
--- a/src/main/java/com/ilummc/tlib/inject/DependencyInjector.java
+++ b/src/main/java/com/ilummc/tlib/inject/DependencyInjector.java
@@ -1,10 +1,7 @@
package com.ilummc.tlib.inject;
import com.ilummc.tlib.TLib;
-import com.ilummc.tlib.annotations.Dependencies;
-import com.ilummc.tlib.annotations.Dependency;
-import com.ilummc.tlib.annotations.Logger;
-import com.ilummc.tlib.annotations.PluginInstance;
+import com.ilummc.tlib.annotations.*;
import com.ilummc.tlib.dependency.TDependency;
import com.ilummc.tlib.util.TLogger;
import org.bukkit.Bukkit;
@@ -31,12 +28,25 @@ public class DependencyInjector {
}
private static void injectConfig(Plugin plugin, Object o) {
-
+ for (Field field : o.getClass().getDeclaredFields()) {
+ try {
+ Config config;
+ if ((config = field.getType().getAnnotation(Config.class)) != null) {
+ field.setAccessible(true);
+ Object obj = TConfigInjector.loadConfig(plugin, field.getType());
+ if (obj != null) {
+ TLib.getTLib().getLogger().info("插件 " + plugin.getName() + " 的 " + config.name() + " 配置文件成功加载");
+ field.set(o, obj);
+ }
+ }
+ } catch (IllegalAccessException ignored) {
+ }
+ }
}
private static void injectLogger(Plugin plugin, Object o) {
- try {
- for (Field field : o.getClass().getDeclaredFields()) {
+ for (Field field : o.getClass().getDeclaredFields()) {
+ try {
Logger logger;
if ((logger = field.getAnnotation(Logger.class)) != null) {
field.getType().asSubclass(TLogger.class);
@@ -45,8 +55,8 @@ public class DependencyInjector {
field.setAccessible(true);
field.set(o, tLogger);
}
+ } catch (Exception ignored) {
}
- } catch (Exception ignored) {
}
}
diff --git a/src/main/java/com/ilummc/tlib/inject/TConfigInjector.java b/src/main/java/com/ilummc/tlib/inject/TConfigInjector.java
index 76921a9..447484a 100644
--- a/src/main/java/com/ilummc/tlib/inject/TConfigInjector.java
+++ b/src/main/java/com/ilummc/tlib/inject/TConfigInjector.java
@@ -1,6 +1,161 @@
package com.ilummc.tlib.inject;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.SerializedName;
+import com.ilummc.tlib.TLib;
+import com.ilummc.tlib.annotations.Config;
+import com.ilummc.tlib.bean.Property;
+import org.apache.commons.lang3.Validate;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.plugin.Plugin;
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.Charset;
+import java.util.*;
+import java.util.stream.Collectors;
+
public class TConfigInjector {
+ public static Object loadConfig(Plugin plugin, Class> clazz) {
+ try {
+ Config config = clazz.getAnnotation(Config.class);
+ Validate.notNull(config);
+ File file = new File(plugin.getDataFolder(), config.name());
+ if (!file.exists()) if (config.fromJar()) plugin.saveResource(config.name(), true);
+ else saveConfig(plugin, clazz);
+ return unserialize(plugin, clazz);
+ } catch (NullPointerException e) {
+ TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败:没有 @Config 注解");
+ } catch (Exception e) {
+ TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败");
+ }
+ return null;
+ }
+
+ public static Object unserialize(Plugin plugin, Class> clazz) {
+ try {
+ Config config = clazz.getAnnotation(Config.class);
+ Validate.notNull(config);
+ return new GsonBuilder().disableHtmlEscaping().excludeFieldsWithModifiers(config.excludeModifiers())
+ .create().fromJson(new Gson().toJson(new Yaml()
+ .dump(Files.toString(new File(plugin.getDataFolder(), config.name()), Charset.forName(config.charset())))), clazz);
+ } catch (NullPointerException e) {
+ TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败:没有 @Config 注解");
+ return null;
+ } catch (Exception e) {
+ try {
+ return clazz.newInstance();
+ } catch (InstantiationException | IllegalAccessException e1) {
+ TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败");
+ return null;
+ }
+ }
+ }
+
+ public static Map serialize(Plugin plugin, Class> clazz) {
+ try {
+ Constructor constructor = clazz.getConstructor();
+ constructor.setAccessible(true);
+ Config config = clazz.getAnnotation(Config.class);
+ Validate.notNull(config);
+ return new Serializer(new LinkedHashMap<>(), constructor.newInstance(), config.excludeModifiers()).get();
+ } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+ TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 序列化失败:没有无参构造方法");
+ } catch (NullPointerException e) {
+ TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 序列化失败:没有 @Config 注解");
+ } catch (Exception e) {
+ TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 序列化失败");
+ }
+ return null;
+ }
+
+ public static void saveConfig(Plugin plugin, Class> clazz) throws IOException, NullPointerException {
+ Object obj = serialize(plugin, clazz);
+ Validate.notNull(obj);
+ Config config = clazz.getAnnotation(Config.class);
+ Validate.notNull(config);
+ File target = new File(plugin.getDataFolder(), config.name());
+ if (!target.exists()) target.createNewFile();
+ DumperOptions options = new DumperOptions();
+ options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+ Yaml yaml = new Yaml(options);
+ String str = yaml.dump(obj);
+ byte[] arr = str.getBytes(config.charset());
+ Files.write(arr, target);
+ }
+
+ private static final List primitiveType = Lists.newArrayList(Integer.class,
+ Double.class, Float.class, Boolean.class, Short.class, Byte.class, Character.class, Long.class, String.class);
+
+ private static class Serializer {
+
+ private HashMap map;
+ private Object o;
+ private int modifiers;
+
+ private Serializer(HashMap map, Object o, int modifiers) {
+ this.map = map;
+ this.o = o;
+ this.modifiers = modifiers;
+ }
+
+ private HashMap get() {
+ for (Field field : o.getClass().getDeclaredFields()) {
+ if ((field.getModifiers() & modifiers) == 0 && !field.isSynthetic())
+ try {
+ SerializedName node = field.getAnnotation(SerializedName.class);
+ if (!field.isAccessible()) field.setAccessible(true);
+ Object obj = field.get(o);
+ map.put(node == null ? field.getName() : node.value(), serialize(obj));
+ } catch (Exception ignored) {
+ }
+ }
+ return map;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private Object serialize(Object o) {
+ try {
+ if (o.getClass().isPrimitive() || primitiveType.contains(o.getClass())) {
+ return o;
+ } else if (o.getClass().isArray()) {
+ List list = new ArrayList();
+ int len = (int) o.getClass().getField("length").get(o);
+ for (int i = 0; i < len; i++) {
+ list.add(serialize(Array.get(o, i)));
+ }
+ return list;
+ } else if (o instanceof Collection) {
+ return ((Collection) o).stream().map(this::serialize).collect(Collectors.toList());
+ } else if (o instanceof Map) {
+ Map map = new LinkedHashMap<>();
+ ((Map) o).forEach((o1, o2) -> map.put((String) o1, serialize(o2)));
+ return map;
+ } else if (o instanceof ConfigurationSerializable) {
+ Map map = new LinkedHashMap();
+ map.put("==", o.getClass().getName());
+ map.putAll(((ConfigurationSerializable) o).serialize());
+ return map;
+ } else if (o instanceof Property) {
+ return serialize(((Property) o).get());
+ } else {
+ return new Serializer(new HashMap<>(), o, modifiers).get();
+ }
+ } catch (Exception ignored) {
+ return null;
+ }
+ }
+
+ }
}