26
									
								
								src/main/java/pw/yumc/MiaoScript/BaseEvent.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/main/java/pw/yumc/MiaoScript/BaseEvent.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
package pw.yumc.MiaoScript;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.event.Event;
 | 
			
		||||
import org.bukkit.event.HandlerList;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created with IntelliJ IDEA
 | 
			
		||||
 *
 | 
			
		||||
 * @author 喵♂呜
 | 
			
		||||
 * Created on 2017/9/22 18:39.
 | 
			
		||||
 */
 | 
			
		||||
public class BaseEvent extends Event {
 | 
			
		||||
    private static HandlerList handlerList = new HandlerList();
 | 
			
		||||
 | 
			
		||||
    public BaseEvent() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static HandlerList getHandlerList() {
 | 
			
		||||
        return handlerList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public HandlerList getHandlers() {
 | 
			
		||||
        return handlerList;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
package pw.yumc.MiaoScript;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
 | 
			
		||||
import javax.script.ScriptEngineManager;
 | 
			
		||||
import javax.script.ScriptException;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.plugin.java.JavaPlugin;
 | 
			
		||||
 | 
			
		||||
@@ -32,8 +32,18 @@ public class MiaoScript extends JavaPlugin {
 | 
			
		||||
        loadEngine();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onDisable() {
 | 
			
		||||
        try {
 | 
			
		||||
            engine.invokeFunction("disable");
 | 
			
		||||
        } catch (ScriptException | NoSuchMethodException e) {
 | 
			
		||||
            Log.w("脚本引擎关闭失败! %s:%s", e.getClass().getName(), e.getMessage());
 | 
			
		||||
            Log.d(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void saveScript() {
 | 
			
		||||
        P.saveFile("modules");
 | 
			
		||||
        P.saveFile(true, "core", "modules", "plugins");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void loadEngine() {
 | 
			
		||||
@@ -45,9 +55,10 @@ public class MiaoScript extends JavaPlugin {
 | 
			
		||||
            this.engine = new MiaoScriptEngine(manager);
 | 
			
		||||
            this.engine.put("base", new Base());
 | 
			
		||||
            this.engine.eval(new InputStreamReader(this.getResource("bios.js")));
 | 
			
		||||
            engine.invokeFunction("boot", this, engine);
 | 
			
		||||
            engine.invokeFunction("boot", this);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.w("脚本引擎初始化失败! %s:%s", e.getClass().getName(), e.getMessage());
 | 
			
		||||
            Log.d(e);
 | 
			
		||||
        } finally {
 | 
			
		||||
            currentThread.setContextClassLoader(previousClassLoader);
 | 
			
		||||
        }
 | 
			
		||||
@@ -70,14 +81,7 @@ public class MiaoScript extends JavaPlugin {
 | 
			
		||||
 | 
			
		||||
        public void save(String path, String content) throws IOException {
 | 
			
		||||
            Log.d("保存文件 %s ...", path);
 | 
			
		||||
            File file = new File(path);
 | 
			
		||||
            if (!file.exists()) {
 | 
			
		||||
                file.getParentFile().mkdirs();
 | 
			
		||||
                file.createNewFile();
 | 
			
		||||
            }
 | 
			
		||||
            FileOutputStream fos = new FileOutputStream(file);
 | 
			
		||||
            fos.write(content.getBytes("UTF-8"));
 | 
			
		||||
            fos.close();
 | 
			
		||||
            Files.write(new File(path).toPath(), content.getBytes("UTF-8"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Class getActionBar() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,19 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
var boot;
 | 
			
		||||
var disable;
 | 
			
		||||
/**
 | 
			
		||||
 * 初始化框架引擎
 | 
			
		||||
 */
 | 
			
		||||
(function () {
 | 
			
		||||
    boot = function (plugin, engine) {
 | 
			
		||||
        engine.put('root', plugin.getDataFolder());
 | 
			
		||||
        engine.put('rootDir', plugin.getDataFolder().getCanonicalPath());
 | 
			
		||||
        load(rootDir + '/modules/init.js');
 | 
			
		||||
        init(plugin, engine);
 | 
			
		||||
    boot = function (plugin) {
 | 
			
		||||
        // 开发环境下初始化
 | 
			
		||||
        var root = "src/main/resources";
 | 
			
		||||
        if (plugin !== null) {
 | 
			
		||||
            // noinspection JSUnresolvedVariable
 | 
			
		||||
            root = plugin.dataFolder.canonicalPath;
 | 
			
		||||
        }
 | 
			
		||||
        load(root + '/core/init.js');
 | 
			
		||||
        init(root, plugin);
 | 
			
		||||
        disable = disablePlugins
 | 
			
		||||
    };
 | 
			
		||||
})();
 | 
			
		||||
							
								
								
									
										95
									
								
								src/main/resources/core/fs.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/main/resources/core/fs.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
/*global Java, base, module, exports, require, __FILE__*/
 | 
			
		||||
var String = Java.type("java.lang.String");
 | 
			
		||||
var File = Java.type("java.io.File");
 | 
			
		||||
var Files = Java.type("java.nio.file.Files");
 | 
			
		||||
var StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 获得文件
 | 
			
		||||
 * @constructor(file)
 | 
			
		||||
 * @constructor(dir,file)
 | 
			
		||||
 * @returns {*}
 | 
			
		||||
 */
 | 
			
		||||
exports.file = function () {
 | 
			
		||||
    if (exports.canonical(arguments[0])) {
 | 
			
		||||
        return arguments[0];
 | 
			
		||||
    }
 | 
			
		||||
    switch (arguments.length) {
 | 
			
		||||
        case 1:
 | 
			
		||||
            return new File(arguments[0]);
 | 
			
		||||
        case 2:
 | 
			
		||||
            return new File(exports.file(arguments[0]), arguments[1]);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 创建目录
 | 
			
		||||
 * @param file
 | 
			
		||||
 */
 | 
			
		||||
exports.mkdirs = function (file) {
 | 
			
		||||
    file.getParentFile().mkdirs();
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 创建文件
 | 
			
		||||
 * @param file
 | 
			
		||||
 */
 | 
			
		||||
exports.create = function (file) {
 | 
			
		||||
    file = exports.file(file);
 | 
			
		||||
    if (!file.exists()) {
 | 
			
		||||
        exports.mkdirs(file);
 | 
			
		||||
        file.createNewFile();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 获得文件规范路径
 | 
			
		||||
 * @param file
 | 
			
		||||
 * @returns {*}
 | 
			
		||||
 */
 | 
			
		||||
exports.canonical = function (file) {
 | 
			
		||||
    // noinspection JSUnresolvedVariable
 | 
			
		||||
    return file.canonicalPath;
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 复制文件
 | 
			
		||||
 * @param inputStream 输入流
 | 
			
		||||
 * @param target 目标文件
 | 
			
		||||
 * @param override 是否覆盖
 | 
			
		||||
 */
 | 
			
		||||
exports.copy = function (inputStream, target, override) {
 | 
			
		||||
    Files.copy(inputStream, target.toPath(), StandardCopyOption[override ? 'REPLACE_EXISTING' : 'ATOMIC_MOVE']);
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 读取文件
 | 
			
		||||
 * @param file 文件路径
 | 
			
		||||
 */
 | 
			
		||||
exports.read = function (file) {
 | 
			
		||||
    file = exports.file(file);
 | 
			
		||||
    if (!file.exists()) {
 | 
			
		||||
        log.w("读取文件 %s 错误 文件不存在!", file);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // noinspection JSPrimitiveTypeWrapperUsage
 | 
			
		||||
    return new String(Files.readAllBytes(file.toPath()), "UTF-8");
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 保存内容文件
 | 
			
		||||
 * @param path 路径
 | 
			
		||||
 * @param content 内容
 | 
			
		||||
 * @param override 是否覆盖
 | 
			
		||||
 */
 | 
			
		||||
exports.save = function (path, content, override) {
 | 
			
		||||
    Files.write(new File(path).toPath(), content.getBytes("UTF-8"), StandardCopyOption[override ? 'REPLACE_EXISTING' : 'ATOMIC_MOVE']);
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 列出目录文件
 | 
			
		||||
 * @param path
 | 
			
		||||
 */
 | 
			
		||||
exports.list = function (path) {
 | 
			
		||||
    var dir = exports.file(path);
 | 
			
		||||
    if (dir.isDirectory()) {
 | 
			
		||||
        return Files.list(dir.toPath());
 | 
			
		||||
    }
 | 
			
		||||
    log.w("路径 %s 不是一个目录 返回空数组!");
 | 
			
		||||
    return [];
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										60
									
								
								src/main/resources/core/init.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/main/resources/core/init.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
var global = this;
 | 
			
		||||
/*global base*/
 | 
			
		||||
 | 
			
		||||
// noinspection JSUnusedLocalSymbols
 | 
			
		||||
function init(root, plugin) {
 | 
			
		||||
    global.root = root;
 | 
			
		||||
    initDir();
 | 
			
		||||
    loadCore();
 | 
			
		||||
    loadRequire();
 | 
			
		||||
    loadPlugins(plugin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 初始化目录
 | 
			
		||||
 */
 | 
			
		||||
function initDir() {
 | 
			
		||||
    // 核心目录
 | 
			
		||||
    global.core_dir = root + "/core";
 | 
			
		||||
    // 模块目录
 | 
			
		||||
    global.miao_module_dir = root + "/modules";
 | 
			
		||||
    // 插件目录
 | 
			
		||||
    global.plugins_dir = root + "/plugins";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 初始化核心
 | 
			
		||||
 */
 | 
			
		||||
function loadCore() {
 | 
			
		||||
    // 加载基础模块
 | 
			
		||||
    load(core_dir + '/ext.js');
 | 
			
		||||
    load(core_dir + '/static.js');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 初始化模块
 | 
			
		||||
 */
 | 
			
		||||
function loadRequire() {
 | 
			
		||||
    // 初始化加载器
 | 
			
		||||
    global.require = load(core_dir + '/require.js')(root, core_dir, miao_module_dir);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 加载JS插件
 | 
			
		||||
 */
 | 
			
		||||
function loadPlugins(plugin) {
 | 
			
		||||
    // 初始化本体插件
 | 
			
		||||
    var self = require('modules/plugin');
 | 
			
		||||
    self.init(plugin, plugins_dir);
 | 
			
		||||
    self.load();
 | 
			
		||||
    self.enable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// noinspection JSUnusedLocalSymbols
 | 
			
		||||
/**
 | 
			
		||||
 * 关闭插件Hook
 | 
			
		||||
 */
 | 
			
		||||
function disablePlugins() {
 | 
			
		||||
    require('modules/plugin').disable();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										143
									
								
								src/main/resources/core/require.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/main/resources/core/require.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,143 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 符合 CommonJS 规范的 模块化加载
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
/*global Java, base*/
 | 
			
		||||
(function (parent, core_dir, miao_module_dir) {
 | 
			
		||||
    'use strict';
 | 
			
		||||
    var File = Java.type("java.io.File");
 | 
			
		||||
    var Files = Java.type("java.nio.file.Files");
 | 
			
		||||
    var String = Java.type("java.lang.String");
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 解析模块名称为文件
 | 
			
		||||
     * 按照下列顺序查找
 | 
			
		||||
     * 当前目录 ./
 | 
			
		||||
     * 父目录 ../
 | 
			
		||||
     * 核心目录 /core
 | 
			
		||||
     * 模块目录 /modules
 | 
			
		||||
     * @param name 模块名称
 | 
			
		||||
     */
 | 
			
		||||
    function findModule(name) {
 | 
			
		||||
        if (_canonical(name)) {
 | 
			
		||||
            name = _canonical(name);
 | 
			
		||||
        }
 | 
			
		||||
        if (!name.match(/.*\.js/)) {
 | 
			
		||||
            name += ".js";
 | 
			
		||||
        }
 | 
			
		||||
        var jsFile = new File(name);
 | 
			
		||||
        if (jsFile.exists()) {
 | 
			
		||||
            return jsFile;
 | 
			
		||||
        }
 | 
			
		||||
        var parentFile = new File(parent, name);
 | 
			
		||||
        if (parentFile.exists()) {
 | 
			
		||||
            return parentFile;
 | 
			
		||||
        }
 | 
			
		||||
        var coreFile = new File(core_dir, name);
 | 
			
		||||
        if (coreFile.exists()) {
 | 
			
		||||
            return coreFile;
 | 
			
		||||
        }
 | 
			
		||||
        var moduleFile = new File(miao_module_dir, name);
 | 
			
		||||
        if (moduleFile.exists()) {
 | 
			
		||||
            return moduleFile;
 | 
			
		||||
        }
 | 
			
		||||
        log.w("模块 %s 加载失败! 下列目录中未找到该模块!", name);
 | 
			
		||||
        log.w("当前目录: %s", _canonical(jsFile));
 | 
			
		||||
        log.w("上级目录: %s", _canonical(parentFile));
 | 
			
		||||
        log.w("核心目录: %s", _canonical(coreFile));
 | 
			
		||||
        log.w("模块目录: %s", _canonical(moduleFile));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 使用NIO读取文件内容
 | 
			
		||||
     * @param file 文件
 | 
			
		||||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    function _readFile(file) {
 | 
			
		||||
        // noinspection JSPrimitiveTypeWrapperUsage
 | 
			
		||||
        return new String(Files.readAllBytes(file.toPath()), "UTF-8");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 预编译模块
 | 
			
		||||
     * @param src
 | 
			
		||||
     * @returns {Object}
 | 
			
		||||
     */
 | 
			
		||||
    function compileJs(src) {
 | 
			
		||||
        var head = "(function (module, exports, require) {\n";
 | 
			
		||||
        var tail = "\n});";
 | 
			
		||||
        var fulljs = head + src + tail;
 | 
			
		||||
        return eval(fulljs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获得文件规范路径
 | 
			
		||||
     * @param file
 | 
			
		||||
     * @returns {*}
 | 
			
		||||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    function _canonical(file) {
 | 
			
		||||
        // noinspection JSUnresolvedVariable
 | 
			
		||||
        return file.canonicalPath;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 加载模块
 | 
			
		||||
     * @param name 模块名称
 | 
			
		||||
     * @param parent 父目录
 | 
			
		||||
     * @returns {*}
 | 
			
		||||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    function _require(name, parent) {
 | 
			
		||||
        var file = findModule(name, parent);
 | 
			
		||||
        // 重定向文件名称
 | 
			
		||||
        name = file.name.split(".")[0];
 | 
			
		||||
        var id = _canonical(file);
 | 
			
		||||
        var module = cacheModules[id];
 | 
			
		||||
        if (module) {
 | 
			
		||||
            return module;
 | 
			
		||||
        }
 | 
			
		||||
        log.d('加载模块 %s 位于 %s', name, id);
 | 
			
		||||
        module = {
 | 
			
		||||
            loaded: false,
 | 
			
		||||
            id: id,
 | 
			
		||||
            exports: {},
 | 
			
		||||
            require: exports(file.parentFile)
 | 
			
		||||
        };
 | 
			
		||||
        var src = _readFile(file);
 | 
			
		||||
        try {
 | 
			
		||||
            // 预编译模块
 | 
			
		||||
            var compiledWrapper = compileJs(src);
 | 
			
		||||
            compiledWrapper.apply(module.exports, [
 | 
			
		||||
                module, module.exports, module.require
 | 
			
		||||
            ]);
 | 
			
		||||
        } catch (ex) {
 | 
			
		||||
            log.w("模块 %s 编译失败!", name);
 | 
			
		||||
            log.w(ex);
 | 
			
		||||
        }
 | 
			
		||||
        log.d('模块 %s 编译成功!', name);
 | 
			
		||||
        module.loaded = true;
 | 
			
		||||
        cacheModules[id] = module;
 | 
			
		||||
        return cacheModules[id];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 闭包方法
 | 
			
		||||
     * @param parent 父目录
 | 
			
		||||
     * @returns {Function}
 | 
			
		||||
     */
 | 
			
		||||
    function exports(parent) {
 | 
			
		||||
        return function (path) {
 | 
			
		||||
            return _require(path, parent).exports;
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 等于 undefined 说明 parent 是一个字符串 需要转成File
 | 
			
		||||
    // 可能更加准确的方案
 | 
			
		||||
    if (_canonical(parent) === undefined) {
 | 
			
		||||
        parent = new File(parent);
 | 
			
		||||
    }
 | 
			
		||||
    var cacheModules = [];
 | 
			
		||||
    log.d("初始化 require 模块组件 父目录 %s", _canonical(parent));
 | 
			
		||||
    return exports(parent);
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										52
									
								
								src/main/resources/core/zip.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/main/resources/core/zip.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
/**
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
/*global Java, base, module, exports, require, __FILE__*/
 | 
			
		||||
 | 
			
		||||
var File = Java.type("java.io.File");
 | 
			
		||||
var ZipFile = Java.type("java.util.zip.ZipFile");
 | 
			
		||||
var fs = require('fs');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 获取文件真实名称
 | 
			
		||||
 *
 | 
			
		||||
 * @param name
 | 
			
		||||
 *            名称
 | 
			
		||||
 * @return string 文件名称
 | 
			
		||||
 */
 | 
			
		||||
function getRealName(name) {
 | 
			
		||||
    return new File(name).name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 解压文件
 | 
			
		||||
 * @param zipFile 压缩文件
 | 
			
		||||
 * @param target 目标目录(不传则为zip文件同级目录)
 | 
			
		||||
 */
 | 
			
		||||
function unzip(zipFile, target) {
 | 
			
		||||
    if (!zipFile.exists()) {
 | 
			
		||||
        log.w("解压文件 %s 错误 文件不存在!", zipFile);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (target === undefined) {
 | 
			
		||||
        // noinspection JSUnresolvedVariable
 | 
			
		||||
        target = new File(zipFile.parentFile.canonicalPath, zipFile.name.split(".")[0]);
 | 
			
		||||
    }
 | 
			
		||||
    log.d("解压文件 %s => %s", zipFile.canonicalPath, target);
 | 
			
		||||
    var zipObj = new ZipFile(zipFile);
 | 
			
		||||
    var e = zipObj.entries();
 | 
			
		||||
    while (e.hasMoreElements()) {
 | 
			
		||||
        var entry = e.nextElement();
 | 
			
		||||
        if (entry.isDirectory()) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        var destinationFilePath = new File(target, getRealName(entry.name));
 | 
			
		||||
        destinationFilePath.getParentFile().mkdirs();
 | 
			
		||||
        fs.copy(zipObj.getInputStream(entry), destinationFilePath, true);
 | 
			
		||||
    }
 | 
			
		||||
    zipObj.close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.unzip = unzip;
 | 
			
		||||
							
								
								
									
										40
									
								
								src/main/resources/modules/bukkit.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/main/resources/modules/bukkit.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Bukkit基础操作
 | 
			
		||||
 * Created by 蒋天蓓 on 2017/2/9 0009.
 | 
			
		||||
 */
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
/*global Java, base, module, exports, require, __FILE__*/
 | 
			
		||||
var Bukkit = Java.type("org.bukkit.Bukkit");
 | 
			
		||||
exports.broadcast = function (message) {
 | 
			
		||||
    Bukkit.broadcastMessage(message);
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 执行名称
 | 
			
		||||
 * @param player 玩家
 | 
			
		||||
 * @param command 命令
 | 
			
		||||
 */
 | 
			
		||||
exports.command = function (player, command) {
 | 
			
		||||
    Bukkit.dispatchCommand(player, command);
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 执行控制台命令
 | 
			
		||||
 * @param command 命令
 | 
			
		||||
 */
 | 
			
		||||
exports.console = function (command) {
 | 
			
		||||
    exports.command(Bukkit.getConsoleSender(), command);
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 玩家以OP权限执行命令
 | 
			
		||||
 * @param player
 | 
			
		||||
 * @param exper
 | 
			
		||||
 */
 | 
			
		||||
exports.opcommand = function (player, exper) {
 | 
			
		||||
    var origin = player.isOp();
 | 
			
		||||
    player.setOp(true);
 | 
			
		||||
    try {
 | 
			
		||||
        exports.command(player, exper);
 | 
			
		||||
    } finally {
 | 
			
		||||
        player.setOp(origin);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										118
									
								
								src/main/resources/modules/event.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								src/main/resources/modules/event.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
/*global Java, base, module, exports, require, __FILE__*/
 | 
			
		||||
var Thread = Java.type("java.lang.Thread");
 | 
			
		||||
var Bukkit = Java.type("org.bukkit.Bukkit");
 | 
			
		||||
var Listener = Java.type("org.bukkit.event.Listener");
 | 
			
		||||
var Modifier = Java.type("java.lang.reflect.Modifier");
 | 
			
		||||
var BukkitEvent = Java.type("org.bukkit.event.Event");
 | 
			
		||||
var EventPriority = Java.type("org.bukkit.event.EventPriority");
 | 
			
		||||
var EventExecutor = Java.type("org.bukkit.plugin.EventExecutor");
 | 
			
		||||
 | 
			
		||||
var mapEvent = [];
 | 
			
		||||
 | 
			
		||||
var plugin = require('plugin').$;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 映射事件名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent
 | 
			
		||||
 */
 | 
			
		||||
function mapEventName() {
 | 
			
		||||
    var eventPackageDir = "org/bukkit/event";
 | 
			
		||||
 | 
			
		||||
    var dirs = Thread.currentThread().getContextClassLoader().getResources(eventPackageDir);
 | 
			
		||||
    while (dirs.hasMoreElements()) {
 | 
			
		||||
        var url = dirs.nextElement();
 | 
			
		||||
        var protocol = url.protocol;
 | 
			
		||||
        if (protocol === "jar") {
 | 
			
		||||
            // noinspection JSUnresolvedVariable
 | 
			
		||||
            var jar = url.openConnection().jarFile;
 | 
			
		||||
            var entries = jar.entries();
 | 
			
		||||
            while (entries.hasMoreElements()) {
 | 
			
		||||
                var entry = entries.nextElement();
 | 
			
		||||
                var name = entry.name;
 | 
			
		||||
                if (name.startsWith(eventPackageDir) && name.endsWith(".class")) {
 | 
			
		||||
                    var i = name.replaceAll('/', '.');
 | 
			
		||||
                    try {
 | 
			
		||||
                        var clz = base.getClass(i.substring(0, i.length - 6));
 | 
			
		||||
                        if (isVaildEvent(clz)) {
 | 
			
		||||
                            // noinspection JSUnresolvedVariable
 | 
			
		||||
                            var simpleName = clz.simpleName.toLowerCase();
 | 
			
		||||
                            log.d("Mapping Event [%s] => %s", clz.name, simpleName);
 | 
			
		||||
                            mapEvent[simpleName] = clz;
 | 
			
		||||
                        }
 | 
			
		||||
                    } catch (ex) {
 | 
			
		||||
                        //ignore already loaded class
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isVaildEvent(clz) {
 | 
			
		||||
    // noinspection JSUnresolvedVariable
 | 
			
		||||
    return BukkitEvent.class.isAssignableFrom(clz) && Modifier.isPublic(clz.getModifiers()) && !Modifier.isAbstract(clz.getModifiers());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 添加事件监听
 | 
			
		||||
 * @param event
 | 
			
		||||
 * @param exec {function}
 | 
			
		||||
 * @param priority
 | 
			
		||||
 * @param ignoreCancel
 | 
			
		||||
 */
 | 
			
		||||
function listen(event, exec, priority, ignoreCancel) {
 | 
			
		||||
    var eventCls = mapEvent[event];
 | 
			
		||||
    if (!eventCls) {
 | 
			
		||||
        try {
 | 
			
		||||
            eventCls = base.getClass(eventCls);
 | 
			
		||||
        } catch (ex) {
 | 
			
		||||
            log.w("事件 %s 未找到!");
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (priority === undefined) {
 | 
			
		||||
        priority = 'NORMAL'
 | 
			
		||||
    }
 | 
			
		||||
    if (ignoreCancel === undefined) {
 | 
			
		||||
        ignoreCancel = false;
 | 
			
		||||
    }
 | 
			
		||||
    var listener = new Java.extend(Listener, {});
 | 
			
		||||
    // noinspection JSUnusedGlobalSymbols
 | 
			
		||||
    /**
 | 
			
		||||
     * @param event Event type to register
 | 
			
		||||
     * @param listener Listener to register
 | 
			
		||||
     * @param priority Priority to register this event at
 | 
			
		||||
     * @param executor EventExecutor to register
 | 
			
		||||
     * @param plugin Plugin to register
 | 
			
		||||
     * @param ignoreCancel
 | 
			
		||||
     */
 | 
			
		||||
    Bukkit.getPluginManager().registerEvent(
 | 
			
		||||
        eventCls,
 | 
			
		||||
        listener,
 | 
			
		||||
        EventPriority[priority],
 | 
			
		||||
        new Java.extend(EventExecutor, {
 | 
			
		||||
            execute: function (listener, event) {
 | 
			
		||||
                exec(event);
 | 
			
		||||
            }
 | 
			
		||||
        }),
 | 
			
		||||
        plugin,
 | 
			
		||||
        ignoreCancel);
 | 
			
		||||
    return {
 | 
			
		||||
        event: eventCls,
 | 
			
		||||
        listener: listener
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 映射事件名称
 | 
			
		||||
mapEventName();
 | 
			
		||||
 | 
			
		||||
exports.on = listen;
 | 
			
		||||
/**
 | 
			
		||||
 * 取消事件监听
 | 
			
		||||
 * @param listener 监听结果
 | 
			
		||||
 */
 | 
			
		||||
exports.off = function (listener) {
 | 
			
		||||
    // noinspection JSUnresolvedVariable
 | 
			
		||||
    listener.event.handlerList.unregister(listener.listener);
 | 
			
		||||
};
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
/*global require*/
 | 
			
		||||
var global = this;
 | 
			
		||||
load(rootDir + '/modules/ext.js');
 | 
			
		||||
load(rootDir + '/modules/static.js');
 | 
			
		||||
 | 
			
		||||
function init(plugin, engine) {
 | 
			
		||||
    log.d("Version: %s", plugin.getDescription().getVersion());
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										90
									
								
								src/main/resources/modules/plugin.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/main/resources/modules/plugin.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
/*global Java, base, module, exports, require, __FILE__*/
 | 
			
		||||
var zip = require("core/zip");
 | 
			
		||||
var fs = require('core/fs');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 载入插件
 | 
			
		||||
 * @param path
 | 
			
		||||
 */
 | 
			
		||||
function loadPlugins(path) {
 | 
			
		||||
    path = fs.file(path);
 | 
			
		||||
    log.i("开始扫描 %s 下的插件...", path);
 | 
			
		||||
    updatePlugins();
 | 
			
		||||
    var files = [];
 | 
			
		||||
    fs.list(path).forEach(function (file) {
 | 
			
		||||
        files.push(file.toFile());
 | 
			
		||||
    });
 | 
			
		||||
    loadZipPlugin(files);
 | 
			
		||||
    loadJsPlugin(files);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 更新插件
 | 
			
		||||
 * @param path
 | 
			
		||||
 */
 | 
			
		||||
function updatePlugins(path) {
 | 
			
		||||
    var dir = fs.file(path, "update");
 | 
			
		||||
    fs.list(dir).forEach(function (file) {
 | 
			
		||||
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ZIP类型插件预加载
 | 
			
		||||
 * @param files
 | 
			
		||||
 */
 | 
			
		||||
function loadZipPlugin(files) {
 | 
			
		||||
    // // TODO ZIP类型插件加载
 | 
			
		||||
    // files.filter(function (file) {
 | 
			
		||||
    //     return file.name.endsWith(".zip");
 | 
			
		||||
    // }).forEach(function (file) {
 | 
			
		||||
    //     zip.unzip(fs.file(plugins_dir, file));
 | 
			
		||||
    //     var dir = new File(plugins_dir, file.name.split(".")[0]);
 | 
			
		||||
    //     // TODO 添加文件夹类型的插件兼容
 | 
			
		||||
    // });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * JS类型插件预加载
 | 
			
		||||
 */
 | 
			
		||||
function loadJsPlugin(files) {
 | 
			
		||||
    files.filter(function (file) {
 | 
			
		||||
        return file.name.endsWith(".js")
 | 
			
		||||
    }).forEach(function (file) {
 | 
			
		||||
        var p = require(file);
 | 
			
		||||
        log.d(JSON.stringify(p));
 | 
			
		||||
        if (!p.description || !p.description.name) {
 | 
			
		||||
            log.w("文件 %s 不存在 description 描述信息 无法加载插件!");
 | 
			
		||||
        } else {
 | 
			
		||||
            exports.plugins.push(p);
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.$ = undefined;
 | 
			
		||||
exports.plugins = [];
 | 
			
		||||
exports.init = function (plugin, path) {
 | 
			
		||||
    if (plugin !== null) {
 | 
			
		||||
        exports.$ = plugin;
 | 
			
		||||
        log.i("Init MiaoScript Engine Version: %s", plugin.description.version);
 | 
			
		||||
        require('./event');
 | 
			
		||||
    }
 | 
			
		||||
    loadPlugins(path);
 | 
			
		||||
};
 | 
			
		||||
exports.load = function () {
 | 
			
		||||
    exports.plugins.forEach(function (p) {
 | 
			
		||||
        p.load();
 | 
			
		||||
    })
 | 
			
		||||
};
 | 
			
		||||
exports.enable = function () {
 | 
			
		||||
    exports.plugins.forEach(function (p) {
 | 
			
		||||
        p.enable();
 | 
			
		||||
    })
 | 
			
		||||
};
 | 
			
		||||
exports.disable = function () {
 | 
			
		||||
    exports.plugins.forEach(function (p) {
 | 
			
		||||
        p.disable();
 | 
			
		||||
    })
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										25
									
								
								src/main/resources/plugins/hello.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/main/resources/plugins/hello.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Hello Wrold 测试插件
 | 
			
		||||
 */
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var event = require('modules/event');
 | 
			
		||||
var joinCancel;
 | 
			
		||||
/*global Java, base, module, exports, require*/
 | 
			
		||||
exports.description = {
 | 
			
		||||
    name: 'HelloWorld'
 | 
			
		||||
};
 | 
			
		||||
exports.load = function () {
 | 
			
		||||
    log.i('载入 Hello Wrold 测试插件!');
 | 
			
		||||
};
 | 
			
		||||
exports.enable = function () {
 | 
			
		||||
    log.i('启用 Hello Wrold 测试插件!');
 | 
			
		||||
    joinCancel = event.on('playerloginevent', function (event) {
 | 
			
		||||
        // noinspection JSUnresolvedVariable
 | 
			
		||||
        event.player.sendMessage('§a欢迎来到 §bMiaoScript §a的世界!');
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
exports.disable = function () {
 | 
			
		||||
    log.i('卸载 Hello Wrold 测试插件!');
 | 
			
		||||
    event.off(joinCancel);
 | 
			
		||||
};
 | 
			
		||||
@@ -26,10 +26,12 @@ public class MiaoScriptTest {
 | 
			
		||||
        try {
 | 
			
		||||
            ScriptEngineManager manager = new ScriptEngineManager();
 | 
			
		||||
            this.engine = new MiaoScriptEngine(manager);
 | 
			
		||||
            this.engine.put("base", new MiaoScript.Base());
 | 
			
		||||
            this.engine.eval(new FileReader("src/main/resources/bios.js"));
 | 
			
		||||
            engine.invokeFunction("boot", this, engine);
 | 
			
		||||
            engine.invokeFunction("boot", null, engine);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            Log.w("脚本引擎初始化失败! %s:%s", e.getClass().getName(), e.getMessage());
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        } finally {
 | 
			
		||||
            currentThread.setContextClassLoader(previousClassLoader);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user