package io.izzel.taboolib; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import io.izzel.taboolib.client.TabooLibClient; import io.izzel.taboolib.client.TabooLibServer; import io.izzel.taboolib.module.dependency.TDependencyInjector; import io.izzel.taboolib.module.inject.TSchedule; import io.izzel.taboolib.util.Files; import io.izzel.taboolib.util.Reflection; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.*; import java.util.stream.Collectors; /** * @Author 坏黑 * @Since 2019-07-05 15:30 */ public class TabooLibLoader { static Map> pluginClasses = Maps.newHashMap(); static List loaders = Lists.newArrayList(); static void init() { // 加载依赖 TDependencyInjector.inject(TabooLib.getPlugin(), TabooLib.class); // 插件统计 Metrics metrics = new Metrics(TabooLib.getPlugin()); metrics.addCustomChart(new Metrics.SingleLineChart("plugins_using_taboolib", () -> Math.toIntExact(Arrays.stream(Bukkit.getPluginManager().getPlugins()).filter(TabooLibAPI::isDependTabooLib).count()))); // 读取插件类 setupClasses(TabooLib.getPlugin()); // 读取加载器 pluginClasses.get("TabooLib").stream().filter(TabooLibLoader::isLoader).forEach(pluginClass -> { try { loaders.add((Loader) Reflection.instantiateObject(pluginClass)); } catch (Exception e) { e.printStackTrace(); } loaders.sort(Comparator.comparingInt(Loader::priority)); }); // 加载插件 PluginLoader.load(TabooLib.getPlugin()); PluginLoader.start(TabooLib.getPlugin()); } public static Optional> getPluginClasses(Plugin plugin) { return Optional.ofNullable(pluginClasses.get(plugin.getName())); } public static List getPluginClassSafely(Plugin plugin) { List classes = pluginClasses.get(plugin.getName()); return classes == null ? new ArrayList<>() : new ArrayList<>(classes); } static boolean isLoader(Class pluginClass) { return !Loader.class.equals(pluginClass) && Loader.class.isAssignableFrom(pluginClass); } @TSchedule static void start() { PluginLoader.active(TabooLib.getPlugin()); // 通讯网络服务器 if (TabooLib.getConfig().getBoolean("SERVER")) { TabooLibServer.main(new String[0]); } // 通讯网络客户端 TabooLibClient.init(); } static void setupClasses(Plugin plugin) { try { long time = System.currentTimeMillis(); List classes; IgnoreClasses annotation = plugin.getClass().getAnnotation(IgnoreClasses.class); if (annotation != null) { classes = Files.getClasses(plugin, annotation.value()); } else { classes = Files.getClasses(plugin); } if (plugin.getName().equals("TabooLib")) { classes = classes.stream().filter(c -> c.getName().startsWith("io.izzel")).collect(Collectors.toList()); } TabooLibAPI.debug("Saved " + classes.size() + " classes (" + plugin.getName() + ") (" + (System.currentTimeMillis() - time) + "ms)"); pluginClasses.put(plugin.getName(), classes); } catch (Exception ignored) { } } static void preLoadClass(Plugin plugin, Class loadClass) { loaders.forEach(loader -> { try { loader.preLoad(plugin, loadClass); } catch (NoClassDefFoundError ignore) { } catch (Throwable e) { e.printStackTrace(); } }); } static void postLoadClass(Plugin plugin, Class loadClass) { loaders.forEach(loader -> { try { loader.postLoad(plugin, loadClass); } catch (NoClassDefFoundError ignore) { } catch (Throwable e) { e.printStackTrace(); } }); } static void unloadClass(Plugin plugin, Class loadClass) { loaders.forEach(loader -> { try { loader.unload(plugin, loadClass); } catch (NoClassDefFoundError ignore) { } catch (Throwable e) { e.printStackTrace(); } }); } public interface Loader { default void preLoad(org.bukkit.plugin.Plugin plugin, Class loadClass) { } default void postLoad(org.bukkit.plugin.Plugin plugin, Class loadClass) { } default void unload(Plugin plugin, Class cancelClass) { } default int priority() { return 0; } } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface IgnoreClasses { String[] value(); } }