This commit is contained in:
坏黑
2018-04-22 22:12:42 +08:00
parent c573617a01
commit b49a779859
126 changed files with 1896 additions and 705 deletions

View File

@@ -1,9 +1,10 @@
package com.ilummc.tlib;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import com.ilummc.tlib.annotations.Config;
import com.ilummc.tlib.bean.Property;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
@Config(name = "cfg.yml", charset = "GBK")
public class ExampleMain extends JavaPlugin {

View File

@@ -1,105 +1,76 @@
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.compat.PlaceholderApiHook;
import com.ilummc.tlib.inject.DependencyInjector;
import com.ilummc.tlib.inject.TConfigWatcher;
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 me.skymc.taboolib.Main;
import org.bukkit.Bukkit;
import java.io.File;
import java.lang.reflect.Field;
import org.bukkit.Bukkit;
import com.ilummc.tlib.annotations.Dependency;
import com.ilummc.tlib.compat.PlaceholderHook;
import com.ilummc.tlib.config.TLibConfig;
import com.ilummc.tlib.filter.TLoggerFilter;
import com.ilummc.tlib.inject.TConfigWatcher;
import com.ilummc.tlib.inject.TDependencyInjector;
import com.ilummc.tlib.inject.TPluginManager;
import com.ilummc.tlib.resources.TLocaleLoader;
import com.ilummc.tlib.util.TLogger;
import lombok.Getter;
import me.skymc.taboolib.Main;
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.ow2.asm:asm:6.1.1")
@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.1.0")
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.slf4j:slf4j-api:1.7.25")
public class TLib {
@Getter
private static TLib tLib;
@Logger("§8[§3§lTabooLib§8][§r{1}§8] §f{2}")
private TLogger tLogger = new TLogger("§8[§3§lTabooLib§8][§r{1}§8] §f{2}", Main.getInst(), TLogger.FINE);
@Getter
private TLogger logger = new TLogger("§8[§3§lTabooLib§8][§r{1}§8] §f{2}", Main.getInst(), TLogger.FINE);
@Getter
private TLibConfig config;
@Getter
private TConfigWatcher configWatcher = new TConfigWatcher();
@Getter
private File libsFolder;
private TLib() {
}
public TLibConfig getConfig() {
return config;
}
public TLogger getLogger() {
return tLogger;
}
public TConfigWatcher getConfigWatcher() {
return configWatcher;
}
public static TLib getTLib() {
return tLib;
}
public static void injectPluginManager() {
// 注入 PluginLoader 用于加载依赖
try {
Field field = Bukkit.getServer().getClass().getDeclaredField("pluginManager");
field.setAccessible(true);
field.set(Bukkit.getServer(), new TLibPluginManager());
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
libsFolder = new File(Main.getInst().getDataFolder(), "/libs");
if (!libsFolder.exists()) {
libsFolder.mkdirs();
}
}
public static void init() {
new File(Main.getInst().getDataFolder(), "/libs").mkdirs();
tLib = new TLib();
LocaleLoader.init();
PlaceholderApiHook.init();
DependencyInjector.inject(Main.getInst(), tLib);
if (Bukkit.getPluginManager() instanceof TLibPluginManager)
TLoggerFilter.init();
TLocaleLoader.init();
PlaceholderHook.init();
TDependencyInjector.inject(Main.getInst(), tLib);
if (Bukkit.getPluginManager() instanceof TPluginManager) {
tLib.getLogger().info("注入成功");
else
} else {
tLib.getLogger().fatal("注入失败");
TLocale.sendToConsole("test1");
TLocale.sendToConsole("test2");
TLocale.sendToConsole("test3");
TLocale.sendToConsole("test4.node1", "Hello", "world");
}
}
public static void unload() {
tLib.getConfigWatcher().unregisterAll();
DependencyInjector.eject(Main.getInst(), tLib);
TDependencyInjector.eject(Main.getInst(), tLib);
}
@Config(name = "tlib.yml", listenChanges = true, readOnly = false)
public static class TLibConfig {
private int downloadPoolSize = 4;
public int getDownloadPoolSize() {
return downloadPoolSize;
}
private String[] locale = {"zh_CN", "en_US"};
public String[] getLocale() {
return locale;
}
private boolean enablePapiByDefault = false;
public boolean isEnablePapiByDefault() {
return enablePapiByDefault;
public static void injectPluginManager() {
try {
Field field = Bukkit.getServer().getClass().getDeclaredField("pluginManager");
field.setAccessible(true);
field.set(Bukkit.getServer(), new TPluginManager());
} catch (NoSuchFieldException | IllegalAccessException ignored) {
}
}
}

View File

@@ -1,13 +1,13 @@
package com.ilummc.tlib.annotations;
import com.ilummc.tlib.util.Ref;
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;
import com.ilummc.tlib.util.Ref;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Config {

View File

@@ -1,8 +1,12 @@
package com.ilummc.tlib.annotations;
import com.ilummc.tlib.dependency.TDependency;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.*;
import com.ilummc.tlib.dependency.TDependency;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -1,12 +1,12 @@
package com.ilummc.tlib.annotations;
import com.ilummc.tlib.util.TLogger;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ilummc.tlib.util.TLogger;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Logger {

View File

@@ -1,12 +1,12 @@
package com.ilummc.tlib.bean;
import java.lang.reflect.Type;
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<Property> {
@Override

View File

@@ -0,0 +1,41 @@
package com.ilummc.tlib.compat;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import me.clip.placeholderapi.PlaceholderAPI;
public abstract class PlaceholderHook {
private static PlaceholderHook 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 PlaceholderHook {
@Override
String replace(Player player, String text) {
return PlaceholderAPI.setPlaceholders(player, text);
}
}
private static class AbstractImpl extends PlaceholderHook {
@Override
String replace(Player player, String text) {
return text;
}
}
}

View File

@@ -0,0 +1,23 @@
package com.ilummc.tlib.config;
import com.ilummc.tlib.annotations.Config;
/**
* @author sky
* @since 2018-04-22 14:31:11
*/
@Config(name = "tlib.yml", listenChanges = true, readOnly = false)
public class TLibConfig {
private String[] locale = {"zh_CN", "en_US"};
public String[] getLocale() {
return locale;
}
private boolean enablePlaceholderHookByDefault = false;
public boolean isEnablePlaceholderHookByDefault() {
return enablePlaceholderHookByDefault;
}
}

View File

@@ -1,12 +1,13 @@
package com.ilummc.tlib.dependency;
import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;
import com.ilummc.eagletdl.EagletTask;
import com.ilummc.eagletdl.ProgressEvent;
import com.ilummc.tlib.TLib;
import me.skymc.taboolib.Main;
import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;
import me.skymc.taboolib.Main;
public class TDependency {
@@ -43,8 +44,9 @@ public class TDependency {
if (downloadMaven(repo, arr[0], arr[1], arr[2], file, url)) {
TDependencyLoader.addToPath(Main.getInst(), file);
return true;
} else
} else {
return false;
}
}
}
return false;
@@ -60,14 +62,10 @@ public class TDependency {
new EagletTask()
.url(link)
.file(target)
.setThreads(TLib.getTLib().getConfig().getDownloadPoolSize())
.setOnError(event -> {
})
.setOnConnected(event -> TLib.getTLib().getLogger().info(" 正在下载 " + String.join(":",
new String[]{groupId, artifactId, version}) +
" 大小 " + ProgressEvent.format(event.getContentLength())))
.setOnProgress(event -> TLib.getTLib().getLogger().info(" 下载速度 " + event.getSpeedFormatted()
+ " 进度 " + event.getPercentageFormatted()))
.setThreads(getDownloadPoolSize())
.setOnError(event -> {})
.setOnConnected(event -> TLib.getTLib().getLogger().info(" 正在下载 " + String.join(":", new String[]{groupId, artifactId, version}) + " 大小 " + ProgressEvent.format(event.getContentLength())))
.setOnProgress(event -> TLib.getTLib().getLogger().info(" 下载速度 " + event.getSpeedFormatted() + " 进度 " + event.getPercentageFormatted()))
.setOnComplete(event -> {
if (event.isSuccess()) {
TLib.getTLib().getLogger().info(" 下载 " + String.join(":", new String[]{groupId, artifactId, version}) + " 完成");
@@ -79,5 +77,8 @@ public class TDependency {
}).start().waitUntil();
return !failed.get();
}
private static int getDownloadPoolSize() {
return Main.getInst().getConfig().contains("DOWNLOAD-POOL-SIZE") ? Main.getInst().getConfig().getInt("DOWNLOAD-POOL-SIZE") : 4;
}
}

View File

@@ -1,7 +1,5 @@
package com.ilummc.tlib.dependency;
import org.bukkit.plugin.Plugin;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -9,6 +7,8 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import org.bukkit.plugin.Plugin;
public class TDependencyLoader {
public static synchronized void addToPath(Plugin plugin, URL url) {

View File

@@ -0,0 +1,32 @@
package com.ilummc.tlib.filter;
import java.util.Arrays;
import java.util.logging.Filter;
import java.util.logging.LogRecord;
import org.bukkit.Bukkit;
/**
* @author Bkm016
* @since 2018-04-22
*/
public class TLoggerFilter implements Filter {
public static void init() {
Bukkit.getLogger().setFilter(new TLoggerFilter());
}
@Override
public boolean isLoggable(LogRecord e) {
if (e.getMessage().contains("Cannot load configuration from stream")) {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (StackTraceElement element : elements) {
if (element.getClassName().contains("ConfigUtils")) {
System.out.println(Arrays.asList(e.getParameters()));
}
}
return false;
}
return true;
}
}

View File

@@ -1,5 +1,25 @@
package com.ilummc.tlib.inject;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.Validate;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.plugin.Plugin;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
@@ -9,24 +29,10 @@ 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.file.YamlConfiguration;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
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.Field;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;
public class TConfigInjector {
public static void fixUnicode(YamlConfiguration configuration) {
public static void fixUnicode(FileConfiguration configuration) {
try {
Field field = YamlConfiguration.class.getDeclaredField("yamlOptions");
field.setAccessible(true);

View File

@@ -1,11 +1,12 @@
package com.ilummc.tlib.inject;
import com.ilummc.tlib.TLib;
import org.apache.commons.lang3.tuple.Triple;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.FileSystems;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@@ -14,6 +15,8 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import org.apache.commons.lang3.tuple.Triple;
public class TConfigWatcher {
private ScheduledExecutorService service = Executors.newScheduledThreadPool(1);

View File

@@ -0,0 +1,173 @@
package com.ilummc.tlib.inject;
import java.io.File;
import java.lang.reflect.Field;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import com.ilummc.tlib.TLib;
import com.ilummc.tlib.annotations.Config;
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.dependency.TDependency;
import com.ilummc.tlib.resources.TLocaleLoader;
import com.ilummc.tlib.util.Ref;
import com.ilummc.tlib.util.TLogger;
public class TDependencyInjector {
public static void inject(Plugin plugin, Object o) {
injectDependencies(plugin, o);
injectLogger(plugin, o);
injectConfig(plugin, o);
injectPluginInstance(plugin, o);
TLocaleLoader.load(plugin, true);
}
static void injectOnEnable(Plugin plugin) {
inject(plugin, plugin);
}
static void onDisable(Plugin plugin) {
eject(plugin, plugin);
}
public static void eject(Plugin plugin, Object o) {
try {
ejectConfig(plugin, o);
} catch (Throwable ignored) {
}
}
private static void ejectConfig(Plugin plugin, Object o) {
for (Field field : Ref.getDeclaredFields(o.getClass())) {
Config config;
if ((config = field.getType().getAnnotation(Config.class)) != null && config.saveOnExit()) {
try {
field.setAccessible(true);
TConfigInjector.saveConfig(plugin, field.get(o));
TLib.getTLib().getLogger().info("插件 " + plugin + " 的配置 " + config.name() + " 已保存");
} catch (Exception e) {
TLib.getTLib().getLogger().warn("插件 " + plugin + " 的配置 " + config.name() + " 保存失败");
e.printStackTrace();
}
}
}
}
private static void injectConfig(Plugin plugin, Object o) {
for (Field field : Ref.getDeclaredFields(o.getClass())) {
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);
if (config.listenChanges()) {
TLib.getTLib().getLogger().info("开始监听插件 " + plugin.getName() + "" + config.name() + " 配置文件");
TLib.getTLib().getConfigWatcher().addOnListen(
new File(plugin.getDataFolder(), config.name()),
obj,
object -> {
try {
Object newObj = TConfigInjector.loadConfig(plugin, object.getClass());
for (Field f : newObj.getClass().getDeclaredFields()) {
f.setAccessible(true);
f.set(obj, f.get(newObj));
}
TLib.getTLib().getLogger().info("插件 " + plugin.getName() + "" + config.name() + " 配置文件成功重载");
} catch (Exception ignored) {
TLib.getTLib().getLogger().warn("插件 " + plugin.getName() + "" + config.name() + " 配置文件重载时发生错误");
}
}
);
}
}
}
} catch (Exception ignored) {
}
}
}
private static void injectLogger(Plugin plugin, Object o) {
for (Field field : Ref.getDeclaredFields(o.getClass())) {
try {
Logger logger;
if ((logger = field.getAnnotation(Logger.class)) != null) {
field.getType().asSubclass(TLogger.class);
TLogger tLogger = new TLogger(logger.value(), plugin, logger.level());
if (!field.isAccessible())
field.setAccessible(true);
field.set(o, tLogger);
}
} catch (Exception ignored2) {
}
}
}
private static void injectPluginInstance(Plugin plugin, Object o) {
for (Field field : Ref.getDeclaredFields(o.getClass())) {
try {
PluginInstance instance;
if ((instance = field.getAnnotation(PluginInstance.class)) != null) {
if (!field.isAccessible())
field.setAccessible(true);
field.getType().asSubclass(JavaPlugin.class);
Plugin pl;
if ((pl = Bukkit.getPluginManager().getPlugin(instance.value())) == null) {
if (!TDependency.requestPlugin(instance.value())) {
TLib.getTLib().getLogger().warn(plugin.getName() + " 所需的依赖插件 " + instance.value() + " 自动加载失败");
return;
} else {
pl = Bukkit.getPluginManager().getPlugin(instance.value());
}
}
if (pl != null)
field.set(o, pl);
}
} catch (Exception ignored) {
}
}
}
private static void injectDependencies(Plugin plugin, Object o) {
Dependency[] dependencies = new Dependency[0];
{
Dependencies d = o.getClass().getAnnotation(Dependencies.class);
if (d != null) {
dependencies = d.value();
}
Dependency d2 = o.getClass().getAnnotation(Dependency.class);
if (d2 != null) {
dependencies = new Dependency[]{d2};
}
}
if (dependencies.length != 0) {
TLib.getTLib().getLogger().info("正在加载 " + plugin.getName() + " 插件所需的依赖");
for (Dependency dependency : dependencies) {
if (dependency.type() == Dependency.Type.PLUGIN) {
if (TDependency.requestPlugin(dependency.plugin())) {
TLib.getTLib().getLogger().info(" " + plugin.getName() + " 请求的插件 " + dependency.plugin() + " 加载成功。");
} else {
TLib.getTLib().getLogger().warn(" " + plugin.getName() + " 请求的插件 " + dependency.plugin() + " 加载失败。");
}
}
if (dependency.type() == Dependency.Type.LIBRARY) {
if (TDependency.requestLib(dependency.maven(), dependency.mavenRepo(), dependency.url())) {
TLib.getTLib().getLogger().info(" " + plugin.getName() + " 请求的库文件 " + String.join(":", dependency.maven()) + " 加载成功。");
} else {
TLib.getTLib().getLogger().warn(" " + plugin.getName() + " 请求的库文件 " + String.join(":", dependency.maven()) + " 加载失败。");
}
}
}
TLib.getTLib().getLogger().info("依赖加载完成");
}
}
}

View File

@@ -0,0 +1,181 @@
package com.ilummc.tlib.inject;
import java.io.File;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.permissions.Permissible;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.EventExecutor;
import org.bukkit.plugin.InvalidDescriptionException;
import org.bukkit.plugin.InvalidPluginException;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginLoader;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.UnknownDependencyException;
import me.skymc.taboolib.Main;
public class TPluginManager implements PluginManager {
private final PluginManager instance;
private final Main main = (Main) Main.getInst();
public TPluginManager() {
instance = Bukkit.getPluginManager();
}
@Override
public void registerInterface(Class<? extends PluginLoader> aClass) throws IllegalArgumentException {
instance.registerInterface(aClass);
}
@Override
public Plugin getPlugin(String s) {
return instance.getPlugin(s);
}
@Override
public Plugin[] getPlugins() {
return instance.getPlugins();
}
@Override
public boolean isPluginEnabled(String s) {
return instance.isPluginEnabled(s);
}
@Override
public boolean isPluginEnabled(Plugin plugin) {
return instance.isPluginEnabled(plugin);
}
@Override
public Plugin loadPlugin(File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException {
return instance.loadPlugin(file);
}
@Override
public Plugin[] loadPlugins(File file) {
return instance.loadPlugins(file);
}
@Override
public void disablePlugins() {
for (Plugin plugin : getPlugins()) {
if (plugin != main) disablePlugin(plugin);
}
disablePlugin(main);
}
@Override
public void clearPlugins() {
instance.clearPlugins();
}
@Override
public void callEvent(Event event) throws IllegalStateException {
instance.callEvent(event);
}
@Override
public void registerEvents(Listener listener, Plugin plugin) {
instance.registerEvents(listener, plugin);
}
@Override
public void registerEvent(Class<? extends Event> aClass, Listener listener, EventPriority eventPriority, EventExecutor eventExecutor, Plugin plugin) {
instance.registerEvent(aClass, listener, eventPriority, eventExecutor, plugin);
}
@Override
public void registerEvent(Class<? extends Event> aClass, Listener listener, EventPriority eventPriority, EventExecutor eventExecutor, Plugin plugin, boolean b) {
instance.registerEvent(aClass, listener, eventPriority, eventExecutor, plugin, b);
}
@Override
public void enablePlugin(Plugin plugin) {
TDependencyInjector.injectOnEnable(plugin);
instance.enablePlugin(plugin);
}
@Override
public void disablePlugin(Plugin plugin) {
TDependencyInjector.onDisable(plugin);
instance.disablePlugin(plugin);
}
@Override
public Permission getPermission(String s) {
return instance.getPermission(s);
}
@Override
public void addPermission(Permission permission) {
instance.addPermission(permission);
}
@Override
public void removePermission(Permission permission) {
instance.removePermission(permission);
}
@Override
public void removePermission(String s) {
instance.removePermission(s);
}
@Override
public Set<Permission> getDefaultPermissions(boolean b) {
return instance.getDefaultPermissions(b);
}
@Override
public void recalculatePermissionDefaults(Permission permission) {
instance.recalculatePermissionDefaults(permission);
}
@Override
public void subscribeToPermission(String s, Permissible permissible) {
instance.subscribeToPermission(s, permissible);
}
@Override
public void unsubscribeFromPermission(String s, Permissible permissible) {
instance.unsubscribeFromPermission(s, permissible);
}
@Override
public Set<Permissible> getPermissionSubscriptions(String s) {
return instance.getPermissionSubscriptions(s);
}
@Override
public void subscribeToDefaultPerms(boolean b, Permissible permissible) {
instance.subscribeToDefaultPerms(b, permissible);
}
@Override
public void unsubscribeFromDefaultPerms(boolean b, Permissible permissible) {
instance.unsubscribeFromDefaultPerms(b, permissible);
}
@Override
public Set<Permissible> getDefaultPermSubscriptions(boolean b) {
return instance.getDefaultPermSubscriptions(b);
}
@Override
public Set<Permission> getPermissions() {
return instance.getPermissions();
}
@Override
public boolean useTimings() {
return instance.useTimings();
}
}

View File

@@ -1,54 +1,69 @@
package com.ilummc.tlib.resources;
import com.ilummc.tlib.util.Ref;
import java.lang.reflect.Field;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import java.lang.reflect.Field;
import com.google.common.base.Strings;
import com.ilummc.tlib.TLib;
import com.ilummc.tlib.util.Ref;
import me.skymc.taboolib.Main;
import me.skymc.taboolib.TabooLib;
public final class TLocale {
private TLocale() {
throw new AssertionError();
}
private static JavaPlugin getCallerPlugin(Class<?> callerClass) {
try {
Field pluginField = callerClass.getClassLoader().getClass().getDeclaredField("plugin");
pluginField.setAccessible(true);
return (JavaPlugin) pluginField.get(callerClass.getClassLoader());
} catch (Exception ignored) {
TLib.getTLib().getLogger().error("无效的语言文件发送形式: &4" + callerClass.getName());
}
return (JavaPlugin) Main.getInst();
}
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();
}
TLocaleLoader.sendTo(getCallerPlugin(callerClass), path, sender, args);
}
public static void sendTo(String path, CommandSender sender, String... args) {
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, args, clazz));
private static String asString(String path, String[] args, Class<?> callerClass) {
return TLocaleLoader.asString(getCallerPlugin(callerClass), path);
}
public static void sendTo(String path, CommandSender sender) {
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 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 sendTo(String path, CommandSender sender, String... args) {
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, sender, args, clazz));
}
public static void sendToConsole(String path, String... args) {
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, Bukkit.getConsoleSender(), args, clazz));
public static String asString(String path, String... args) {
try {
return asString(path, args, Ref.getCallerClass(3).get());
} catch (Exception e) {
TLib.getTLib().getLogger().error("语言文件获取失败: " + path);
TLib.getTLib().getLogger().error("原因: " + e.getMessage());
return "§4<" + path + "§4>";
}
}
public static void sendToConsole(String path) {
Ref.getCallerClass(3).ifPresent(clazz -> sendTo(path, Bukkit.getConsoleSender(), new String[0], clazz));
public static void reload() {
Ref.getCallerClass(3).ifPresent(clazz -> TLocaleLoader.load(getCallerPlugin(clazz), false));
}
}

View File

@@ -0,0 +1,98 @@
package com.ilummc.tlib.resources;
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;
import javax.annotation.concurrent.ThreadSafe;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import com.google.common.collect.ImmutableList;
import com.ilummc.tlib.TLib;
import com.ilummc.tlib.resources.type.TLocaleText;
@ThreadSafe
@SuppressWarnings("rawtypes")
class TLocaleInstance {
TLocaleInstance() {
}
void sendTo(String path, CommandSender sender) {
try {
map.getOrDefault(path, ImmutableList.of(TLocaleSendable.getEmpty(path))).forEach(sendable -> sendable.sendTo(sender));
} catch (Exception e) {
TLib.getTLib().getLogger().error("语言文件发送失败: " + path);
TLib.getTLib().getLogger().error("原因: " + e.getMessage());
}
}
void sendTo(String path, CommandSender sender, String... args) {
try {
map.getOrDefault(path, ImmutableList.of(TLocaleSendable.getEmpty(path))).forEach(sendable -> sendable.sendTo(sender, args));
} catch (Exception e) {
TLib.getTLib().getLogger().error("语言文件发送失败: " + path);
TLib.getTLib().getLogger().error("原因: " + e.getMessage());
}
}
String asString(String path) {
return map.getOrDefault(path, ImmutableList.of(TLocaleSendable.getEmpty(path))).get(0).asString();
}
void load(FileConfiguration configuration) {
configuration.getKeys(false).forEach(s -> {
Object object = configuration.get(s);
if (object instanceof ConfigurationSection) {
loadRecursively(s, (ConfigurationSection) object);
}
else if (object instanceof TLocaleSendable) {
map.put(s, Collections.singletonList((TLocaleSendable) 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(TLocaleText.of(String.valueOf(object))));
}
});
}
private static final Function<Object, TLocaleSendable> TO_SENDABLE = o -> {
if (o instanceof TLocaleSendable) {
return ((TLocaleSendable) o);
} else if (o instanceof String) {
return TLocaleText.of(((String) o));
} else {
return TLocaleText.of(String.valueOf(o));
}
};
private final Map<String, List<TLocaleSendable>> map = new ConcurrentHashMap<>();
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 TLocaleSendable) {
map.put(path + "." + s, Collections.singletonList((TLocaleSendable) 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(TLocaleText.of(String.valueOf(object))));
}
});
}
}

View File

@@ -0,0 +1,104 @@
package com.ilummc.tlib.resources;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.channels.FileChannel;
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;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.plugin.Plugin;
import com.ilummc.tlib.TLib;
import com.ilummc.tlib.inject.TConfigInjector;
import com.ilummc.tlib.resources.type.TLocaleText;
import me.skymc.taboolib.Main;
import me.skymc.taboolib.fileutils.ConfigUtils;
import me.skymc.taboolib.fileutils.FileUtils;
public class TLocaleLoader {
private static final Map<String, TLocaleInstance> 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 String asString(Plugin plugin, String path) {
return Optional.ofNullable(map.get(plugin.getName())).get().asString(path);
}
public static void init() {
ConfigurationSerialization.registerClass(TLocaleText.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) {
TLib.getTLib().getLogger().error("语言文件加载失败");
return;
}
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
saveResource(inputStream, file);
}
TLib.getTLib().getLogger().info("尝试加载 " + lang + ".yml 作为语言文件");
FileConfiguration configuration = ConfigUtils.load(plugin, file);
TLocaleInstance localeInstance = new TLocaleInstance();
localeInstance.load(configuration);
map.put(plugin.getName(), localeInstance);
TConfigInjector.fixUnicode(configuration);
TLib.getTLib().getLogger().info("成功加载 " + lang + " 语言文件");
}
} catch (Exception e) {
TLib.getTLib().getLogger().error("载入语言文件发生异常:" + e.toString());
}
}
private static void saveResource(InputStream inputStream, File file) {
FileOutputStream fileOutputStream = null;
try {
byte[] data = FileUtils.read(inputStream);
fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(data);
} catch (Exception e) {
TLib.getTLib().getLogger().error("资源文件写入失败: " + file);
TLib.getTLib().getLogger().error("原因: " + e.getMessage());
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (Exception ignored) {
}
}
}
}

View File

@@ -0,0 +1,25 @@
package com.ilummc.tlib.resources;
import org.bukkit.command.CommandSender;
public interface TLocaleSendable {
public static TLocaleSendable getEmpty(String path) {
return new TLocaleSendable() {
@Override
public void sendTo(CommandSender sender, String... args) {
sender.sendMessage("§4<" + path + "§4>");
}
@Override
public String asString(String... args) {
return "§4<" + path + "§4>";
}
};
}
void sendTo(CommandSender sender, String... args);
String asString(String... args);
}

View File

@@ -0,0 +1,107 @@
package com.ilummc.tlib.resources.type;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.concurrent.Immutable;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.SerializableAs;
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.PlaceholderHook;
import com.ilummc.tlib.resources.TLocaleSendable;
import com.ilummc.tlib.util.Strings;
@Immutable
@SerializableAs("TEXT")
@SuppressWarnings({"unchecked", "rawtypes"})
public class TLocaleText implements TLocaleSendable, ConfigurationSerializable {
private final Object text;
private final boolean usePlaceholder;
private TLocaleText(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>");
}
}
private String replaceMsg(CommandSender sender, String s) {
return usePlaceholder ? PlaceholderHook.replace(sender, s) : 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))));
}
}
@Override
public String asString(String... args) {
return Strings.replaceWithOrder((String) text, args);
}
@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 TLocaleText valueOf(Map<String, Object> map) {
if (map.containsKey("text")) {
Object object = map.get("text");
Object objPapi = map.getOrDefault("papi", TLib.getTLib().getConfig().isEnablePlaceholderHookByDefault());
boolean papi = objPapi instanceof Boolean ? (boolean) objPapi : objPapi instanceof String && objPapi.equals("true");
if (object instanceof List) {
return new TLocaleText(((List<String>) object).stream()
.map(s -> ChatColor.translateAlternateColorCodes('&', s))
.collect(Collectors.toList()), papi);
}
else if (object instanceof String[]) {
return new TLocaleText(Arrays.stream(((String[]) object))
.map(s -> ChatColor.translateAlternateColorCodes('&', s))
.collect(Collectors.toList()), papi);
}
else {
return new TLocaleText(ChatColor.translateAlternateColorCodes('&', Objects.toString(object)), papi);
}
}
return new TLocaleText("§cError chat message loaded.", TLib.getTLib().getConfig().isEnablePlaceholderHookByDefault());
}
public static TLocaleText of(String s) {
return new TLocaleText(ChatColor.translateAlternateColorCodes('&', s), TLib.getTLib().getConfig().isEnablePlaceholderHookByDefault());
}
}

View File

@@ -0,0 +1,83 @@
package com.ilummc.tlib.resources.type;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.concurrent.Immutable;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.SerializableAs;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.ilummc.tlib.TLib;
import com.ilummc.tlib.resources.TLocaleSendable;
import lombok.Data;
import lombok.Getter;
import net.minecraft.server.v1_11_R1.EntityEvoker.e;
/**
* @author Bkm016
* @since 2018-04-22
*/
@Immutable
@SerializableAs("TITLE")
@Data
public class TLocaleTitle implements TLocaleSendable, ConfigurationSerializable {
private String title;
private String subtitle;
private int fadein;
private int fadeout;
private int stay;
private boolean usePlaceholder;
private TLocaleTitle(boolean usePlaceholder) {
this.usePlaceholder = usePlaceholder;
}
@Override
public void sendTo(CommandSender sender, String... args) {
// TODO Auto-generated method stub
}
@Override
public String asString(String... args) {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<String, Object> serialize() {
HashMap<String, Object> map = Maps.newHashMap();
map.put("papi", usePlaceholder);
map.put("title", title);
map.put("subtitle", subtitle);
map.put("fadein", fadein);
map.put("fadeout", fadeout);
map.put("stay", stay);
return map;
}
public static TLocaleTitle valueOf(Map<String, Object> map) {
TLocaleTitle title;
try {
title = new TLocaleTitle((boolean) map.getOrDefault("papi", TLib.getTLib().getConfig().isEnablePlaceholderHookByDefault()));
title.setTitle((String) map.getOrDefault("title", ""));
title.setSubtitle((String) map.getOrDefault("subtitle", ""));
title.setFadein((int) map.getOrDefault("fadein", 10));
title.setFadeout((int) map.getOrDefault("fadeout", 10));
title.setStay((int) map.getOrDefault("stay", 10));
} catch (Exception e) {
title = new TLocaleTitle(false);
title.setTitle("§4Load failed!");
title.setSubtitle("§c" + e.getMessage());
}
return title;
}
}

View File

@@ -1,16 +1,24 @@
package com.ilummc.tlib.util;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import javax.annotation.concurrent.ThreadSafe;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import com.ilummc.tlib.TLib;
import com.ilummc.tlib.util.asm.AsmAnalyser;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import sun.reflect.Reflection;
import javax.annotation.concurrent.ThreadSafe;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import sun.reflect.Reflection;
@ThreadSafe
public class Ref {
@@ -62,7 +70,7 @@ 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;
@@ -79,7 +87,9 @@ public class Ref {
abstract Class<?> getCallerClass(int i);
private static class ReflectionImpl extends CallerClass {
@Override
@SuppressWarnings({ "deprecation", "restriction" })
@Override
Class<?> getCallerClass(int i) {
return Reflection.getCallerClass(i);
}

View File

@@ -1,9 +1,11 @@
package com.ilummc.tlib.util;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.plugin.Plugin;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
public class TLogger {
@@ -27,37 +29,37 @@ public class TLogger {
public void verbose(String msg) {
if (level <= VERBOSE)
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§f全部", msg));
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§f全部", ChatColor.translateAlternateColorCodes('&', msg)));
}
public void finest(String msg) {
if (level <= FINEST)
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§e良好", msg));
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§e良好", ChatColor.translateAlternateColorCodes('&', msg)));
}
public void fine(String msg) {
if (level <= FINE)
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§a正常", msg));
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§a正常", ChatColor.translateAlternateColorCodes('&', msg)));
}
public void info(String msg) {
if (level <= INFO)
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§b信息", msg));
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§b信息", ChatColor.translateAlternateColorCodes('&', msg)));
}
public void warn(String msg) {
if (level <= WARN)
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§6警告", "§6" + msg));
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§6警告", "§6" + ChatColor.translateAlternateColorCodes('&', msg)));
}
public void error(String msg) {
if (level <= ERROR)
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§c错误", "§c" + msg));
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§c错误", "§c" + ChatColor.translateAlternateColorCodes('&', msg)));
}
public void fatal(String msg) {
if (level <= FATAL)
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§4致命错误", "§4" + msg));
Bukkit.getConsoleSender().sendMessage(Strings.replaceWithOrder(pattern, plugin.getName(), "§4致命错误", "§4" + ChatColor.translateAlternateColorCodes('&', msg)));
}
}

View File

@@ -1,12 +1,12 @@
package com.ilummc.tlib.util.asm;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List;
public class AsmAnalyser extends ClassVisitor implements Opcodes {
private final List<String> fields = new ArrayList<>();