船新 I18n 系统

修了一个配置文件小bug
This commit is contained in:
Izzel_Aliz 2018-04-22 13:30:50 +08:00
parent 385b2aa974
commit c573617a01
18 changed files with 479 additions and 38 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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
View File

@ -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>

View File

@ -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;
}
} }
} }

View File

@ -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;

View 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;
}
}
}

View File

@ -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();
} }

View File

@ -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));

View File

@ -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) {

View 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))));
});
}
}

View 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());
}
}
}

View 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);
}

View File

@ -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());
}
}

View 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));
}
}

View File

@ -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;
}
}
}
}
} }

View File

@ -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++) {

View File