├── .idea
├── .gitignore
├── JavaScriptLibraryPlugin.iml
├── codeStyles
│ └── codeStyleConfig.xml
├── vcs.xml
├── encodings.xml
├── runConfigurations
│ └── server.xml
├── compiler.xml
└── misc.xml
├── src
└── main
│ ├── resources
│ ├── config.yml
│ ├── lib
│ │ ├── info.json
│ │ ├── load.js
│ │ ├── util.js
│ │ └── event.js
│ └── plugin.yml
│ └── java
│ └── xingchen
│ └── jslib
│ ├── event
│ ├── EventHolder.java
│ ├── EventLoader.java
│ └── register
│ │ ├── JavaScriptFilesEvalledEvent.java
│ │ ├── AbstractJavaScriptPluginEvent.java
│ │ └── JavaScriptPreRegisterEvent.java
│ ├── js
│ ├── IScriptHolder.java
│ ├── ScriptHolderBase.java
│ ├── event
│ │ ├── JavaScriptCancellableEvent.java
│ │ └── JavaScriptEvent.java
│ ├── ScriptFiles.java
│ ├── JavaScriptUtil.java
│ ├── JavaScriptLoader.java
│ └── JavaScriptInfo.java
│ ├── export
│ ├── KeyValue.java
│ ├── LinkageLoader.java
│ └── PluginScripts.java
│ ├── command
│ ├── CommandLoader.java
│ ├── EnumJsSubCommand.java
│ └── JsCommand.java
│ ├── JSApi.java
│ ├── JavaScriptLibrary.java
│ └── config
│ └── ConfigManager.java
├── README.md
├── JavaScriptLibraryPlugin.iml
├── MinecraftPlugin.iml
└── pom.xml
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /workspace.xml
--------------------------------------------------------------------------------
/src/main/resources/config.yml:
--------------------------------------------------------------------------------
1 | linkage: false
2 | command:
3 | run: true
4 | book: true
--------------------------------------------------------------------------------
/.idea/JavaScriptLibraryPlugin.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/main/resources/lib/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "libraries",
3 | "order": [
4 | "util",
5 | "load",
6 | "event"
7 | ]
8 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JavaScriptLibraryPlugin
2 | A Bukkit Plugin to provide a environment for users to use JavaScript code
3 |
4 | Open Source License is LGPL3 License.Please follow it.
5 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/event/EventHolder.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.event;
2 |
3 | import org.bukkit.event.Listener;
4 |
5 | /**
6 | * 无方法
7 | * 仅为JavaScript提供监听器标记
8 | */
9 | public class EventHolder implements Listener {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/js/IScriptHolder.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.js;
2 |
3 | /**
4 | * 本地脚本接口
5 | * 可标记本地脚本的文件/文件夹
6 | */
7 | public interface IScriptHolder {
8 | /**脚本文件/文件夹(可有多个)*/
9 | public ScriptFiles[] getScriptFiles();
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: JavaScriptLibrary
2 | main: xingchen.jslib.JavaScriptLibrary
3 | version: 1.0.2
4 | permissions:
5 | jslib.command.help:
6 | default: op
7 | jslib.command.run:
8 | default: op
9 | jslib.command.book:
10 | default: op
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/JavaScriptLibraryPlugin.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | SPIGOT
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/MinecraftPlugin.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | SPIGOT
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/js/ScriptHolderBase.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.js;
2 |
3 | public class ScriptHolderBase implements IScriptHolder {
4 | protected ScriptFiles[] scriptFiles;
5 |
6 | public ScriptHolderBase(ScriptFiles[] scriptFiles) {
7 | this.scriptFiles = scriptFiles;
8 | }
9 |
10 | @Override
11 | public ScriptFiles[] getScriptFiles() {
12 | return this.scriptFiles;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/export/KeyValue.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.export;
2 |
3 | /**键值对*/
4 | public class KeyValue {
5 | protected K key;
6 | protected V value;
7 |
8 | public KeyValue(K key, V value) {
9 | this.key = key;
10 | this.value = value;
11 | }
12 |
13 | public K getKey() {
14 | return this.key;
15 | }
16 |
17 | public void setKey(K key) {
18 | this.key = key;
19 | }
20 |
21 | public V getValue() {
22 | return this.value;
23 | }
24 |
25 | public void setValue(V value) {
26 | this.value = value;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/event/EventLoader.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.event;
2 |
3 | import org.bukkit.event.Listener;
4 | import org.bukkit.plugin.Plugin;
5 |
6 | /**
7 | * 事件监听器(暂时无用)
8 | */
9 | public class EventLoader implements Listener {
10 | private Plugin plugin;
11 |
12 | public EventLoader(Plugin plugin) {
13 | this.plugin = plugin;
14 | }
15 |
16 | public static void init(Plugin plugin) {
17 | plugin.getServer().getPluginManager().registerEvents(new EventLoader(plugin), plugin);
18 | }
19 |
20 | public Plugin getPlugin() {
21 | return this.plugin;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/server.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/event/register/JavaScriptFilesEvalledEvent.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.event.register;
2 |
3 | import org.bukkit.event.HandlerList;
4 |
5 | import xingchen.jslib.export.LinkageLoader;
6 |
7 | public class JavaScriptFilesEvalledEvent extends AbstractJavaScriptPluginEvent {
8 | private static HandlerList handlerList = new HandlerList();
9 |
10 | public JavaScriptFilesEvalledEvent(LinkageLoader linkageLoader, String scriptName) {
11 | super(linkageLoader, scriptName);
12 | }
13 |
14 | @Override
15 | public HandlerList getHandlers() {
16 | return handlerList;
17 | }
18 |
19 | public static HandlerList getHandlerList() {
20 | return handlerList;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/event/register/AbstractJavaScriptPluginEvent.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.event.register;
2 |
3 | import org.bukkit.event.Event;
4 | import xingchen.jslib.export.LinkageLoader;
5 |
6 | public abstract class AbstractJavaScriptPluginEvent extends Event {
7 | protected LinkageLoader linkageLoader;
8 | protected String scriptName;
9 |
10 | public AbstractJavaScriptPluginEvent(LinkageLoader linkageLoader, String scriptName) {
11 | this.linkageLoader = linkageLoader;
12 | this.scriptName = scriptName;
13 | }
14 |
15 | public LinkageLoader getLinkageLoader() {
16 | return this.linkageLoader;
17 | }
18 |
19 | public void setLinkageLoader(LinkageLoader linkageLoader) {
20 | this.linkageLoader = linkageLoader;
21 | }
22 |
23 | public String getScriptName() {
24 | return this.scriptName;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/main/resources/lib/load.js:
--------------------------------------------------------------------------------
1 | var load = null;
2 | (function() {
3 | var File = java.io.File;
4 |
5 | global.load = function (dir, name) {
6 | if(dir instanceof java.io.File && name == undefined) {
7 | return eval(dir);
8 | }
9 |
10 | if(dir == undefined || name == undefined) {
11 | name = dir || name;
12 | dir = JsLibPlugin.JavaScriptLibrary.instance.getDataFolder().getParent();
13 | }
14 |
15 | if(typeof(dir) == "string") {
16 | dir = new File(dir);
17 | }
18 | if(typeof(name) != "string") {
19 | name = name.toString();
20 | }
21 |
22 | var path = new File(dir, name);
23 | if(path.exists()) {
24 | if(path.isDirectory()) {
25 | var files = path.listFiles();
26 | var result = [];
27 | for(var i in files) {
28 | result.push(global.load(files[i]));
29 | }
30 | return result;
31 | } else {
32 | return eval(path);
33 | }
34 | }
35 |
36 | return null;
37 | }
38 | })();
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/command/CommandLoader.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.command;
2 |
3 | import java.lang.reflect.InvocationTargetException;
4 |
5 | import org.bukkit.Bukkit;
6 | import org.bukkit.Server;
7 | import org.bukkit.command.CommandMap;
8 |
9 | import xingchen.jslib.JavaScriptLibrary;
10 |
11 | public class CommandLoader {
12 | public static CommandMap commandMap;
13 |
14 | public static JsCommand jsCommand;
15 |
16 | public static void init(JavaScriptLibrary plugin) {
17 | Server server = Bukkit.getServer();
18 | try {
19 | commandMap = (CommandMap) server.getClass().getMethod("getCommandMap").invoke(server);
20 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
21 | e.printStackTrace();
22 | }
23 |
24 | if(commandMap == null) {
25 | return;
26 | }
27 |
28 | jsCommand = new JsCommand();
29 | commandMap.register(plugin.getPluginName(), jsCommand);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/event/register/JavaScriptPreRegisterEvent.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.event.register;
2 |
3 | import org.bukkit.event.Cancellable;
4 | import org.bukkit.event.HandlerList;
5 |
6 | import xingchen.jslib.export.LinkageLoader;
7 |
8 | public class JavaScriptPreRegisterEvent extends AbstractJavaScriptPluginEvent implements Cancellable {
9 | private static HandlerList handlerList = new HandlerList();
10 |
11 | protected boolean isCancelled;
12 |
13 | public JavaScriptPreRegisterEvent(LinkageLoader linkageLoader, String scriptName) {
14 | super(linkageLoader, scriptName);
15 | }
16 |
17 | @Override
18 | public boolean isCancelled() {
19 | return this.isCancelled;
20 | }
21 |
22 | @Override
23 | public void setCancelled(boolean cancel) {
24 | this.isCancelled = cancel;
25 | }
26 |
27 | @Override
28 | public HandlerList getHandlers() {
29 | return handlerList;
30 | }
31 |
32 | public static HandlerList getHandlerList() {
33 | return handlerList;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/js/event/JavaScriptCancellableEvent.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.js.event;
2 |
3 | import org.bukkit.event.Cancellable;
4 | import org.bukkit.event.HandlerList;
5 |
6 | /**
7 | * 实现了{#Cancellable}的事件
8 | * 见:{#JavaScriptEvent}
9 | */
10 | public class JavaScriptCancellableEvent extends JavaScriptEvent implements Cancellable {
11 | private static HandlerList handlerList = new HandlerList();
12 |
13 | private boolean isCancelled;
14 |
15 | public JavaScriptCancellableEvent(String name, Object object) {
16 | super(name, object);
17 | this.isCancelled = false;
18 | }
19 |
20 | @Override
21 | public HandlerList getHandlers() {
22 | return handlerList;
23 | }
24 |
25 | @Override
26 | public boolean isCancelled() {
27 | return this.isCancelled;
28 | }
29 |
30 | @Override
31 | public void setCancelled(boolean isCancelled) {
32 | this.isCancelled = isCancelled;
33 | }
34 |
35 | public static HandlerList getHandlerList() {
36 | return handlerList;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/command/EnumJsSubCommand.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.command;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**js命令的子命令*/
7 | public enum EnumJsSubCommand {
8 | HELP("help", "jslib.command.help"),
9 | RUN("run", "jslib.command.run"),
10 | BOOK("book", "jslib.command.book");
11 |
12 | public static Map lookup;
13 |
14 | private String name;
15 | private String permission;
16 |
17 | private EnumJsSubCommand(String name, String permission) {
18 | this.name = name;
19 | this.permission = permission;
20 | }
21 |
22 | public boolean isSubCommand(String arg) {
23 | return this.name.equalsIgnoreCase(arg);
24 | }
25 |
26 | public String getName() {
27 | return this.name;
28 | }
29 |
30 | public String getPermission() {
31 | return this.permission;
32 | }
33 |
34 | static {
35 | lookup = new HashMap<>();
36 | for(EnumJsSubCommand subCommand : values()) {
37 | lookup.put(subCommand.getName(), subCommand);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/js/event/JavaScriptEvent.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.js.event;
2 |
3 | import org.bukkit.event.Event;
4 | import org.bukkit.event.HandlerList;
5 |
6 | /**
7 | * 由于在JavaScript中继承时不能为类添加超类以外的方法,所以创建类这个类以在JavaScript中实现自定义事件
8 | */
9 | public class JavaScriptEvent extends Event {
10 | private static HandlerList handlerList = new HandlerList();
11 |
12 | /**事件唯一标识符(最好不要重复)*/
13 | protected String name;
14 | /**数据对象(一般是JavaScript对象)*/
15 | protected Object object;
16 |
17 | public JavaScriptEvent(String name, Object object) {
18 | this.name = name;
19 | this.object = object;
20 | }
21 |
22 | @Override
23 | public HandlerList getHandlers() {
24 | return handlerList;
25 | }
26 |
27 | public String getName() {
28 | return this.name;
29 | }
30 |
31 | public Object getObject() {
32 | return this.object;
33 | }
34 |
35 | public void setObject(Object object) {
36 | this.object = object;
37 | }
38 |
39 | public static HandlerList getHandlerList() {
40 | return handlerList;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/js/ScriptFiles.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.js;
2 |
3 | import java.io.File;
4 |
5 | import javax.annotation.Nullable;
6 |
7 | import xingchen.jslib.config.ConfigManager;
8 |
9 | /**
10 | * 脚本文件信息
11 | * 包含了信息文件和代码文件
12 | */
13 | public class ScriptFiles {
14 | /**信息文件*/
15 | @Nullable
16 | protected File info;
17 | protected File jsFile;
18 |
19 | public ScriptFiles(File jsFile) {
20 | this(null, jsFile);
21 | }
22 |
23 | public ScriptFiles(File info, File jsFile) {
24 | this.info = info;
25 | this.jsFile = jsFile;
26 | }
27 |
28 | public File getInfo() {
29 | return this.info;
30 | }
31 |
32 | public File getJsFile() {
33 | return this.jsFile;
34 | }
35 |
36 | /**
37 | * 寻找文件夹中的信息文件,并标记
38 | *
39 | * @param directory 目标文件夹
40 | * @return 可能包含信息文件的{#ScriptFiles}
41 | */
42 | public static ScriptFiles fromDirectory(File directory) {
43 | if(directory.exists() && directory.isDirectory()) {
44 | File info = new File(directory, ConfigManager.INFOFILENAME);
45 | if(!info.exists() || info.isDirectory()) {
46 | info = null;
47 | }
48 | return new ScriptFiles(info, directory);
49 | }
50 |
51 | return null;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/JSApi.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib;
2 |
3 | import java.io.File;
4 |
5 | import org.bukkit.plugin.Plugin;
6 |
7 | import xingchen.jslib.export.LinkageLoader;
8 | import xingchen.jslib.js.ScriptFiles;
9 | import xingchen.jslib.js.ScriptHolderBase;
10 |
11 | public class JSApi {
12 | private static JSApi instance;
13 |
14 | /**
15 | * 快速注册js
16 | *
17 | * @param plugin 注册js的插件
18 | * @param pluginJsName 插件提供的js的名字(为null则不进行插件js注册)
19 | * @param pluginJsFile 插件提供的js所在的文件夹
20 | * @param userJsName 使用者的js的名字(为null则不进行使用者js注册)
21 | * @param userJsFile 使用者的js所在的文件夹
22 | */
23 | public void registerJavaScript(Plugin plugin, String pluginJsName, File pluginJsFile, String userJsName, File userJsFile) {
24 | if(pluginJsName != null) {
25 | LinkageLoader.instance.registerLinkage(pluginJsName, plugin, new ScriptHolderBase(new ScriptFiles[] {ScriptFiles.fromDirectory(pluginJsFile)}));
26 | }
27 |
28 | if(userJsName != null) {
29 | LinkageLoader.instance.registerLinkage(userJsName, plugin, new ScriptHolderBase(new ScriptFiles[] {ScriptFiles.fromDirectory(userJsFile)}));
30 | }
31 | }
32 |
33 | public static JSApi getApi() {
34 | return instance;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/JavaScriptLibrary.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib;
2 |
3 | import org.bukkit.plugin.ServicePriority;
4 | import org.bukkit.plugin.java.JavaPlugin;
5 |
6 | import xingchen.jslib.command.CommandLoader;
7 | import xingchen.jslib.config.ConfigManager;
8 | import xingchen.jslib.export.LinkageLoader;
9 | import xingchen.jslib.js.JavaScriptLoader;
10 |
11 | public class JavaScriptLibrary extends JavaPlugin {
12 | public static JavaScriptLibrary instance;
13 |
14 | /**插件名*/
15 | private String pluginName;
16 | /**配置管理器对象*/
17 | private ConfigManager config;
18 |
19 | @Override
20 | public void onEnable() {
21 | instance = this;
22 | this.pluginName = "javaScriptLibrary";
23 |
24 | this.config = new ConfigManager(this);
25 | //EventLoader.init(this);
26 | CommandLoader.init(this);
27 |
28 | JavaScriptLoader.instance = new JavaScriptLoader(this.getClassLoader());
29 | LinkageLoader.instance = new LinkageLoader(this);
30 | JavaScriptLoader.init();
31 | if(this.config.isLinkage()) {
32 | this.getServer().getServicesManager().register(LinkageLoader.class, LinkageLoader.instance, this, ServicePriority.Normal);
33 | }
34 | }
35 |
36 | @Override
37 | public void onDisable() {
38 | this.getServer().getServicesManager().unregisterAll(this);
39 | }
40 |
41 | public String getPluginName() {
42 | return this.pluginName;
43 | }
44 |
45 | public ConfigManager getConfigManager() {
46 | return this.config;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/js/JavaScriptUtil.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.js;
2 |
3 | import org.bukkit.event.Event;
4 | import org.bukkit.event.EventPriority;
5 | import org.bukkit.event.HandlerList;
6 | import org.bukkit.event.Listener;
7 | import org.bukkit.plugin.EventExecutor;
8 | import org.bukkit.plugin.Plugin;
9 | import org.bukkit.plugin.RegisteredListener;
10 |
11 | import jdk.nashorn.api.scripting.ScriptObjectMirror;
12 |
13 | /**
14 | * JavaScript工具库
15 | * 为JavaScript的使用添加了一些便捷的方法
16 | */
17 | public class JavaScriptUtil {
18 | /**
19 | * 注册事件
20 | *
21 | * @param eventClass handlerList 可通过事件类的getHandlerList()方法获取
22 | * @param callback 当事件触发时回调的JavaScript函数
23 | * @param priority 事件优先级(低优先级的代码先执行)
24 | * @param ignoreCancelled 代码是否被已经取消的事件触发(如果事件被低优先级的取消,那高优先级的代码将不会执行)
25 | * @param key 事件监听器(每种事件只能被每个监听器注册一次)
26 | * @param plugin 注册事件的插件
27 | * @return {#EventExecutor}
28 | */
29 | public static EventExecutor registerEvent(HandlerList handlerList, ScriptObjectMirror callback, EventPriority priority, boolean ignoreCancelled, Listener key, Plugin plugin) {
30 | EventExecutor eventExecutor = new EventExecutor() {
31 | public void execute(Listener listener, Event event) {
32 | callback.call(callback, event);
33 | }
34 | };
35 | handlerList.register(new RegisteredListener(key, eventExecutor, priority, plugin, ignoreCancelled));
36 | return eventExecutor;
37 | }
38 |
39 | /**
40 | * 注销事件
41 | *
42 | * @param handlerList 可通过事件类的getHandlerList()方法获取
43 | * @param key 事件监听器
44 | */
45 | public static void removeEvent(HandlerList handlerList, Listener key) {
46 | handlerList.unregister(key);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/resources/lib/util.js:
--------------------------------------------------------------------------------
1 | /************************************************************
2 | provide some function to simply the development
3 |
4 | variable:
5 | global: points the global scope
6 | Lib: contains function of this library
7 | eval: eval the code or the file contents
8 | Lib.getClassloader: get ClassLoader of target plugin
9 | Lib.loadType: load a class by classloader and return a JavaPackage
10 | ************************************************************/
11 |
12 | var global = this;
13 | var Lib = {};
14 | var JsLibPlugin = Packages.xingchen.jslib;
15 | var eval = null;
16 | (function() {
17 | var File = Packages.java.io.File;
18 | var JavaPlugin = Packages.org.bukkit.plugin.java.JavaPlugin;
19 |
20 | Lib.engine = JsLibPlugin.js.JavaScriptLoader.instance.getEngine();
21 | global.eval = function(code) {
22 | if(code instanceof File) {
23 | JsLibPlugin.js.JavaScriptLoader.instance["eval(java.io.File)"](code);
24 | } else {
25 | JsLibPlugin.js.JavaScriptLoader.instance["eval(java.lang.String)"](code);
26 | }
27 | };
28 | Lib.getClassloader = function(name, force) {
29 | var linkages = JsLibPlugin.export.LinkageLoader.instance.getLinkages();
30 | if(linkages.containsKey(name) && linkages.get(name).getClassloader() != null) {
31 | return linkages.get(name).getClassloader();
32 | }
33 | if(force == true) {
34 | var plugins = Packages.org.bukkit.Bukkit.getServer().getPluginManager().getPlugins();
35 | for(var i in plugins) {
36 | if(plugins[i].getName() == name) {
37 | if(plugins[i] instanceof JavaPlugin) {
38 | var method = JavaPlugin.class.getDeclaredMethod("getClassLoader");
39 | method.setAccessible(true);
40 | return method.invoke(plugins[i]);
41 | }
42 | }
43 | }
44 | }
45 | return null;
46 | }
47 | Lib.loadType = function(name, classloader) {
48 | if(classloader == undefined) {
49 | return Java.type(name);
50 | }
51 |
52 | var class_ = undefined;
53 | try {
54 | class_ = classloader.loadClass(name);
55 | } catch(e) {
56 | class_ = undefined;
57 | }
58 | if(class_ == undefined) {
59 | return Java.type(name);
60 | } else {
61 | return class_.static;
62 | }
63 | }
64 | })();
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | xingchen
6 | JavaScriptLibraryPlugin
7 | 1.0.2
8 |
9 | JavaScriptLibraryPlugin
10 | http://maven.apache.org
11 |
12 |
13 | UTF-8
14 | 1.8
15 | 1.8
16 | JavaScriptLibraryPlugin-${project.version}
17 | 1.15.2
18 | E:\Minecraft资源库\服务器\服务端\${debug.mcversion}\plugins
19 |
20 |
21 |
22 |
23 | org.spigotmc
24 | spigot
25 | ${debug.mcversion}
26 | system
27 | E:/Minecraft资源库/服务器/核心/spigot-${debug.mcversion}.jar
28 |
29 |
30 |
31 |
32 | ${out.name}
33 |
34 |
35 | org.apache.maven.plugins
36 | maven-jar-plugin
37 |
38 |
39 | false
40 |
41 |
42 |
43 |
44 | maven-antrun-plugin
45 |
46 |
47 | copy
48 | package
49 |
50 | run
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/export/LinkageLoader.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.export;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import org.bukkit.plugin.Plugin;
6 |
7 | import xingchen.jslib.event.register.JavaScriptPreRegisterEvent;
8 | import xingchen.jslib.js.IScriptHolder;
9 | import xingchen.jslib.event.register.JavaScriptFilesEvalledEvent;
10 |
11 | public class LinkageLoader {
12 | public static LinkageLoader instance;
13 |
14 | private Plugin plugin;
15 |
16 | private Map linkages;
17 |
18 | public LinkageLoader(Plugin plugin) {
19 | this.plugin = plugin;
20 | this.linkages = new HashMap<>();
21 | }
22 |
23 | /*public static void create(Plugin plugin) {
24 | instance = new LinkageLoader(plugin);
25 | for(Plugin other : plugin.getServer().getPluginManager().getPlugins()) {
26 | Method method = null;
27 | try {
28 | method = other.getClass().getMethod("getJsHolder");
29 | } catch (NoSuchMethodException | SecurityException e) {
30 | continue;
31 | }
32 | try {
33 | Object object = method.invoke(other);
34 | if(object instanceof IJsHolder) {
35 | instance.addLinkage(other, (IJsHolder) object);
36 | }
37 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
38 | e.printStackTrace();
39 | }
40 | }
41 | }
42 |
43 | public void evalAll() {
44 | this.linkages.entrySet().stream().forEach(i -> i.getValue().evalAll());
45 | }*/
46 |
47 | /**
48 | * 添加路径
49 | * {#IScriptHolder}实现类:{#ScriptHolderBase}
50 | *
51 | * @reture 注册是否成功
52 | */
53 | public boolean registerLinkage(String name, Plugin plugin, IScriptHolder jsHolder, ClassLoader classLoader) {
54 | if(this.getLinkages().containsKey(name)) {
55 | return false;
56 | }
57 |
58 | JavaScriptPreRegisterEvent preEvent = new JavaScriptPreRegisterEvent(this, name);
59 | this.plugin.getServer().getPluginManager().callEvent(preEvent);
60 | if(preEvent.isCancelled()) {
61 | return false;
62 | }
63 |
64 | PluginScripts scripts = new PluginScripts(plugin, jsHolder);
65 | scripts.setClassLoader(classLoader);
66 | this.linkages.put(name, scripts);
67 | scripts.loadScripts();
68 | scripts.evalAll();
69 |
70 | this.plugin.getServer().getPluginManager().callEvent(new JavaScriptFilesEvalledEvent(this, name));
71 |
72 | return true;
73 | }
74 |
75 | public boolean registerLinkage(String name, Plugin plugin, IScriptHolder jsHolder) {
76 | return registerLinkage(name, plugin, jsHolder, null);
77 | }
78 |
79 | public Plugin getPlugin() {
80 | return this.plugin;
81 | }
82 |
83 | public Map getLinkages() {
84 | return this.linkages;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/resources/lib/event.js:
--------------------------------------------------------------------------------
1 | Lib.Event = {};
2 | (function() {
3 | Lib.Event.priority = Packages.org.bukkit.event.EventPriority;
4 | Lib.Event.createKey = function() {
5 | return new JsLibPlugin.event.EventHolder();
6 | };
7 | Lib.Event.defaultKey = Lib.Event.createKey();
8 | Lib.Event.register = function(event, callback, priority_, ignoreCancelled, key, plugin) {
9 | if(priority_ == undefined) {
10 | priority_ = Lib.Event.priority.NORMAL;
11 | }
12 | if(ignoreCancelled == undefined) {
13 | ignoreCancelled = false;
14 | }
15 | if(key == undefined) {
16 | key = Lib.Event.defaultKey;
17 | }
18 | if(plugin == undefined) {
19 | plugin = JsLibPlugin.JavaScriptLibrary.instance;
20 | }
21 |
22 | var result = {};
23 | var handlerList = event.getHandlerList();
24 | result["listener"] = key;
25 | result["executor"] = JsLibPlugin.js.JavaScriptUtil.registerEvent(handlerList, callback, priority_, ignoreCancelled, key, plugin);
26 | result["unregister"] = function() {
27 | JsLibPlugin.js.JavaScriptUtil.removeEvent(handlerList, result["listener"]);
28 | }
29 |
30 | return result;
31 | };
32 | Lib.Event.unregister = function(event, key) {
33 | if(key == undefined) {
34 | key = Lib.Event.defaultKey;
35 | }
36 | JsLibPlugin.js.JavaScriptUtil.removeEvent(event.getHandlerList(), key);
37 | };
38 | Lib.Event.events = {};
39 | Lib.Event.addDepend = function(scriptNames, callback) {
40 | var linkages = JsLibPlugin.export.LinkageLoader.instance.getLinkages();
41 | var need = scriptNames;
42 | if(typeof(scriptNames) == "string") {
43 | var need = [scriptNames];
44 | }
45 |
46 | for (var i in need) {
47 | if(linkages.containsKey(i) && linkages.get(i).isEvalled()) {
48 | need.splice(i, 1);
49 | }
50 | }
51 | if(need.length <= 0) {
52 | callback();
53 | } else {
54 | if(!("jsEvalled" in Lib.Event.events)) {
55 | Lib.Event.events["jsEvalled"] = {};
56 | Lib.Event.events["jsEvalled"].evalList = [];
57 | Lib.Event.events["jsEvalled"].event = Lib.Event.register(JsLibPlugin.event.register.JavaScriptFilesEvalledEvent, function(evt) {
58 | for(var i=0;i map) {
37 | ConfigManager config = JavaScriptLibrary.instance.getConfigManager();
38 | String name = ConfigManager.getMainJsName(map);
39 |
40 | if(name != null) {
41 | String script = (String) map.get(name);
42 | try {
43 | this.engine.eval(script);
44 | } catch(ScriptException e2) {
45 | config.getLogger().log(Level.WARNING, "Unable to eval " + name + ".js", e2);
46 | }
47 | }
48 | }
49 |
50 | /**
51 | * 调用文件里的代码
52 | *
53 | * @param file 目标文件
54 | * @return 引擎eval方法的返回值
55 | * @throws IOException 读取文件时发生异常
56 | * @throws RuntimeException {#ScriptException}
57 | */
58 | public Object eval(File file) throws IOException {
59 | String code = JavaScriptLibrary.instance.getConfigManager().readFrom(file);
60 | if(code != null) {
61 | return this.eval(code);
62 | }
63 |
64 | return null;
65 | }
66 |
67 | /**
68 | * 通过引擎编译并执行代码
69 | *
70 | * @param code JavaScript代码
71 | * @return 引擎eval方法的返回值
72 | * @throws RuntimeException 执行代码时出现的异常(包装了{#ScriptException})
73 | */
74 | public Object eval(String code) {
75 | try {
76 | return this.engine.eval(code);
77 | } catch(ScriptException e) {
78 | throw new RuntimeException(e);
79 | }
80 | }
81 |
82 | /**
83 | * 根据列表获取指定层的代码
84 | *
85 | * @param map JavaScript表
86 | * @param path 层列表
87 | * @return Object(可能为代码)
88 | */
89 | public Object getMapCode(Map map, String[] path) {
90 | Object object = map;
91 | for(int i = 0; i < path.length; i++) {
92 | if(object instanceof Map) {
93 | object = ((Map) object).get(path[i]);
94 | } else {
95 | return null;
96 | }
97 | }
98 | return object;
99 | }
100 |
101 | public ScriptEngine getEngine() {
102 | return this.engine;
103 | }
104 |
105 | public static void init() {
106 | ConfigManager config = JavaScriptLibrary.instance.getConfigManager();
107 |
108 | if(config.getLib() != null) {
109 | config.getLib().loadScripts();
110 | config.getLib().evalAll();
111 | }
112 |
113 | if(config.getScripts() != null) {
114 | config.getScripts().loadScripts();
115 | config.getScripts().evalAll();
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/export/PluginScripts.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.export;
2 |
3 | import java.io.File;
4 | import java.io.FileNotFoundException;
5 | import java.io.UnsupportedEncodingException;
6 | import java.util.ArrayList;
7 | import java.util.Arrays;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.logging.Level;
11 |
12 | import org.bukkit.plugin.Plugin;
13 |
14 | import xingchen.jslib.JavaScriptLibrary;
15 | import xingchen.jslib.js.IScriptHolder;
16 | import xingchen.jslib.js.JavaScriptInfo;
17 | import xingchen.jslib.js.JavaScriptLoader;
18 | import xingchen.jslib.js.ScriptHolderBase;
19 | import xingchen.jslib.js.ScriptFiles;
20 |
21 | /**
22 | * 插件全部的JavaScript代码
23 | */
24 | public class PluginScripts {
25 | protected Plugin plugin;
26 | protected IScriptHolder jsHolder;
27 | protected ClassLoader classLoader;
28 |
29 | /**
30 | * 结构:
31 | * [
32 | * "KeyValue": {
33 | * "key": {#JavaScriptInfo},
34 | * "value": {#String} / {#Map}
35 | * if value instanceof {#Map}:
36 | * "value": {
37 | * "codeName": {#String} / {#Map}
38 | * if value instanceof {#Map}:......
39 | * }
40 | * }
41 | * ]
42 | */
43 | protected List> scripts;
44 | protected boolean isEvalled;
45 |
46 | public PluginScripts(Plugin plugin, File... directory) {
47 | this(plugin, new ScriptHolderBase(Arrays.stream(directory).map(i -> ScriptFiles.fromDirectory(i)).filter(i -> i != null).toArray(ScriptFiles[]::new)));
48 | }
49 |
50 | public PluginScripts(Plugin plugin, IScriptHolder jsHolder) {
51 | this.plugin = plugin;
52 | this.jsHolder = jsHolder;
53 | this.scripts = new ArrayList<>();
54 | this.isEvalled = false;
55 | }
56 |
57 | /**
58 | * 将JavaScript代码读取到内存({@link #scripts})
59 | */
60 | public void loadScripts() {
61 | Arrays.stream(this.jsHolder.getScriptFiles()).forEach(script -> {
62 | File file = script.getJsFile();
63 | if(file.exists()) {
64 | Object object = JavaScriptLibrary.instance.getConfigManager().parseScriptFile(file, "js");
65 | JavaScriptInfo info = null;
66 | if(script.getInfo() != null) {
67 | try {
68 | info = JavaScriptInfo.parse(this.plugin, script.getInfo());
69 | } catch (UnsupportedEncodingException | FileNotFoundException e) {
70 | JavaScriptLibrary.instance.getConfigManager().getLogger().log(Level.WARNING, "Unable to parse the js info belonging to the plugin: " + this.plugin.getName(), e);
71 | return;
72 | }
73 | }
74 |
75 | scripts.add(new KeyValue<>(info, object));
76 | }
77 | });
78 | }
79 |
80 | /**
81 | * 编译并执行当前对象内存中的JavaScript代码(必须先通过{@link #loadScripts()}读取代码)
82 | */
83 | public void evalAll() {
84 | this.scripts.stream().forEach(i -> {
85 | Object value = i.getValue();
86 | if(value instanceof String) {
87 | JavaScriptLoader.instance.eval(value.toString());
88 | } else if(value instanceof Map) {
89 | Map map = (Map) value;
90 | if(i.getKey() == null) {
91 | JavaScriptLoader.instance.evalMap(map);
92 | } else {
93 | i.getKey().invokeByOrder(map);
94 | }
95 | }
96 | });
97 | this.isEvalled = true;
98 | }
99 |
100 | public Plugin getPlugin() {
101 | return this.plugin;
102 | }
103 |
104 | public IScriptHolder getJsHolder() {
105 | return this.jsHolder;
106 | }
107 |
108 | public void setJsHolder(IScriptHolder jsHolder) {
109 | this.jsHolder = jsHolder;
110 | }
111 |
112 | public List> getScripts() {
113 | return this.scripts;
114 | }
115 |
116 | public void setScripts(List> scripts) {
117 | this.scripts = scripts;
118 | }
119 |
120 | public ClassLoader getClassLoader() {
121 | return this.classLoader;
122 | }
123 |
124 | public void setClassLoader(ClassLoader classLoader) {
125 | this.classLoader = classLoader;
126 | }
127 |
128 | public void setEvalled(boolean evalled) {
129 | isEvalled = evalled;
130 | }
131 |
132 | public boolean isEvalled() {
133 | return this.isEvalled;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/js/JavaScriptInfo.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.js;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.FileNotFoundException;
7 | import java.io.InputStreamReader;
8 | import java.io.UnsupportedEncodingException;
9 | import java.util.ArrayList;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.logging.Level;
13 |
14 | import javax.script.ScriptException;
15 |
16 | import org.bukkit.plugin.Plugin;
17 |
18 | import com.google.gson.JsonArray;
19 | import com.google.gson.JsonElement;
20 | import com.google.gson.JsonObject;
21 | import com.google.gson.JsonParser;
22 |
23 | import xingchen.jslib.JavaScriptLibrary;
24 |
25 | /**
26 | * 为null时为根据默认主JavaScript名调用代码
27 | * 为EMPTY对象时不调用代码
28 | * 当名字非空时根据给定的顺序进行调用
29 | *
30 | * 例(info.json):
31 | * {
32 | * name:"名字",
33 | * order:[
34 | * "代码文件1",
35 | * "代码文件2"
36 | * ]
37 | * }
38 | */
39 | public class JavaScriptInfo {
40 | public static final JavaScriptInfo EMPTY = new JavaScriptInfo(null, null);
41 |
42 | protected String name;
43 | protected List invokeOrder;
44 |
45 | public JavaScriptInfo(String name, List invokeOrder) {
46 | this.name = name;
47 | this.invokeOrder = invokeOrder;
48 | }
49 |
50 | /*@Override
51 | public boolean equals(Object object) {
52 | if(this == object) {
53 | return true;
54 | }
55 |
56 | if(object instanceof JavaScriptInfo) {
57 | JavaScriptInfo info = (JavaScriptInfo) object;
58 | if(this.getName() == info.getName()) {
59 | return true;
60 | }
61 | if(this.getName() == null) {
62 | return false;
63 | }
64 |
65 | return this.getName().equals(info.getName());
66 | }
67 |
68 | return false;
69 | }
70 |
71 | @Override
72 | public int hashCode() {
73 | if(this.name == null) {
74 | return 0;
75 | }
76 | return this.name.hashCode();
77 | }*/
78 |
79 | /**
80 | * 解析指定文件夹中的脚本信息文件
81 | *
82 | * @param plugin 调用该方法的插件
83 | * @param infoFile 信息文件所在的文件夹
84 | * @return 脚本信息对象
85 | */
86 | public static JavaScriptInfo parse(Plugin plugin, File infoFile) throws UnsupportedEncodingException, FileNotFoundException {
87 | if(infoFile == null || !infoFile.exists() || infoFile.isDirectory()) {
88 | return EMPTY;
89 | }
90 |
91 | BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(infoFile), "utf-8"));
92 |
93 | JsonParser parse = new JsonParser();
94 | JsonElement json = parse.parse(reader);
95 | if(!json.isJsonObject()) {
96 | return EMPTY;
97 | }
98 | JsonObject object = json.getAsJsonObject();
99 |
100 | String name;
101 | if(object.has("name")) {
102 | name = object.get("name").getAsString();
103 | } else {
104 | name = plugin.getName();
105 | }
106 |
107 | List invokeOrder = new ArrayList<>();
108 | if(object.has("order") && object.get("order").isJsonArray()) {
109 | JsonArray array = object.get("order").getAsJsonArray();
110 | for(int i = 0; i < array.size(); i++) {
111 | invokeOrder.add(array.get(i).getAsString());
112 | }
113 | }
114 |
115 | return new JavaScriptInfo(name, invokeOrder);
116 | }
117 |
118 | /**
119 | * 按照信息对象上的顺序调用JavaScript代码
120 | *
121 | * @param map JavaScript代码表
122 | */
123 | public void invokeByOrder(Map map) {
124 | if(this == EMPTY) {
125 | return;
126 | }
127 |
128 | this.invokeOrder.stream().forEach(i -> {
129 | String code = null;
130 | if(i.lastIndexOf("/") >= 0) {
131 | Object object = JavaScriptLoader.instance.getMapCode(map, i.split("/"));
132 | if(object != null) {
133 | code = (String) object;
134 | }
135 | } else if(map.get(i) instanceof String) {
136 | code = (String) map.get(i);
137 | }
138 |
139 | if(code != null) {
140 | try {
141 | JavaScriptLoader.instance.getEngine().eval(code);
142 | } catch(ScriptException e2) {
143 | JavaScriptLibrary.instance.getConfigManager().getLogger().log(Level.WARNING, "Unable to eval " + i + ".js", e2);
144 | }
145 | }
146 | });
147 | }
148 |
149 | public String getName() {
150 | return this.name;
151 | }
152 |
153 | public List getInvokeOrder() {
154 | return this.invokeOrder;
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/command/JsCommand.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.command;
2 |
3 | import java.util.Arrays;
4 | import java.util.logging.Level;
5 | import java.util.regex.Pattern;
6 | import java.util.stream.Collectors;
7 | import java.util.stream.IntStream;
8 |
9 | import javax.script.ScriptContext;
10 | import javax.script.ScriptException;
11 | import javax.script.SimpleScriptContext;
12 |
13 | import org.bukkit.ChatColor;
14 | import org.bukkit.command.Command;
15 | import org.bukkit.command.CommandSender;
16 | import org.bukkit.entity.Player;
17 | import org.bukkit.inventory.ItemStack;
18 | import org.bukkit.inventory.meta.BookMeta;
19 | import org.bukkit.inventory.meta.ItemMeta;
20 |
21 | import jdk.nashorn.api.scripting.ScriptObjectMirror;
22 | import jdk.nashorn.internal.runtime.Undefined;
23 | import xingchen.jslib.JavaScriptLibrary;
24 | import xingchen.jslib.js.JavaScriptLoader;
25 |
26 | public class JsCommand extends Command {
27 | public static final String CODEWRAP = "function(me) {%s}";
28 | public static final Pattern UNCOLOR = Pattern.compile("§.");
29 |
30 | public static final String COMMANDTIP = "§2请使用 §6/js help §2来查看帮助";
31 | public static final String ONLYPLAYER = "§4只有玩家才能使用此命令";
32 | public static final String UNABLE = "§4此命令未开启";
33 |
34 | public JsCommand() {
35 | super("javascriptlib", "Command of JavaScriptLibrary plugin", "/js help", Arrays.asList("javascript", "js"));
36 | }
37 |
38 | @Override
39 | public boolean execute(CommandSender sender, String capital, String[] args) {
40 | if(args.length <= 0 || "help".equalsIgnoreCase(args[0])) {
41 | this.sendHelp(sender);
42 | } else {
43 | String subcommand = args[0].toLowerCase();
44 | if(EnumJsSubCommand.RUN.isSubCommand(subcommand)) {
45 | if(!JavaScriptLibrary.instance.getConfigManager().getCommandRunState()) {
46 | sender.sendMessage(UNABLE);
47 | return true;
48 | }
49 | if(args.length >= 2) {
50 | String code = IntStream.range(1, args.length).mapToObj(i -> args[i]).collect(Collectors.joining(" "));
51 | this.eval(sender, code);
52 | }
53 | } else if(EnumJsSubCommand.BOOK.isSubCommand(subcommand)) {
54 | if(!JavaScriptLibrary.instance.getConfigManager().getCommandBookState()) {
55 | sender.sendMessage(UNABLE);
56 | return true;
57 | }
58 | if(sender instanceof Player) {
59 | Player player = (Player) sender;
60 | ItemStack itemStack = player.getEquipment().getItemInMainHand();
61 | if(itemStack != null && itemStack.hasItemMeta()) {
62 | ItemMeta meta = itemStack.getItemMeta();
63 | if(meta instanceof BookMeta) {
64 | StringBuilder sb = new StringBuilder();
65 | BookMeta bookmeta = (BookMeta) meta;
66 | bookmeta.getPages().stream().forEach(i -> sb.append(ChatColor.stripColor(i)));
67 | String code = sb.toString();
68 | if(code != null && !code.isEmpty()) {
69 | this.eval(player, code);
70 | }
71 | } else {
72 | sender.sendMessage("§4手上的物品不是代码书");
73 | }
74 | } else {
75 | sender.sendMessage("§4手上的物品不是代码书");
76 | }
77 | } else {
78 | sender.sendMessage(ONLYPLAYER);
79 | }
80 | } else {
81 | sender.sendMessage(COMMANDTIP);
82 | }
83 | }
84 |
85 | return true;
86 | }
87 |
88 | public void eval(CommandSender sender, String code) {
89 | try {
90 | Object function = JavaScriptLoader.instance.getEngine().eval(String.format(CODEWRAP, code));
91 | if(function != null && function instanceof ScriptObjectMirror) {
92 | Object back = ((ScriptObjectMirror) function).call(function, sender);
93 | if(back != null && back != Undefined.getUndefined()) {
94 | sender.sendMessage(back.toString());
95 | }
96 | }
97 | } catch (ScriptException e) {
98 | JavaScriptLibrary.instance.getConfigManager().getLogger().log(Level.WARNING, "Unable to eval javascript code: " + code, e);
99 | sender.sendMessage("§4在执行此js代码时出错");
100 | sender.sendMessage(e.getMessage());
101 | }
102 | }
103 |
104 | public void buildCommandJsLib(CommandSender sender, ScriptContext context) {
105 | context.setAttribute("me", sender, SimpleScriptContext.ENGINE_SCOPE);
106 | }
107 |
108 | public void sendHelp(CommandSender sender) {
109 | if(sender.hasPermission(EnumJsSubCommand.HELP.getPermission())) {
110 | sender.sendMessage(new String[] {
111 | " ",
112 | "§2§l/js run §6运行一段js代码",
113 | "§2§l/js book §6运行主手上拿着的书里的js代码",
114 | " "
115 | });
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/main/java/xingchen/jslib/config/ConfigManager.java:
--------------------------------------------------------------------------------
1 | package xingchen.jslib.config;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.BufferedReader;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.IOException;
8 | import java.io.InputStreamReader;
9 | import java.net.URL;
10 | import java.util.ArrayList;
11 | import java.util.Arrays;
12 | import java.util.HashMap;
13 | import java.util.LinkedList;
14 | import java.util.List;
15 | import java.util.Map;
16 | import java.util.jar.JarInputStream;
17 | import java.util.logging.Level;
18 | import java.util.logging.Logger;
19 | import java.util.stream.Collectors;
20 | import java.util.zip.ZipEntry;
21 |
22 | import org.bukkit.configuration.ConfigurationSection;
23 | import org.bukkit.configuration.file.FileConfiguration;
24 | import org.bukkit.plugin.Plugin;
25 |
26 | import xingchen.jslib.JavaScriptLibrary;
27 | import xingchen.jslib.export.PluginScripts;
28 |
29 | /**
30 | * 配置管理器
31 | */
32 | public class ConfigManager {
33 | /**脚本信息文件名*/
34 | public static final String INFOFILENAME = "info.json";
35 | public static List MAINJSNAME = new ArrayList<>();
36 |
37 | private Plugin plugin;
38 | private Logger logger;
39 |
40 | private FileConfiguration configFile;
41 |
42 | /**run子命令是否开启*/
43 | private boolean commandRun;
44 | /**book子命令是否开启*/
45 | private boolean commandBook;
46 | /**是否开启和其他插件的联动*/
47 | private boolean linkage;
48 |
49 | /**支持库代码*/
50 | private PluginScripts libraries;
51 | /**用户代码*/
52 | private PluginScripts scripts;
53 |
54 | public ConfigManager(Plugin plugin) {
55 | this.plugin = plugin;
56 | this.logger = plugin.getLogger();
57 | if(!this.checkCongig("config.yml")) {
58 | this.logger.info("配置文件未创建,正在创建...");
59 | plugin.saveDefaultConfig();
60 | } else {
61 | this.logger.info("配置文件已经创建,开始加载...");
62 | }
63 |
64 | this.checkLibraries();
65 | this.configFile = this.plugin.getConfig();
66 |
67 | Object command = this.configFile.get("command");
68 | if(command instanceof ConfigurationSection) {
69 | ConfigurationSection commandCS = (ConfigurationSection) command;
70 | this.commandRun = commandCS.getBoolean("run", false);
71 | this.commandBook = commandCS.getBoolean("book", false);
72 | } else if(command instanceof Boolean) {
73 | this.setAllCommand(((Boolean)command).booleanValue());
74 | } else {
75 | this.setAllCommand(false);
76 | }
77 |
78 | //加载支持库和用户代码
79 | this.linkage = this.configFile.getBoolean("linkage", false);
80 | this.libraries = this.loadScript("lib");
81 | if(this.libraries != null) {
82 | this.scripts = this.loadScript("scripts");
83 | } else {
84 | this.logger.info("发现js支持库损坏。");
85 | this.logger.info("请删除原支持库后重新启动。插件将会自动修复。");
86 | }
87 | }
88 |
89 | /**
90 | * 读取文件中的内容
91 | *
92 | * @param file 目标文件
93 | *
94 | * @return 文件中的内容(如果文件不存在或者为文件夹,则返回null)
95 | *
96 | * @exception IOException 如果文件读取时出现异常
97 | */
98 | public String readFrom(File file) throws IOException {
99 | if(file.exists() && !file.isDirectory()) {
100 | BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
101 | LinkedList stringList = new LinkedList<>();
102 |
103 | String line;
104 | while((line = reader.readLine()) != null) {
105 | stringList.add(line);
106 | }
107 |
108 | reader.close();
109 | return stringList.stream().collect(Collectors.joining("\n"));
110 | }
111 |
112 | return null;
113 | }
114 |
115 | /**
116 | * 根据{@link ConfigManager#MAINJSNAME}中的顺序,获取代码表中的主脚本名
117 | */
118 | public static String getMainJsName(Map map) {
119 | for(int i=0;i checkLibrary(target, dir, name + File.separator + i.getName()));
166 | } else {
167 | this.saveLibrary(target, name);
168 | }
169 | }
170 | }*/
171 |
172 | /**
173 | * 检查并修复支持库文件
174 | */
175 | public void checkLibraries() {
176 | try {
177 | JarInputStream jarZip = new JarInputStream(new BufferedInputStream(this.getJarURL().openStream()));
178 | ZipEntry entry;
179 | while((entry = jarZip.getNextEntry()) != null) {
180 | if(!entry.isDirectory() && entry.getName().startsWith("lib/")) {
181 | this.saveLibrary(this.plugin.getDataFolder(), entry.getName());
182 | }
183 | }
184 | jarZip.close();
185 | } catch (IOException e) {
186 | this.logger.log(Level.SEVERE, "Failed to check JavaScript Libraries.", e);
187 | }
188 | }
189 |
190 | /**
191 | * 加载用户插件
192 | */
193 | public PluginScripts loadScript(String fileName) {
194 | File file = new File(this.plugin.getDataFolder(), fileName);
195 | if(file.exists()) {
196 | return new PluginScripts(this.plugin, new File[] {file});
197 | }
198 |
199 | return null;
200 | }
201 |
202 | /**
203 | * 解析脚本文件,并返回其代码
204 | *
205 | * @param file 目标文件
206 | * @param suffix 脚本文件扩展名
207 | *
208 | * @return 如果文件为文件夹,则返回{#Map},否则返回{#String}
209 | */
210 | public Object parseScriptFile(File file, String suffix) {
211 | if(file.isDirectory()) {
212 | HashMap map = new HashMap<>();
213 | Arrays.stream(file.listFiles()).forEach(i -> {
214 | Object script = this.parseScriptFile(i, suffix);
215 | if(script != null && (!(script instanceof Map) || !((Map) script).isEmpty())) {
216 | String fileName = i.getName();
217 | if(i.isDirectory()) {
218 | map.put(fileName, script);
219 | } else {
220 | int lastp = fileName.lastIndexOf(".");
221 | if(suffix.equalsIgnoreCase(fileName.substring(lastp + 1))) {
222 | String name = fileName.substring(0, lastp);
223 | map.put(name, script);
224 | }
225 | }
226 | }
227 | });
228 |
229 | return map;
230 | } else {
231 | String name = file.getName();
232 | if(suffix.equalsIgnoreCase(name.substring(name.lastIndexOf(".") + 1))) {
233 | try {
234 | return this.readFrom(file);
235 | } catch (IOException e) {
236 | e.printStackTrace();
237 | }
238 | }
239 |
240 | return null;
241 | }
242 | }
243 |
244 | public Plugin getPlugin() {
245 | return this.plugin;
246 | }
247 |
248 | public void setPlugin(Plugin plugin) {
249 | this.plugin = plugin;
250 | }
251 |
252 | public Logger getLogger() {
253 | return this.logger;
254 | }
255 |
256 | public void setLogger(Logger logger) {
257 | this.logger = logger;
258 | }
259 |
260 | public FileConfiguration getConfigFile() {
261 | return this.configFile;
262 | }
263 |
264 | public void setConfigFile(FileConfiguration configFile) {
265 | this.configFile = configFile;
266 | }
267 |
268 | public void setAllCommand(boolean state) {
269 | this.commandRun = state;
270 | this.commandBook = state;
271 | }
272 |
273 | public boolean getCommandRunState() {
274 | return this.commandRun;
275 | }
276 |
277 | public void setCommandRunState(boolean commandRun) {
278 | this.commandRun = commandRun;
279 | }
280 |
281 | public boolean getCommandBookState() {
282 | return this.commandBook;
283 | }
284 |
285 | public void setCommandBookState(boolean commandBook) {
286 | this.commandBook = commandBook;
287 | }
288 |
289 | public boolean isLinkage() {
290 | return this.linkage;
291 | }
292 |
293 | public void setLinkage(boolean linkage) {
294 | this.linkage = linkage;
295 | }
296 |
297 | public PluginScripts getScripts() {
298 | return this.scripts;
299 | }
300 |
301 | public void setScripts(PluginScripts scripts) {
302 | this.scripts = scripts;
303 | }
304 |
305 | public PluginScripts getLib() {
306 | return this.libraries;
307 | }
308 |
309 | static {
310 | MAINJSNAME.add("main");
311 | MAINJSNAME.add("root");
312 | }
313 | }
314 |
--------------------------------------------------------------------------------