From 19b4bd9a6b825e3ef46db805a91e1bed3292ad2b Mon Sep 17 00:00:00 2001 From: Izzel_Aliz Date: Sun, 29 Apr 2018 22:32:39 +0800 Subject: [PATCH] =?UTF-8?q?=E8=88=B9=E6=96=B0=E4=B8=A4=E4=B8=AA=20Sendable?= =?UTF-8?q?=20Json=20=E5=92=8C=20ActionBar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/ilummc/tlib/nms/ActionBar.java | 1 - .../tlib/resources/TLocaleInstance.java | 5 +- .../ilummc/tlib/resources/TLocaleLoader.java | 4 + .../tlib/resources/type/TLocaleActionBar.java | 61 +++ .../tlib/resources/type/TLocaleJson.java | 153 +++++++ .../tlib/resources/type/TLocaleTitle.java | 4 +- .../tlib/util/asm/AsmClassTransformer.java | 66 +-- .../skymc/taboolib/javashell/JavaShell.java | 378 +++++++++--------- .../taboolib/javashell/utils/JarUtils.java | 23 +- src/main/resources/internalLang.yml | 3 +- 10 files changed, 453 insertions(+), 245 deletions(-) create mode 100644 src/main/java/com/ilummc/tlib/resources/type/TLocaleActionBar.java create mode 100644 src/main/java/com/ilummc/tlib/resources/type/TLocaleJson.java diff --git a/src/main/java/com/ilummc/tlib/nms/ActionBar.java b/src/main/java/com/ilummc/tlib/nms/ActionBar.java index 5dc685f..7ef5d6a 100644 --- a/src/main/java/com/ilummc/tlib/nms/ActionBar.java +++ b/src/main/java/com/ilummc/tlib/nms/ActionBar.java @@ -17,7 +17,6 @@ public abstract class ActionBar { instance = (ActionBar) AsmClassTransformer.builder().from(Impl_1_8.class).fromVersion("v1_8_R3") .toVersion(Bukkit.getServer().getClass().getName().split("\\.")[3]).build().transform(); } - System.out.println(instance.getClass()); } public static void sendActionBar(Player player, String text) { diff --git a/src/main/java/com/ilummc/tlib/resources/TLocaleInstance.java b/src/main/java/com/ilummc/tlib/resources/TLocaleInstance.java index 6fde383..e70fae0 100644 --- a/src/main/java/com/ilummc/tlib/resources/TLocaleInstance.java +++ b/src/main/java/com/ilummc/tlib/resources/TLocaleInstance.java @@ -37,9 +37,10 @@ class TLocaleInstance { Bukkit.getScheduler().runTask(plugin, () -> sendable.sendTo(sender, args)); } }); - } catch (Exception e) { + } catch (Exception | Error e) { TLib.getTLib().getLogger().error(Strings.replaceWithOrder(TLib.getTLib().getInternalLang().getString("SEND-LOCALE-ERROR"), path)); - TLib.getTLib().getLogger().error(Strings.replaceWithOrder(TLib.getTLib().getInternalLang().getString("LOCALE-ERROR-REASON"), e.getMessage())); + TLib.getTLib().getLogger().error(Strings.replaceWithOrder(TLib.getTLib().getInternalLang().getString("LOCALE-ERROR-REASON"), e.toString())); + e.printStackTrace(); } } diff --git a/src/main/java/com/ilummc/tlib/resources/TLocaleLoader.java b/src/main/java/com/ilummc/tlib/resources/TLocaleLoader.java index 5947c3b..0e58c87 100644 --- a/src/main/java/com/ilummc/tlib/resources/TLocaleLoader.java +++ b/src/main/java/com/ilummc/tlib/resources/TLocaleLoader.java @@ -1,6 +1,8 @@ package com.ilummc.tlib.resources; import com.ilummc.tlib.TLib; +import com.ilummc.tlib.resources.type.TLocaleActionBar; +import com.ilummc.tlib.resources.type.TLocaleJson; import com.ilummc.tlib.resources.type.TLocaleText; import com.ilummc.tlib.resources.type.TLocaleTitle; import com.ilummc.tlib.util.Strings; @@ -39,6 +41,8 @@ public class TLocaleLoader { public static void init() { ConfigurationSerialization.registerClass(TLocaleText.class, "TEXT"); ConfigurationSerialization.registerClass(TLocaleTitle.class, "TITLE"); + ConfigurationSerialization.registerClass(TLocaleJson.class, "JSON"); + ConfigurationSerialization.registerClass(TLocaleActionBar.class, "ACTION"); } public static void load(Plugin plugin, boolean ignoreLoaded) { diff --git a/src/main/java/com/ilummc/tlib/resources/type/TLocaleActionBar.java b/src/main/java/com/ilummc/tlib/resources/type/TLocaleActionBar.java new file mode 100644 index 0000000..270e151 --- /dev/null +++ b/src/main/java/com/ilummc/tlib/resources/type/TLocaleActionBar.java @@ -0,0 +1,61 @@ +package com.ilummc.tlib.resources.type; + +import com.google.common.collect.Maps; +import com.ilummc.tlib.compat.PlaceholderHook; +import com.ilummc.tlib.nms.ActionBar; +import com.ilummc.tlib.resources.TLocaleSendable; +import com.ilummc.tlib.util.Strings; +import me.skymc.taboolib.Main; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; + +import javax.annotation.concurrent.Immutable; +import java.util.Map; + +@Immutable +@SerializableAs("ACTION") +public class TLocaleActionBar implements TLocaleSendable, ConfigurationSerializable { + + private final String text; + + private final boolean papi; + + public TLocaleActionBar(String text, boolean papi) { + this.text = text; + this.papi = papi; + } + + public static TLocaleActionBar valueOf(Map map) { + String text = String.valueOf(map.getOrDefault("text", "Empty Action bar message.")); + boolean papi = (boolean) map.getOrDefault("papi", Main.getInst().getConfig().getBoolean("LOCALE.USE_PAPI", false)); + return new TLocaleActionBar(text, papi); + } + + @Override + public void sendTo(CommandSender sender, String... args) { + if (sender instanceof Player) + ActionBar.sendActionBar(((Player) sender), replace(sender, text, args)); + } + + private String replace(CommandSender sender, String text, String[] args) { + String s = Strings.replaceWithOrder(text, args); + return papi ? PlaceholderHook.replace(sender, s) : s; + } + + @Override + public String asString(String... args) { + return "ActionBar: [" + text + "]"; + } + + @Override + public Map serialize() { + Map map = Maps.newHashMap(); + map.put("text", text); + if (papi) + map.put("papi", true); + return map; + } + +} diff --git a/src/main/java/com/ilummc/tlib/resources/type/TLocaleJson.java b/src/main/java/com/ilummc/tlib/resources/type/TLocaleJson.java new file mode 100644 index 0000000..ae63db4 --- /dev/null +++ b/src/main/java/com/ilummc/tlib/resources/type/TLocaleJson.java @@ -0,0 +1,153 @@ +package com.ilummc.tlib.resources.type; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +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; +import me.skymc.taboolib.Main; +import net.md_5.bungee.api.chat.*; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; + +import javax.annotation.concurrent.ThreadSafe; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@ThreadSafe +@SerializableAs("JSON") +public class TLocaleJson implements TLocaleSendable, ConfigurationSerializable { + + private static final Pattern pattern = Pattern.compile("<([^<>]*)?@([^<>]*)>"); + private final List components; + private final boolean papi; + private final Map map; + + private TLocaleJson(List components, boolean papi, Map map) { + this.components = ImmutableList.copyOf(components); + this.papi = papi; + this.map = map; + } + + public static TLocaleJson valueOf(Map map) { + Object textObj = map.getOrDefault("text", "Empty Node"); + List textList = textObj instanceof String ? Lists.newArrayList(((String) textObj)) : + (textObj instanceof List && !((List) textObj).isEmpty()) ? + ((List) textObj).stream().map(Object::toString).collect(Collectors.toList()) : Lists.newArrayList(String.valueOf(textObj)); + boolean papi = (boolean) map.getOrDefault("papi", Main.getInst().getConfig().getBoolean("LOCALE.USE_PAPI", false)); + Object argsObj = map.get("args"); + if (argsObj instanceof Map) { + Map section = ((Map) argsObj); + List collect = textList.stream().map(s -> { + String[] template = pattern.split(s); + int index = 0; + Matcher matcher = pattern.matcher(s); + List builder; + if (template.length > index) { + builder = new ArrayList<>(Arrays.asList(TextComponent.fromLegacyText(template[index++]))); + } else builder = new ArrayList<>(); + while (matcher.find()) { + String replace = matcher.group(); + if (replace.length() <= 2) continue; + replace = replace.substring(1, replace.length() - 1); + String[] split = replace.split("@"); + String text = split.length > 1 ? split[0] : ""; + String node = split.length > 1 ? split[1] : split[0]; + if (section.containsKey(node)) { + Map arg = (Map) section.get(node); + text = (String) arg.getOrDefault("text", text); + BaseComponent[] component = TextComponent.fromLegacyText(text); + arg.forEach((key, value) -> { + switch (key) { + case "suggest": + for (BaseComponent baseComponent : component) { + baseComponent.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, String.valueOf(value))); + } + break; + case "command": + for (BaseComponent baseComponent : component) { + baseComponent.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.valueOf(value))); + } + break; + case "hover": + for (BaseComponent baseComponent : component) { + baseComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(String.valueOf(value)).create())); + } + break; + } + }); + builder.addAll(Arrays.asList(component)); + } else { + builder.addAll(Arrays.asList(TextComponent.fromLegacyText(text))); + TLib.getTLib().getLogger().warn(Strings.replaceWithOrder(TLib.getTLib().getInternalLang().getString("MISSING-ARGUMENT"), node)); + } + if (index < template.length) { + builder.addAll(Arrays.asList(TextComponent.fromLegacyText(template[index++]))); + } + } + return builder.toArray(new BaseComponent[0]); + }).collect(Collectors.toList()); + return new TLocaleJson(collect, papi, map); + } + return new TLocaleJson(textList.stream().map(TextComponent::fromLegacyText).collect(Collectors.toList()), papi, map); + } + + @Override + public void sendTo(CommandSender sender, String... args) { + if (sender instanceof Player) + components.forEach(comp -> ((Player) sender).spigot().sendMessage(replace(comp, sender, args))); + } + + @Override + public String asString(String... args) { + return components.toString(); + } + + @Override + public Map serialize() { + return Maps.newHashMap(map); + } + + private BaseComponent[] replace(BaseComponent[] component, CommandSender sender, String... args) { + BaseComponent[] components = new BaseComponent[component.length]; + for (int i = 0; i < components.length; i++) { + components[i] = replace(component[i].duplicate(), sender, args); + } + return components; + } + + private List replace(List component, CommandSender sender, String... args) { + return component.stream().map(c -> replace(c, sender, args)).collect(Collectors.toList()); + } + + private BaseComponent replace(BaseComponent component, CommandSender sender, String... args) { + if (component.getClickEvent() != null) { + ClickEvent clickEvent = new ClickEvent(component.getClickEvent().getAction(), replace(sender, component.getClickEvent().getValue(), args)); + component.setClickEvent(clickEvent); + } + if (component.getHoverEvent() != null) { + HoverEvent hoverEvent = new HoverEvent(component.getHoverEvent().getAction(), replace(component.getHoverEvent().getValue(), sender, args)); + component.setHoverEvent(hoverEvent); + } + if (component.getExtra() != null) + component.setExtra(replace(component.getExtra(), sender, args)); + if (component instanceof TextComponent) { + ((TextComponent) component).setText(replace(sender, ((TextComponent) component).getText(), args)); + } + return component; + } + + private String replace(CommandSender sender, String text, String[] args) { + String s = Strings.replaceWithOrder(text, args); + return papi ? PlaceholderHook.replace(sender, s) : s; + } +} diff --git a/src/main/java/com/ilummc/tlib/resources/type/TLocaleTitle.java b/src/main/java/com/ilummc/tlib/resources/type/TLocaleTitle.java index 7628140..bf5a4ef 100644 --- a/src/main/java/com/ilummc/tlib/resources/type/TLocaleTitle.java +++ b/src/main/java/com/ilummc/tlib/resources/type/TLocaleTitle.java @@ -1,11 +1,11 @@ package com.ilummc.tlib.resources.type; import com.google.common.collect.Maps; -import com.ilummc.tlib.TLib; import com.ilummc.tlib.compat.PlaceholderHook; import com.ilummc.tlib.resources.TLocale; import com.ilummc.tlib.resources.TLocaleSendable; import com.ilummc.tlib.util.Strings; +import me.skymc.taboolib.Main; import me.skymc.taboolib.display.TitleUtils; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; @@ -52,7 +52,7 @@ public class TLocaleTitle implements TLocaleSendable, ConfigurationSerializable (int) map.getOrDefault("fadein", 10), (int) map.getOrDefault("fadeout", 10), (int) map.getOrDefault("stay", 20), - (boolean) map.getOrDefault("papi", TLib.getTLib().getConfig().isEnablePlaceholderHookByDefault())); + (boolean) map.getOrDefault("papi", Main.getInst().getConfig().getBoolean("LOCALE.USE_PAPI", false))); } catch (Exception e) { title = new TLocaleTitle("§4Load failed!", "§c" + e.getMessage(), 10, 20, 10, false); } diff --git a/src/main/java/com/ilummc/tlib/util/asm/AsmClassTransformer.java b/src/main/java/com/ilummc/tlib/util/asm/AsmClassTransformer.java index b4da8a9..1c5f3a0 100644 --- a/src/main/java/com/ilummc/tlib/util/asm/AsmClassTransformer.java +++ b/src/main/java/com/ilummc/tlib/util/asm/AsmClassTransformer.java @@ -28,10 +28,6 @@ public class AsmClassTransformer extends ClassVisitor implements Opcodes { this.toVer = toVer; } - public static Builder builder() { - return new Builder().toVersion(Bukkit.getServer().getClass().getName().split("\\.")[3]); - } - public Object transform() { try { ClassReader classReader = new ClassReader(from.getResourceAsStream("/" + from.getName().replace('.', '/') + ".class")); @@ -51,10 +47,8 @@ public class AsmClassTransformer extends ClassVisitor implements Opcodes { } } - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, newClassName.replace('.', '/'), replace(signature), - prevName, replace(interfaces)); + public static Builder builder() { + return new Builder().toVersion(Bukkit.getServer().getClass().getName().split("\\.")[3]); } @Override @@ -90,31 +84,10 @@ public class AsmClassTransformer extends ClassVisitor implements Opcodes { } else return null; } - public static class Builder { - - private Class from; - - private String fromVersion, toVersion; - - public Builder from(Class clazz) { - this.from = clazz; - return this; - } - - public Builder fromVersion(String ver) { - fromVersion = ver; - return this; - } - - public Builder toVersion(String ver) { - toVersion = ver; - return this; - } - - public AsmClassTransformer build() { - return new AsmClassTransformer(from, fromVersion, toVersion, new ClassWriter(ClassWriter.COMPUTE_MAXS)); - } - + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + super.visit(version, access, newClassName.replace('.', '/'), replace(signature), + replace(superName), replace(interfaces)); } private class AsmMethodTransformer extends MethodVisitor { @@ -150,4 +123,31 @@ public class AsmClassTransformer extends ClassVisitor implements Opcodes { super.visitLocalVariable(name, replace(descriptor), replace(signature), start, end, index); } } + + public static class Builder { + + private Class from; + + private String fromVersion, toVersion; + + public Builder from(Class clazz) { + this.from = clazz; + return this; + } + + public Builder fromVersion(String ver) { + fromVersion = ver; + return this; + } + + public Builder toVersion(String ver) { + toVersion = ver; + return this; + } + + public AsmClassTransformer build() { + return new AsmClassTransformer(from, fromVersion, toVersion, new ClassWriter(ClassWriter.COMPUTE_MAXS)); + } + + } } diff --git a/src/main/java/me/skymc/taboolib/javashell/JavaShell.java b/src/main/java/me/skymc/taboolib/javashell/JavaShell.java index fc6d40d..67adb68 100644 --- a/src/main/java/me/skymc/taboolib/javashell/JavaShell.java +++ b/src/main/java/me/skymc/taboolib/javashell/JavaShell.java @@ -1,11 +1,10 @@ package me.skymc.taboolib.javashell; -import java.io.File; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.HashMap; - +import com.ilummc.tlib.dependency.TDependencyLoader; +import lombok.Getter; +import lombok.Setter; +import me.skymc.taboolib.Main; +import me.skymc.taboolib.message.MsgUtils; import org.apache.commons.lang.ArrayUtils; import org.bukkit.Bukkit; import org.bukkit.event.HandlerList; @@ -13,195 +12,190 @@ import org.bukkit.event.Listener; import org.bukkit.plugin.RegisteredListener; import org.bukkit.scheduler.BukkitRunnable; -import lombok.Getter; -import lombok.Setter; -import me.skymc.taboolib.Main; -import me.skymc.taboolib.javashell.utils.JarUtils; -import me.skymc.taboolib.message.MsgUtils; +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashMap; public class JavaShell { - - @Getter - @Setter - private static String paths = ""; - - @Getter - @Setter - private static File javaShellFolder; - - @Getter - @Setter - private static File scriptFolder; - - @Getter - @Setter - private static File cacheFolder; - - @Getter - @Setter - private static File libFolder; - - @Getter - @Setter - private static HashMap> shells = new HashMap<>(); - - public static void javaShellSetup() { - File dataFolder = Main.getInst().getDataFolder(); - File pluginsFolder = dataFolder.getParentFile(); - File serverRoot = Bukkit.getWorldContainer(); - File[] rootJars = serverRoot.listFiles((dir, name) -> name.toLowerCase().endsWith("jar")); + @Getter + @Setter + private static String paths = ""; - File[] pluginJars = pluginsFolder.listFiles((dir, name) -> name.toLowerCase().endsWith("jar")); + @Getter + @Setter + private static File javaShellFolder; - for (File file : (File[]) ArrayUtils.addAll(rootJars, pluginJars)) { - String path = file.getAbsolutePath(); - paths += File.pathSeparator + path; - } - - javaShellFolder = new File(Main.getInst().getDataFolder(), "JavaShells"); - if (!javaShellFolder.exists()) { - Main.getInst().saveResource("JavaShells/scripts/-testshell.java", true); - } - - scriptFolder = new File(javaShellFolder, "scripts"); - if (!scriptFolder.exists()) { - scriptFolder.mkdir(); - } - - cacheFolder = new File(javaShellFolder, "cache"); - if (!cacheFolder.exists()) { - cacheFolder.mkdir(); - } - - libFolder = new File(javaShellFolder, "lib"); - if (!libFolder.exists()) { - libFolder.mkdir(); - } - - File tools = new File(Main.getInst().getDataFolder(), "JavaShells/lib/com.sun.tools.jar"); - if (!tools.exists()) { - MsgUtils.warn("&4JavaShell &c工具的必要依赖 &4com.sun.tools.jar &c不存在, 功能关闭!"); - return; - } - - loadLibrary(); - new BukkitRunnable() { - - @Override - public void run() { - long time = System.currentTimeMillis(); - for (File file : scriptFolder.listFiles()) { - if (!file.getName().startsWith("-")) { - reloadShell(file.getName()); - } - } - MsgUtils.send("载入 " + shells.size() + " 个脚本, 耗时 &f" + (System.currentTimeMillis() - time) + "ms"); - } - }.runTask(Main.getInst()); - } - - public static void javaShellCancel() { - for (File cacheFile : cacheFolder.listFiles()) { - cacheFile.delete(); - } - for (String name : shells.keySet()) { - invokeMethod(name, "onDisable"); - } - } - - public static void invokeMethod(String name, String method) { - if (shells.containsKey(name)) { - Class clazz = shells.get(name); - try { - Method disableMethod = clazz.getMethod(method); - if (disableMethod != null) { - disableMethod.invoke(clazz.newInstance()); - } - } - catch (Exception e) { - // - } - } - } - - public static void unloadShell(String shell) { - invokeMethod(shell, "onDisable"); - Class clazz = shells.remove(shell); - try { - if (clazz.newInstance() instanceof Listener) { - for (RegisteredListener listener : HandlerList.getRegisteredListeners(Main.getInst())) { - if (listener.getListener().getClass().getName().equals(clazz.getName())) { - HandlerList.unregisterAll(listener.getListener()); - } - } - MsgUtils.send("已为脚本 &f" + shell + " &7注销监听器"); - } - } - catch (Exception e) { - // - } - } - - public static boolean reloadShell(String shell) { - unloadShell(shell = shell.replace(".java", "")); - - try { - Class.forName("com.sun.tools.javac.main.Main"); - } - catch (Exception e) { - MsgUtils.warn("&4JavaShell &c工具的必要依赖 &4com.sun.tools.jar &c丢失, 无法载入!"); - return false; - } - - File javaFile = new File(scriptFolder, shell + ".java"); - if (!javaFile.exists()) { - MsgUtils.send("&c脚本 &4" + shell + "&c 不存在"); - return false; - } - - String[] args = { - "-nowarn", - "-classpath", "." + File.pathSeparator + JavaShell.getPaths(), - "-d", cacheFolder.getAbsolutePath() + File.separator, - javaFile.getAbsolutePath() - }; - - int code = new com.sun.tools.javac.main.Main("javac").compile(args).exitCode; - if (code == 0) { - MsgUtils.send("&f" + shell + "&7 载入成功"); - try { - URL[] urls = { cacheFolder.toURI().toURL() }; - URLClassLoader sysloader = new URLClassLoader(urls, Main.class.getClassLoader()); - Class clazz = sysloader.loadClass(shell); - shells.put(shell, clazz); - sysloader.close(); - - invokeMethod(shell, "onEnable"); - if (clazz.newInstance() instanceof Listener) { - Bukkit.getPluginManager().registerEvents((Listener) clazz.newInstance(), Main.getInst()); - MsgUtils.send("已为脚本 &f" + shell + " &7注册监听器"); - } - } - catch (Exception e) { - // - } - return true; - } - else { - MsgUtils.send("&4" + shell + "&c 载入失败"); - return false; - } - } - - private static void loadLibrary() { - for (File jar : libFolder.listFiles()) { - try { - JarUtils.addClassPath(JarUtils.getJarUrl(jar)); - MsgUtils.send("成功载入 &f" + jar.getName() + " &7到运行库"); - } catch (Exception e) { - // - } - } - } + @Getter + @Setter + private static File scriptFolder; + + @Getter + @Setter + private static File cacheFolder; + + @Getter + @Setter + private static File libFolder; + + @Getter + @Setter + private static HashMap> shells = new HashMap<>(); + + public static void javaShellSetup() { + File dataFolder = Main.getInst().getDataFolder(); + File pluginsFolder = dataFolder.getParentFile(); + File serverRoot = Bukkit.getWorldContainer(); + + File[] rootJars = serverRoot.listFiles((dir, name) -> name.toLowerCase().endsWith("jar")); + + File[] pluginJars = pluginsFolder.listFiles((dir, name) -> name.toLowerCase().endsWith("jar")); + + for (File file : (File[]) ArrayUtils.addAll(rootJars, pluginJars)) { + String path = file.getAbsolutePath(); + paths += File.pathSeparator + path; + } + + javaShellFolder = new File(Main.getInst().getDataFolder(), "JavaShells"); + if (!javaShellFolder.exists()) { + Main.getInst().saveResource("JavaShells/scripts/-testshell.java", true); + } + + scriptFolder = new File(javaShellFolder, "scripts"); + if (!scriptFolder.exists()) { + scriptFolder.mkdir(); + } + + cacheFolder = new File(javaShellFolder, "cache"); + if (!cacheFolder.exists()) { + cacheFolder.mkdir(); + } + + libFolder = new File(javaShellFolder, "lib"); + if (!libFolder.exists()) { + libFolder.mkdir(); + } + + File tools = new File(Main.getInst().getDataFolder(), "JavaShells/lib/com.sun.tools.jar"); + if (!tools.exists()) { + MsgUtils.warn("&4JavaShell &c工具的必要依赖 &4com.sun.tools.jar &c不存在, 功能关闭!"); + return; + } + + loadLibrary(); + new BukkitRunnable() { + + @Override + public void run() { + long time = System.currentTimeMillis(); + for (File file : scriptFolder.listFiles()) { + if (!file.getName().startsWith("-")) { + reloadShell(file.getName()); + } + } + MsgUtils.send("载入 " + shells.size() + " 个脚本, 耗时 &f" + (System.currentTimeMillis() - time) + "ms"); + } + }.runTask(Main.getInst()); + } + + public static void javaShellCancel() { + for (File cacheFile : cacheFolder.listFiles()) { + cacheFile.delete(); + } + for (String name : shells.keySet()) { + invokeMethod(name, "onDisable"); + } + } + + public static void invokeMethod(String name, String method) { + if (shells.containsKey(name)) { + Class clazz = shells.get(name); + try { + Method disableMethod = clazz.getMethod(method); + if (disableMethod != null) { + disableMethod.invoke(clazz.newInstance()); + } + } catch (Exception e) { + // + } + } + } + + public static void unloadShell(String shell) { + invokeMethod(shell, "onDisable"); + Class clazz = shells.remove(shell); + try { + if (clazz.newInstance() instanceof Listener) { + for (RegisteredListener listener : HandlerList.getRegisteredListeners(Main.getInst())) { + if (listener.getListener().getClass().getName().equals(clazz.getName())) { + HandlerList.unregisterAll(listener.getListener()); + } + } + MsgUtils.send("已为脚本 &f" + shell + " &7注销监听器"); + } + } catch (Exception e) { + // + } + } + + public static boolean reloadShell(String shell) { + unloadShell(shell = shell.replace(".java", "")); + + try { + Class.forName("com.sun.tools.javac.main.Main"); + } catch (Exception e) { + MsgUtils.warn("&4JavaShell &c工具的必要依赖 &4com.sun.tools.jar &c丢失, 无法载入!"); + return false; + } + + File javaFile = new File(scriptFolder, shell + ".java"); + if (!javaFile.exists()) { + MsgUtils.send("&c脚本 &4" + shell + "&c 不存在"); + return false; + } + + String[] args = { + "-nowarn", + "-classpath", "." + File.pathSeparator + JavaShell.getPaths(), + "-d", cacheFolder.getAbsolutePath() + File.separator, + javaFile.getAbsolutePath() + }; + + int code = new com.sun.tools.javac.main.Main("javac").compile(args).exitCode; + if (code == 0) { + MsgUtils.send("&f" + shell + "&7 载入成功"); + try { + URL[] urls = {cacheFolder.toURI().toURL()}; + URLClassLoader sysloader = new URLClassLoader(urls, Main.class.getClassLoader()); + Class clazz = sysloader.loadClass(shell); + shells.put(shell, clazz); + sysloader.close(); + + invokeMethod(shell, "onEnable"); + if (clazz.newInstance() instanceof Listener) { + Bukkit.getPluginManager().registerEvents((Listener) clazz.newInstance(), Main.getInst()); + MsgUtils.send("已为脚本 &f" + shell + " &7注册监听器"); + } + } catch (Exception e) { + // + } + return true; + } else { + MsgUtils.send("&4" + shell + "&c 载入失败"); + return false; + } + } + + private static void loadLibrary() { + for (File jar : libFolder.listFiles()) { + try { + TDependencyLoader.addToPath(Main.getInst(), jar); + MsgUtils.send("成功载入 &f" + jar.getName() + " &7到运行库"); + } catch (Exception e) { + // + } + } + } } diff --git a/src/main/java/me/skymc/taboolib/javashell/utils/JarUtils.java b/src/main/java/me/skymc/taboolib/javashell/utils/JarUtils.java index df6d0da..804bd71 100644 --- a/src/main/java/me/skymc/taboolib/javashell/utils/JarUtils.java +++ b/src/main/java/me/skymc/taboolib/javashell/utils/JarUtils.java @@ -1,12 +1,9 @@ package me.skymc.taboolib.javashell.utils; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import me.skymc.taboolib.message.MsgUtils; +import org.bukkit.Bukkit; + +import java.io.*; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; @@ -15,10 +12,6 @@ import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import org.bukkit.Bukkit; - -import me.skymc.taboolib.message.MsgUtils; - public class JarUtils { public static boolean extractFromJar(final String fileName, final String dest) throws IOException { @@ -65,6 +58,7 @@ public class JarUtils { } } + @Deprecated public static URL getJarUrl(final File file) throws IOException { return new URL("jar:" + file.toURI().toURL().toExternalForm() + "!/"); } @@ -88,13 +82,14 @@ public class JarUtils { } } - public static void addClassPath(final URL url) { + @Deprecated + public static void addClassPath(final URL url) { final URLClassLoader sysloader = (URLClassLoader) Bukkit.class.getClassLoader(); final Class sysclass = URLClassLoader.class; try { - final Method method = sysclass.getDeclaredMethod("addURL", URL.class); + final Method method = sysclass.getDeclaredMethod("addURL", URL.class); method.setAccessible(true); - method.invoke(sysloader, url); + method.invoke(sysloader, url); } catch (Throwable t) { MsgUtils.warn("无法添加添加 &4" + url + "&c 到运行库"); MsgUtils.warn(t.getMessage()); diff --git a/src/main/resources/internalLang.yml b/src/main/resources/internalLang.yml index 6060850..b419155 100644 --- a/src/main/resources/internalLang.yml +++ b/src/main/resources/internalLang.yml @@ -5,4 +5,5 @@ ERROR-LOADING-LANG: '加载 {0} 插件的语言文件时发生异常:{1}' RELOADING-LANG: '正在重新载入 {0} 插件的语言文件' FETCH-LOCALE-ERROR: '语言文件获取失败:{0}' SEND-LOCALE-ERROR: '语言文件发送失败:{0}' -LOCALE-ERROR-REASON: '原因:{0}' \ No newline at end of file +LOCALE-ERROR-REASON: '原因:{0}' +MISSING-ARGUMENT: '语言文本含有没有找到的参数 {0}' \ No newline at end of file