船新 I18n 系统
修了一个配置文件小bug
This commit is contained in:
parent
385b2aa974
commit
c573617a01
@ -1,6 +1,9 @@
|
|||||||
<component name="ProjectDictionaryState">
|
<component name="ProjectDictionaryState">
|
||||||
<dictionary name="csh20">
|
<dictionary name="csh20">
|
||||||
<words>
|
<words>
|
||||||
|
<w>mvdw</w>
|
||||||
|
<w>papi</w>
|
||||||
|
<w>sendable</w>
|
||||||
<w>unserialize</w>
|
<w>unserialize</w>
|
||||||
<w>unserializer</w>
|
<w>unserializer</w>
|
||||||
</words>
|
</words>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<component name="libraryTable">
|
<component name="libraryTable">
|
||||||
<library name="Maven: com.ilummc.eagletdl:EagletCore:1.1">
|
<library name="Maven: com.ilummc.eagletdl:EagletCore:1.1.2">
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/com/ilummc/eagletdl/EagletCore/1.1/EagletCore-1.1.jar!/" />
|
<root url="jar://$MAVEN_REPOSITORY$/com/ilummc/eagletdl/EagletCore/1.1.2/EagletCore-1.1.2.jar!/" />
|
||||||
</CLASSES>
|
</CLASSES>
|
||||||
<JAVADOC>
|
<JAVADOC>
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/com/ilummc/eagletdl/EagletCore/1.1/EagletCore-1.1-javadoc.jar!/" />
|
<root url="jar://$MAVEN_REPOSITORY$/com/ilummc/eagletdl/EagletCore/1.1.2/EagletCore-1.1.2-javadoc.jar!/" />
|
||||||
</JAVADOC>
|
</JAVADOC>
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/com/ilummc/eagletdl/EagletCore/1.1/EagletCore-1.1-sources.jar!/" />
|
<root url="jar://$MAVEN_REPOSITORY$/com/ilummc/eagletdl/EagletCore/1.1.2/EagletCore-1.1.2-sources.jar!/" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
</library>
|
</library>
|
||||||
</component>
|
</component>
|
@ -1,13 +1,13 @@
|
|||||||
<component name="libraryTable">
|
<component name="libraryTable">
|
||||||
<library name="Maven: com.zaxxer:HikariCP:3.0.0">
|
<library name="Maven: com.zaxxer:HikariCP:3.1.0">
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/com/zaxxer/HikariCP/3.0.0/HikariCP-3.0.0.jar!/" />
|
<root url="jar://$MAVEN_REPOSITORY$/com/zaxxer/HikariCP/3.1.0/HikariCP-3.1.0.jar!/" />
|
||||||
</CLASSES>
|
</CLASSES>
|
||||||
<JAVADOC>
|
<JAVADOC>
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/com/zaxxer/HikariCP/3.0.0/HikariCP-3.0.0-javadoc.jar!/" />
|
<root url="jar://$MAVEN_REPOSITORY$/com/zaxxer/HikariCP/3.1.0/HikariCP-3.1.0-javadoc.jar!/" />
|
||||||
</JAVADOC>
|
</JAVADOC>
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/com/zaxxer/HikariCP/3.0.0/HikariCP-3.0.0-sources.jar!/" />
|
<root url="jar://$MAVEN_REPOSITORY$/com/zaxxer/HikariCP/3.1.0/HikariCP-3.1.0-sources.jar!/" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
</library>
|
</library>
|
||||||
</component>
|
</component>
|
12
pom.xml
12
pom.xml
@ -58,15 +58,15 @@
|
|||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>com.ilummc.eagletdl</groupId>
|
|
||||||
<artifactId>EagletCore</artifactId>
|
|
||||||
<version>1.1</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.zaxxer</groupId>
|
<groupId>com.zaxxer</groupId>
|
||||||
<artifactId>HikariCP</artifactId>
|
<artifactId>HikariCP</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>3.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ilummc.eagletdl</groupId>
|
||||||
|
<artifactId>EagletCore</artifactId>
|
||||||
|
<version>1.1.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.ow2.asm</groupId>
|
<groupId>org.ow2.asm</groupId>
|
||||||
|
@ -3,9 +3,12 @@ package com.ilummc.tlib;
|
|||||||
import com.ilummc.tlib.annotations.Config;
|
import com.ilummc.tlib.annotations.Config;
|
||||||
import com.ilummc.tlib.annotations.Dependency;
|
import com.ilummc.tlib.annotations.Dependency;
|
||||||
import com.ilummc.tlib.annotations.Logger;
|
import com.ilummc.tlib.annotations.Logger;
|
||||||
|
import com.ilummc.tlib.compat.PlaceholderApiHook;
|
||||||
import com.ilummc.tlib.inject.DependencyInjector;
|
import com.ilummc.tlib.inject.DependencyInjector;
|
||||||
import com.ilummc.tlib.inject.TConfigWatcher;
|
import com.ilummc.tlib.inject.TConfigWatcher;
|
||||||
import com.ilummc.tlib.inject.TLibPluginManager;
|
import com.ilummc.tlib.inject.TLibPluginManager;
|
||||||
|
import com.ilummc.tlib.resources.LocaleLoader;
|
||||||
|
import com.ilummc.tlib.resources.TLocale;
|
||||||
import com.ilummc.tlib.util.TLogger;
|
import com.ilummc.tlib.util.TLogger;
|
||||||
import me.skymc.taboolib.Main;
|
import me.skymc.taboolib.Main;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -21,7 +24,7 @@ public class TLib {
|
|||||||
private static TLib tLib;
|
private static TLib tLib;
|
||||||
|
|
||||||
@Logger("§8[§3§lTabooLib§8][§r{1}§8] §f{2}")
|
@Logger("§8[§3§lTabooLib§8][§r{1}§8] §f{2}")
|
||||||
private TLogger tLogger;
|
private TLogger tLogger = new TLogger("§8[§3§lTabooLib§8][§r{1}§8] §f{2}", Main.getInst(), TLogger.FINE);
|
||||||
|
|
||||||
private TLibConfig config;
|
private TLibConfig config;
|
||||||
|
|
||||||
@ -60,11 +63,17 @@ public class TLib {
|
|||||||
public static void init() {
|
public static void init() {
|
||||||
new File(Main.getInst().getDataFolder(), "/libs").mkdirs();
|
new File(Main.getInst().getDataFolder(), "/libs").mkdirs();
|
||||||
tLib = new TLib();
|
tLib = new TLib();
|
||||||
|
LocaleLoader.init();
|
||||||
|
PlaceholderApiHook.init();
|
||||||
DependencyInjector.inject(Main.getInst(), tLib);
|
DependencyInjector.inject(Main.getInst(), tLib);
|
||||||
if (Bukkit.getPluginManager() instanceof TLibPluginManager)
|
if (Bukkit.getPluginManager() instanceof TLibPluginManager)
|
||||||
tLib.getLogger().info("注入成功");
|
tLib.getLogger().info("注入成功");
|
||||||
else
|
else
|
||||||
tLib.getLogger().fatal("注入失败");
|
tLib.getLogger().fatal("注入失败");
|
||||||
|
TLocale.sendToConsole("test1");
|
||||||
|
TLocale.sendToConsole("test2");
|
||||||
|
TLocale.sendToConsole("test3");
|
||||||
|
TLocale.sendToConsole("test4.node1", "Hello", "world");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unload() {
|
public static void unload() {
|
||||||
@ -72,7 +81,7 @@ public class TLib {
|
|||||||
DependencyInjector.eject(Main.getInst(), tLib);
|
DependencyInjector.eject(Main.getInst(), tLib);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Config(name = "tlib.yml", listenChanges = true)
|
@Config(name = "tlib.yml", listenChanges = true, readOnly = false)
|
||||||
public static class TLibConfig {
|
public static class TLibConfig {
|
||||||
|
|
||||||
private int downloadPoolSize = 4;
|
private int downloadPoolSize = 4;
|
||||||
@ -80,5 +89,17 @@ public class TLib {
|
|||||||
public int getDownloadPoolSize() {
|
public int getDownloadPoolSize() {
|
||||||
return downloadPoolSize;
|
return downloadPoolSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String[] locale = {"zh_CN", "en_US"};
|
||||||
|
|
||||||
|
public String[] getLocale() {
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean enablePapiByDefault = false;
|
||||||
|
|
||||||
|
public boolean isEnablePapiByDefault() {
|
||||||
|
return enablePapiByDefault;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@ public @interface Config {
|
|||||||
|
|
||||||
boolean saveOnExit() default false;
|
boolean saveOnExit() default false;
|
||||||
|
|
||||||
|
boolean readOnly() default true;
|
||||||
|
|
||||||
String charset() default "UTF-8";
|
String charset() default "UTF-8";
|
||||||
|
|
||||||
boolean listenChanges() default false;
|
boolean listenChanges() default false;
|
||||||
|
40
src/main/java/com/ilummc/tlib/compat/PlaceholderApiHook.java
Normal file
40
src/main/java/com/ilummc/tlib/compat/PlaceholderApiHook.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package com.ilummc.tlib.compat;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public abstract class PlaceholderApiHook {
|
||||||
|
|
||||||
|
private static PlaceholderApiHook impl;
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null)
|
||||||
|
impl = new PlaceholderImpl();
|
||||||
|
else impl = new AbstractImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String replace(CommandSender sender, String text) {
|
||||||
|
return sender instanceof Player ? impl.replace(((Player) sender), text) : text;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract String replace(Player player, String text);
|
||||||
|
|
||||||
|
private static class PlaceholderImpl extends PlaceholderApiHook {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String replace(Player player, String text) {
|
||||||
|
return PlaceholderAPI.setPlaceholders(player, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AbstractImpl extends PlaceholderApiHook {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String replace(Player player, String text) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -7,7 +7,6 @@ import me.skymc.taboolib.Main;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
|
|
||||||
public class TDependency {
|
public class TDependency {
|
||||||
|
|
||||||
@ -56,14 +55,12 @@ public class TDependency {
|
|||||||
TLib.getTLib().getLogger().warn("已启用离线模式, 将不会下载第三方依赖库");
|
TLib.getTLib().getLogger().warn("已启用离线模式, 将不会下载第三方依赖库");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ReentrantLock lock = new ReentrantLock();
|
|
||||||
AtomicBoolean failed = new AtomicBoolean(false);
|
AtomicBoolean failed = new AtomicBoolean(false);
|
||||||
String link = dl.length() == 0 ? url + "/" + groupId.replace('.', '/') + "/" + artifactId + "/" + version + "/" + artifactId + "-" + version + ".jar" : dl;
|
String link = dl.length() == 0 ? url + "/" + groupId.replace('.', '/') + "/" + artifactId + "/" + version + "/" + artifactId + "-" + version + ".jar" : dl;
|
||||||
EagletTask task = new EagletTask()
|
new EagletTask()
|
||||||
.url(link)
|
.url(link)
|
||||||
.file(target)
|
.file(target)
|
||||||
.setThreads(TLib.getTLib().getConfig().getDownloadPoolSize())
|
.setThreads(TLib.getTLib().getConfig().getDownloadPoolSize())
|
||||||
.setOnStart(event -> lock.lock())
|
|
||||||
.setOnError(event -> {
|
.setOnError(event -> {
|
||||||
})
|
})
|
||||||
.setOnConnected(event -> TLib.getTLib().getLogger().info(" 正在下载 " + String.join(":",
|
.setOnConnected(event -> TLib.getTLib().getLogger().info(" 正在下载 " + String.join(":",
|
||||||
@ -79,12 +76,7 @@ public class TDependency {
|
|||||||
TLib.getTLib().getLogger().error(" 下载 " + String.join(":", new String[]{groupId, artifactId, version}) + " 失败");
|
TLib.getTLib().getLogger().error(" 下载 " + String.join(":", new String[]{groupId, artifactId, version}) + " 失败");
|
||||||
TLib.getTLib().getLogger().error(" 请手动下载 " + link + " 并重命名为 " + target.getName() + " 后放在 /TabooLib/libs 文件夹内");
|
TLib.getTLib().getLogger().error(" 请手动下载 " + link + " 并重命名为 " + target.getName() + " 后放在 /TabooLib/libs 文件夹内");
|
||||||
}
|
}
|
||||||
lock.unlock();
|
}).start().waitUntil();
|
||||||
});
|
|
||||||
task.start();
|
|
||||||
while (lock.tryLock()) lock.unlock();
|
|
||||||
lock.lock();
|
|
||||||
lock.unlock();
|
|
||||||
return !failed.get();
|
return !failed.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package com.ilummc.tlib.inject;
|
|||||||
import com.ilummc.tlib.TLib;
|
import com.ilummc.tlib.TLib;
|
||||||
import com.ilummc.tlib.annotations.*;
|
import com.ilummc.tlib.annotations.*;
|
||||||
import com.ilummc.tlib.dependency.TDependency;
|
import com.ilummc.tlib.dependency.TDependency;
|
||||||
|
import com.ilummc.tlib.resources.LocaleLoader;
|
||||||
import com.ilummc.tlib.util.Ref;
|
import com.ilummc.tlib.util.Ref;
|
||||||
import com.ilummc.tlib.util.TLogger;
|
import com.ilummc.tlib.util.TLogger;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -15,10 +16,11 @@ import java.lang.reflect.Field;
|
|||||||
public class DependencyInjector {
|
public class DependencyInjector {
|
||||||
|
|
||||||
public static void inject(Plugin plugin, Object o) {
|
public static void inject(Plugin plugin, Object o) {
|
||||||
|
injectDependencies(plugin, o);
|
||||||
injectLogger(plugin, o);
|
injectLogger(plugin, o);
|
||||||
injectConfig(plugin, o);
|
injectConfig(plugin, o);
|
||||||
injectPluginInstance(plugin, o);
|
injectPluginInstance(plugin, o);
|
||||||
injectDependencies(plugin, o);
|
LocaleLoader.load(plugin, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void injectOnEnable(Plugin plugin) {
|
static void injectOnEnable(Plugin plugin) {
|
||||||
@ -39,7 +41,7 @@ public class DependencyInjector {
|
|||||||
private static void ejectConfig(Plugin plugin, Object o) {
|
private static void ejectConfig(Plugin plugin, Object o) {
|
||||||
for (Field field : Ref.getDeclaredFields(o.getClass())) {
|
for (Field field : Ref.getDeclaredFields(o.getClass())) {
|
||||||
Config config;
|
Config config;
|
||||||
if ((config = field.getType().getAnnotation(Config.class)) != null) {
|
if ((config = field.getType().getAnnotation(Config.class)) != null && config.saveOnExit()) {
|
||||||
try {
|
try {
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
TConfigInjector.saveConfig(plugin, field.get(o));
|
TConfigInjector.saveConfig(plugin, field.get(o));
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.ilummc.tlib.inject;
|
package com.ilummc.tlib.inject;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
@ -9,6 +10,7 @@ import com.ilummc.tlib.TLib;
|
|||||||
import com.ilummc.tlib.annotations.Config;
|
import com.ilummc.tlib.annotations.Config;
|
||||||
import com.ilummc.tlib.bean.Property;
|
import com.ilummc.tlib.bean.Property;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
@ -17,7 +19,6 @@ import org.yaml.snakeyaml.Yaml;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -25,6 +26,36 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
public class TConfigInjector {
|
public class TConfigInjector {
|
||||||
|
|
||||||
|
public static void fixUnicode(YamlConfiguration configuration) {
|
||||||
|
try {
|
||||||
|
Field field = YamlConfiguration.class.getDeclaredField("yamlOptions");
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(configuration, NoUnicodeDumperOption.INSTANCE);
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class NoUnicodeDumperOption extends DumperOptions {
|
||||||
|
|
||||||
|
private static final NoUnicodeDumperOption INSTANCE = new NoUnicodeDumperOption();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAllowUnicode(boolean allowUnicode) {
|
||||||
|
super.setAllowUnicode(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAllowUnicode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLineBreak(LineBreak lineBreak) {
|
||||||
|
super.setLineBreak(LineBreak.getPlatformLineBreak());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Object loadConfig(Plugin plugin, Class<?> clazz) {
|
public static Object loadConfig(Plugin plugin, Class<?> clazz) {
|
||||||
try {
|
try {
|
||||||
Config config = clazz.getAnnotation(Config.class);
|
Config config = clazz.getAnnotation(Config.class);
|
||||||
@ -32,7 +63,9 @@ public class TConfigInjector {
|
|||||||
File file = new File(plugin.getDataFolder(), config.name());
|
File file = new File(plugin.getDataFolder(), config.name());
|
||||||
if (!file.exists()) if (config.fromJar()) plugin.saveResource(config.name(), true);
|
if (!file.exists()) if (config.fromJar()) plugin.saveResource(config.name(), true);
|
||||||
else saveConfig(plugin, clazz.newInstance());
|
else saveConfig(plugin, clazz.newInstance());
|
||||||
return unserialize(plugin, clazz);
|
Object obj = unserialize(plugin, clazz);
|
||||||
|
if (!config.readOnly()) saveConfig(plugin, obj);
|
||||||
|
return obj;
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败:没有 @Config 注解");
|
TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置类 " + clazz.getSimpleName() + " 加载失败:没有 @Config 注解");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -83,6 +116,7 @@ public class TConfigInjector {
|
|||||||
if (!target.exists()) target.createNewFile();
|
if (!target.exists()) target.createNewFile();
|
||||||
DumperOptions options = new DumperOptions();
|
DumperOptions options = new DumperOptions();
|
||||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||||
|
options.setAllowUnicode(false);
|
||||||
Yaml yaml = new Yaml(options);
|
Yaml yaml = new Yaml(options);
|
||||||
String str = yaml.dump(obj);
|
String str = yaml.dump(obj);
|
||||||
byte[] arr = str.getBytes(config.charset());
|
byte[] arr = str.getBytes(config.charset());
|
||||||
@ -124,12 +158,7 @@ public class TConfigInjector {
|
|||||||
if (o.getClass().isPrimitive() || primitiveType.contains(o.getClass())) {
|
if (o.getClass().isPrimitive() || primitiveType.contains(o.getClass())) {
|
||||||
return o;
|
return o;
|
||||||
} else if (o.getClass().isArray()) {
|
} else if (o.getClass().isArray()) {
|
||||||
List list = new ArrayList<>();
|
return ImmutableList.copyOf(((Object[]) o));
|
||||||
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) {
|
} else if (o instanceof Collection) {
|
||||||
return ((Collection) o).stream().map(this::serialize).collect(Collectors.toList());
|
return ((Collection) o).stream().map(this::serialize).collect(Collectors.toList());
|
||||||
} else if (o instanceof Map) {
|
} else if (o instanceof Map) {
|
||||||
|
65
src/main/java/com/ilummc/tlib/resources/LocaleInstance.java
Normal file
65
src/main/java/com/ilummc/tlib/resources/LocaleInstance.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package com.ilummc.tlib.resources;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ThreadSafe
|
||||||
|
class LocaleInstance {
|
||||||
|
|
||||||
|
private static final Function<Object, Sendable> TO_SENDABLE = o -> {
|
||||||
|
if (o instanceof Sendable) return ((Sendable) o);
|
||||||
|
else if (o instanceof String) return SimpleChatMessage.of(((String) o));
|
||||||
|
else return SimpleChatMessage.of(String.valueOf(o));
|
||||||
|
};
|
||||||
|
|
||||||
|
LocaleInstance() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<String, List<Sendable>> map = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
void sendTo(String path, CommandSender sender) {
|
||||||
|
map.getOrDefault(path, ImmutableList.of(Sendable.EMPTY)).forEach(sendable -> sendable.sendTo(sender));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendTo(String path, CommandSender sender, String... args) {
|
||||||
|
map.getOrDefault(path, ImmutableList.of(Sendable.EMPTY)).forEach(sendable -> sendable.sendTo(sender, args));
|
||||||
|
System.out.println(map.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(YamlConfiguration configuration) {
|
||||||
|
configuration.getKeys(false).forEach(s -> {
|
||||||
|
Object object = configuration.get(s);
|
||||||
|
if (object instanceof ConfigurationSection)
|
||||||
|
loadRecursively(s, (ConfigurationSection) object);
|
||||||
|
else if (object instanceof Sendable)
|
||||||
|
map.put(s, Collections.singletonList((Sendable) object));
|
||||||
|
else if (object instanceof List && !((List) object).isEmpty())
|
||||||
|
map.put(s, ((List<?>) object).stream().map(TO_SENDABLE).collect(Collectors.toList()));
|
||||||
|
else map.put(s, Collections.singletonList(SimpleChatMessage.of(String.valueOf(object))));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadRecursively(String path, ConfigurationSection section) {
|
||||||
|
section.getKeys(false).forEach(s -> {
|
||||||
|
Object object = section.get(path + "." + s);
|
||||||
|
if (object instanceof ConfigurationSection)
|
||||||
|
loadRecursively(path + "." + s, (ConfigurationSection) object);
|
||||||
|
else if (object instanceof Sendable)
|
||||||
|
map.put(path + "." + s, Collections.singletonList((Sendable) object));
|
||||||
|
else if (object instanceof List && !((List) object).isEmpty())
|
||||||
|
map.put(path + "." + s, ((List<?>) object).stream().map(TO_SENDABLE).collect(Collectors.toList()));
|
||||||
|
else map.put(path + "." + s, Collections.singletonList(SimpleChatMessage.of(String.valueOf(object))));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
76
src/main/java/com/ilummc/tlib/resources/LocaleLoader.java
Normal file
76
src/main/java/com/ilummc/tlib/resources/LocaleLoader.java
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package com.ilummc.tlib.resources;
|
||||||
|
|
||||||
|
import com.ilummc.tlib.TLib;
|
||||||
|
import com.ilummc.tlib.inject.TConfigInjector;
|
||||||
|
import me.skymc.taboolib.Main;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class LocaleLoader {
|
||||||
|
|
||||||
|
private static final Map<String, LocaleInstance> map = new HashMap<>();
|
||||||
|
|
||||||
|
static void sendTo(Plugin plugin, String path, CommandSender sender, String... args) {
|
||||||
|
Optional.ofNullable(map.get(plugin.getName())).ifPresent(localeInstance -> localeInstance.sendTo(path, sender, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sendTo(Plugin plugin, String path, CommandSender sender) {
|
||||||
|
Optional.ofNullable(map.get(plugin.getName())).ifPresent(localeInstance -> localeInstance.sendTo(path, sender));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
ConfigurationSerialization.registerClass(SimpleChatMessage.class);
|
||||||
|
ConfigurationSerialization.registerClass(SimpleChatMessage.class, "Message");
|
||||||
|
ConfigurationSerialization.registerClass(SimpleChatMessage.class, "MESSAGE");
|
||||||
|
ConfigurationSerialization.registerClass(SimpleChatMessage.class, "TEXT");
|
||||||
|
ConfigurationSerialization.registerClass(SimpleChatMessage.class, "Text");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void load(Plugin plugin, boolean ignoreLoaded) {
|
||||||
|
try {
|
||||||
|
if ((!ignoreLoaded || !map.containsKey(plugin.getName())) && plugin == Main.getInst() ||
|
||||||
|
plugin.getDescription().getDepend().contains("TabooLib") || plugin.getDescription().getSoftDepend().contains("TabooLib")) {
|
||||||
|
InputStream inputStream = null;
|
||||||
|
File file = null;
|
||||||
|
String lang = null;
|
||||||
|
for (String s : TLib.getTLib().getConfig().getLocale()) {
|
||||||
|
lang = s;
|
||||||
|
file = new File(plugin.getDataFolder(), "/lang/" + s + ".yml");
|
||||||
|
if (file.exists()) {
|
||||||
|
inputStream = Files.newInputStream(file.toPath(), StandardOpenOption.READ);
|
||||||
|
break;
|
||||||
|
} else if ((inputStream = plugin.getClass().getResourceAsStream("/lang/" + s + ".yml")) != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (inputStream == null) return;
|
||||||
|
TLib.getTLib().getLogger().info("尝试加载 " + lang + ".yml 作为语言文件");
|
||||||
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(new InputStreamReader(inputStream, Charset.forName("utf-8")));
|
||||||
|
LocaleInstance localeInstance = new LocaleInstance();
|
||||||
|
localeInstance.load(configuration);
|
||||||
|
map.put(plugin.getName(), localeInstance);
|
||||||
|
TConfigInjector.fixUnicode(configuration);
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
file.createNewFile();
|
||||||
|
}
|
||||||
|
configuration.save(file);
|
||||||
|
TLib.getTLib().getLogger().info("成功加载 " + lang + " 语言文件");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
TLib.getTLib().getLogger().error("载入语言文件发生异常:" + e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/main/java/com/ilummc/tlib/resources/Sendable.java
Normal file
21
src/main/java/com/ilummc/tlib/resources/Sendable.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package com.ilummc.tlib.resources;
|
||||||
|
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
public interface Sendable {
|
||||||
|
|
||||||
|
Sendable EMPTY = new Sendable() {
|
||||||
|
@Override
|
||||||
|
public void sendTo(CommandSender sender) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendTo(CommandSender sender, String... args) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void sendTo(CommandSender sender);
|
||||||
|
|
||||||
|
void sendTo(CommandSender sender, String... args);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package com.ilummc.tlib.resources;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.ilummc.tlib.TLib;
|
||||||
|
import com.ilummc.tlib.compat.PlaceholderApiHook;
|
||||||
|
import com.ilummc.tlib.util.Strings;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||||
|
import org.bukkit.configuration.serialization.SerializableAs;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
@SerializableAs("TEXT")
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public class SimpleChatMessage implements Sendable, ConfigurationSerializable {
|
||||||
|
|
||||||
|
private final Object text;
|
||||||
|
|
||||||
|
private final boolean usePlaceholder;
|
||||||
|
|
||||||
|
private SimpleChatMessage(Object text, boolean usePlaceholder) {
|
||||||
|
this.usePlaceholder = usePlaceholder;
|
||||||
|
if (text instanceof String)
|
||||||
|
this.text = text;
|
||||||
|
else if (text instanceof List)
|
||||||
|
this.text = ImmutableList.copyOf(((List) text));
|
||||||
|
else
|
||||||
|
throw new IllegalArgumentException("Param 'text' can only be an instance of String or String[] or List<String>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendTo(CommandSender sender) {
|
||||||
|
if (text instanceof String)
|
||||||
|
sender.sendMessage(replaceMsg(sender, (String) text));
|
||||||
|
else if (text instanceof List)
|
||||||
|
((List) text).forEach(s -> sender.sendMessage(replaceMsg(sender, String.valueOf(s))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendTo(CommandSender sender, String... args) {
|
||||||
|
if (text instanceof String)
|
||||||
|
sender.sendMessage(replaceMsg(sender, Strings.replaceWithOrder((String) text, args)));
|
||||||
|
else if (text instanceof List)
|
||||||
|
((List) text).forEach(s -> sender.sendMessage(replaceMsg(sender, Strings.replaceWithOrder(String.valueOf(s), args))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String replaceMsg(CommandSender sender, String s) {
|
||||||
|
return usePlaceholder ? PlaceholderApiHook.replace(sender, s) : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (text instanceof String[]) return Arrays.toString((String[]) text);
|
||||||
|
else return text.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> serialize() {
|
||||||
|
if (usePlaceholder) return Maps.newHashMap(ImmutableMap.of("text", text, "papi", true));
|
||||||
|
return Maps.newHashMap(ImmutableMap.of("text", text));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SimpleChatMessage valueOf(Map<String, Object> map) {
|
||||||
|
if (map.containsKey("text")) {
|
||||||
|
Object object = map.get("text");
|
||||||
|
Object objPapi = map.getOrDefault("papi", TLib.getTLib().getConfig().isEnablePapiByDefault());
|
||||||
|
boolean papi = objPapi instanceof Boolean ? (boolean) objPapi : objPapi instanceof String && objPapi.equals("true");
|
||||||
|
if (object instanceof List)
|
||||||
|
return new SimpleChatMessage(((List<String>) object).stream()
|
||||||
|
.map(s -> ChatColor.translateAlternateColorCodes('&', s))
|
||||||
|
.collect(Collectors.toList()), papi);
|
||||||
|
else if (object instanceof String[])
|
||||||
|
return new SimpleChatMessage(Arrays.stream(((String[]) object))
|
||||||
|
.map(s -> ChatColor.translateAlternateColorCodes('&', s))
|
||||||
|
.collect(Collectors.toList()), papi);
|
||||||
|
else
|
||||||
|
return new SimpleChatMessage(ChatColor.translateAlternateColorCodes('&', Objects.toString(object)), papi);
|
||||||
|
}
|
||||||
|
return new SimpleChatMessage("§cError chat message loaded.", TLib.getTLib().getConfig().isEnablePapiByDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SimpleChatMessage of(String s) {
|
||||||
|
return new SimpleChatMessage(ChatColor.translateAlternateColorCodes('&', s), TLib.getTLib().getConfig().isEnablePapiByDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
54
src/main/java/com/ilummc/tlib/resources/TLocale.java
Normal file
54
src/main/java/com/ilummc/tlib/resources/TLocale.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package com.ilummc.tlib.resources;
|
||||||
|
|
||||||
|
import com.ilummc.tlib.util.Ref;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
public final class TLocale {
|
||||||
|
|
||||||
|
private TLocale() {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sendTo(String path, CommandSender sender, String[] args, Class<?> callerClass) {
|
||||||
|
try {
|
||||||
|
Field pluginField = callerClass.getClassLoader().getClass().getDeclaredField("plugin");
|
||||||
|
pluginField.setAccessible(true);
|
||||||
|
JavaPlugin plugin = (JavaPlugin) pluginField.get(callerClass.getClassLoader());
|
||||||
|
if (args.length == 0)
|
||||||
|
LocaleLoader.sendTo(plugin, path, sender);
|
||||||
|
else
|
||||||
|
LocaleLoader.sendTo(plugin, path, sender, args);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendTo(String path, CommandSender sender, String... args) {
|
||||||
|
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, args, clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendTo(String path, CommandSender sender) {
|
||||||
|
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, new String[0], clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendTo(CommandSender sender, String path, String... args) {
|
||||||
|
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, args, clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendTo(CommandSender sender, String path) {
|
||||||
|
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, new String[0], clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToConsole(String path, String... args) {
|
||||||
|
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, Bukkit.getConsoleSender(), args, clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToConsole(String path) {
|
||||||
|
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, Bukkit.getConsoleSender(), new String[0], clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,6 +4,7 @@ import com.ilummc.tlib.TLib;
|
|||||||
import com.ilummc.tlib.util.asm.AsmAnalyser;
|
import com.ilummc.tlib.util.asm.AsmAnalyser;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import sun.reflect.Reflection;
|
||||||
|
|
||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -46,11 +47,10 @@ public class Ref {
|
|||||||
classReader.accept(analyser, ClassReader.SKIP_DEBUG);
|
classReader.accept(analyser, ClassReader.SKIP_DEBUG);
|
||||||
fields = analyser.getFields().stream().map(name -> {
|
fields = analyser.getFields().stream().map(name -> {
|
||||||
try {
|
try {
|
||||||
System.out.println(name);
|
|
||||||
return clazz.getDeclaredField(name);
|
return clazz.getDeclaredField(name);
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
}).filter(Objects::nonNull).collect(Collectors.toList());
|
||||||
if (cache) cachedFields.putIfAbsent(clazz.getName(), fields);
|
if (cache) cachedFields.putIfAbsent(clazz.getName(), fields);
|
||||||
return fields;
|
return fields;
|
||||||
@ -59,4 +59,44 @@ public class Ref {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Optional<Class<?>> getCallerClass(int depth) {
|
||||||
|
return Optional.ofNullable(CallerClass.impl.getCallerClass(depth + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static abstract class CallerClass {
|
||||||
|
|
||||||
|
private static CallerClass impl;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Class.forName("sun.reflect.Reflection");
|
||||||
|
impl = new ReflectionImpl();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
impl = new StackTraceImpl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract Class<?> getCallerClass(int i);
|
||||||
|
|
||||||
|
private static class ReflectionImpl extends CallerClass {
|
||||||
|
@Override
|
||||||
|
Class<?> getCallerClass(int i) {
|
||||||
|
return Reflection.getCallerClass(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StackTraceImpl extends CallerClass {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Class<?> getCallerClass(int i) {
|
||||||
|
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
|
||||||
|
try {
|
||||||
|
return Class.forName(elements[i].getClassName());
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ public class Strings {
|
|||||||
* @return 替换好的字符串
|
* @return 替换好的字符串
|
||||||
*/
|
*/
|
||||||
public static String replaceWithOrder(String template, String... args) {
|
public static String replaceWithOrder(String template, String... args) {
|
||||||
|
if (args.length == 0) return template;
|
||||||
char[] arr = template.toCharArray();
|
char[] arr = template.toCharArray();
|
||||||
StringBuilder stringBuilder = new StringBuilder(template.length());
|
StringBuilder stringBuilder = new StringBuilder(template.length());
|
||||||
for (int i = 0; i < arr.length; i++) {
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
0
src/main/resources/lang/zh_CN.yml
Normal file
0
src/main/resources/lang/zh_CN.yml
Normal file
Loading…
Reference in New Issue
Block a user