feat: 新增 Console 和 reflect 部分完善 command

Signed-off-by: 502647092 <admin@yumc.pw>
This commit is contained in:
502647092 2017-10-10 21:01:43 +08:00
parent 59b2824413
commit d0b43487c2
14 changed files with 281 additions and 95 deletions

View File

@ -58,7 +58,7 @@ public class MiaoScript extends JavaPlugin implements Executor {
} }
private void saveScript() { private void saveScript() {
P.saveFile(true, "core", "modules", "plugins"); P.saveFile(true, "core", "modules", "kit");
} }
private void loadEngine() { private void loadEngine() {

View File

@ -18,7 +18,8 @@ var disable;
} catch (ex) { } catch (ex) {
log.w("MiaoScript 初始化失败! %s", ex); log.w("MiaoScript 初始化失败! %s", ex);
throw ex; throw ex;
} } finally {
disable = disablePlugins disable = disablePlugins
}
}; };
})(); })();

View File

@ -0,0 +1,21 @@
/**
* 控制台输出类
*/
/*global base*/
var log = base.getLog().static;
var Level = Java.type('java.util.logging.Level');
var console = {
log: function () {
log.i(arguments.join(' '));
},
warn: function () {
log.w(arguments.join(' '));
},
error: function () {
log.log(Level.SEVERE, arguments.join(' '));
},
debug: function () {
log.d(arguments.join(' '));
}
};
global.console = console;

View File

@ -10,7 +10,7 @@ var ext = {};
* @returns {*} * @returns {*}
*/ */
ext.getStatic = function (name) { ext.getStatic = function (name) {
return base.getClass(name).static; return base.class(name).static;
}; };
/** /**
* 获得随机数 * 获得随机数

View File

@ -96,7 +96,7 @@ exports.list = function (path) {
if (dir.isDirectory()) { if (dir.isDirectory()) {
return Files.list(dir.toPath()); return Files.list(dir.toPath());
} }
log.w("路径 %s 不是一个目录 返回空数组!"); log.w("路径 %s 不是一个目录 返回空数组!", path);
return []; return [];
}; };
/** /**

View File

@ -30,7 +30,6 @@ function initDir() {
function loadCore() { function loadCore() {
// 加载基础模块 // 加载基础模块
load(core_dir + '/ext.js'); load(core_dir + '/ext.js');
load(core_dir + '/static.js');
load(core_dir + '/console.js'); load(core_dir + '/console.js');
} }
@ -39,7 +38,7 @@ function loadCore() {
*/ */
function loadRequire() { function loadRequire() {
// 初始化加载器 // 初始化加载器
global.require = load(core_dir + '/require.js')(root, core_dir, miao_module_dir); global.require = load(core_dir + '/require.js')(root);
} }
function loadLib4Bukkit() { function loadLib4Bukkit() {

View File

@ -3,7 +3,7 @@
* *
*/ */
/*global Java, base*/ /*global Java, base*/
(function (parent, core_dir, miao_module_dir) { (function (parent) {
'use strict'; 'use strict';
var File = Java.type("java.io.File"); var File = Java.type("java.io.File");
@ -16,35 +16,37 @@
* 模块目录 /modules * 模块目录 /modules
* @param name 模块名称 * @param name 模块名称
*/ */
function findModule(name) { function resolve(name) {
if (_canonical(name)) { if (_canonical(name)) {
name = _canonical(name); name = _canonical(name);
} }
// 如果不是 .js 结尾就加上 name = normalizeName(name, '.js');
if (!name.match(/.*\.js/)) { return resolveAsFile(parent, name) ||
name += ".js"; resolveAsFile(name) ||
resolveAsFile(core_dir, name) ||
resolveAsFile(miao_module_dir, name) ||
undefined;
} }
var jsFile = new File(name);
if (jsFile.exists()) { /**
return jsFile; * 解析文件
* @constructor(file)
* @constructor(dir,file)
* @returns {*}
*/
function resolveAsFile() {
var file = arguments.length > 1 ? new File(arguments[0], arguments[1]) : new File(arguments[0]);
if (file.exists()) {
return file;
} }
var parentFile = new File(parent, name);
if (parentFile.exists()) {
return parentFile;
} }
var coreFile = new File(core_dir, name);
if (coreFile.exists()) { function normalizeName(fileName, ext) {
return coreFile; var extension = ext || '.js';
if (fileName.endsWith(extension)) {
return fileName;
} }
var moduleFile = new File(miao_module_dir, name); return fileName + extension;
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));
} }
/** /**
@ -55,11 +57,43 @@
function compileJs(file) { function compileJs(file) {
var cacheFile = _cacheFile(file); var cacheFile = _cacheFile(file);
base.save(cacheFile, "(function (module, exports, require) {" + base.read(file) + "});"); base.save(cacheFile, "(function (module, exports, require) {" + base.read(file) + "});");
// 使用 load 可以保留行号和文件名称
var obj = load(cacheFile); var obj = load(cacheFile);
base.delete(cacheFile); base.delete(cacheFile);
return obj; return obj;
} }
/**
* 编译模块
* @param id
* @param name
* @param file
* @returns {Object}
*/
function compileModule(id, name, file) {
log.d('加载模块 %s 位于 %s', name, id);
// noinspection JSUnresolvedVariable
var module = {
id: id,
exports: {},
loaded: false,
require: exports(file.parentFile)
};
try {
// 预编译模块
var compiledWrapper = compileJs(file);
compiledWrapper.apply(module.exports, [
module, module.exports, module.require
]);
log.d('模块 %s 编译成功!', name);
module.loaded = true;
} catch (ex) {
log.w("模块 %s 编译失败!", name);
log.d(ex);
}
return module;
}
/** /**
* 获得文件规范路径 * 获得文件规范路径
* @param file * @param file
@ -83,7 +117,11 @@
* @private * @private
*/ */
function _require(name, path) { function _require(name, path) {
var file = findModule(name, path); var file = resolve(name, path);
if (file === undefined) {
log.w("模块 %s 加载失败! 未找到该模块!", name);
return;
}
// 重定向文件名称 // 重定向文件名称
name = file.name.split(".")[0]; name = file.name.split(".")[0];
var id = _canonical(file); var id = _canonical(file);
@ -91,27 +129,7 @@
if (module) { if (module) {
return module; return module;
} }
log.d('加载模块 %s 位于 %s', name, id); cacheModules[id] = module = compileModule(id, name, file);
// noinspection JSUnresolvedVariable
module = {
loaded: false,
id: id,
exports: {},
require: exports(file.parentFile)
};
try {
// 预编译模块
var compiledWrapper = compileJs(file);
compiledWrapper.apply(module.exports, [
module, module.exports, module.require
]);
log.d('模块 %s 编译成功!', name);
module.loaded = true;
} catch (ex) {
log.w("模块 %s 编译失败!", name);
log.d(ex);
}
cacheModules[id] = module;
return module; return module;
} }
@ -126,7 +144,7 @@
}; };
} }
var cacheDir = parent + "/cache"; var cacheDir = parent + "/runtime";
// 等于 undefined 说明 parent 是一个字符串 需要转成File // 等于 undefined 说明 parent 是一个字符串 需要转成File
// 可能有更加准确的方案 // 可能有更加准确的方案

View File

@ -1,24 +0,0 @@
/**
* 基础静态类
* Created by 蒋天蓓 on 2017/2/9 0009.
*/
/**
* 日志类
*/
var log = base.getLog().static;
/**
* ActionBar类
*/
var actionbar = base.getActionBar().static;
/**
* Title类
*/
var title = base.getTitle().static;
/**
* 玩家兼容类
*/
var cplayer = base.getPlayer().static;
/**
* 工具类
*/
var mctools = base.getTools().static;

View File

@ -0,0 +1,119 @@
'use strict';
/**
* 反射工具类
* Created by 蒋天蓓 on 2017/2/9 0009.
*/
/*global Java, base, module, exports, require, __FILE__*/
var Class = Java.type('java.lang.Class');
var NoSuchFieldException = Java.type('java.lang.NoSuchFieldException');
function Reflect(obj) {
this.obj = obj;
this.class = obj instanceof Class ? obj : obj.class;
}
/**
* Get an array of types for an array of objects
*/
function types(values) {
if (values === null) {
return [];
}
var result = [];
values.forEach(function (t) {
result.push(t === null ? Object.class : t.class)
});
return result;
}
function accessible(accessible) {
if (accessible === null) {
return null;
}
if (!accessible.isAccessible()) {
accessible.setAccessible(true);
}
return accessible;
}
function declaredConstructor() {
return accessible(arguments[0].declaredConstructor(arguments.slice(1)));
}
function declaredField(clazz, name) {
var field = null;
// noinspection JSUnresolvedVariable
while (clazz !== java.lang.Object.class) {
try {
field = clazz.declaredField(name);
if (field !== null) {
break;
}
} catch (e) {
clazz = clazz.superclass();
}
}
if (field === null) {
throw new NoSuchFieldException(name + " is not found in " + clazz.name);
}
return field;
}
Reflect.field = function (name) {
try {
// Try getting a public field
var field = this.class.field(name);
return on(field.get(this.obj));
} catch (ex) {
// Try again, getting a non-public field
try {
return on(accessible(declaredField(this.class, name)).get(this.obj));
} catch (ex) {
throw new NoSuchFieldException(ex);
}
}
};
Reflect.method = function () {
var name = arguments[0];
var clazzs = arguments.slice(1);
try {
return this.class.method(name, clazzs);
} catch (ex) {
return this.class.declaredMethod(name, clazzs);
}
};
var methodCache = [];
Reflect.cacheMethod = function () {
var name = arguments[0];
var mkey = this.class.name + '.' + name;
if (!methodCache[mkey]) {
methodCache[mkey] = this.method(name, arguments.slice(1));
}
return methodCache[mkey];
};
Reflect.call = function () {
var name = arguments[0];
var params = arguments.slice(1);
var method = this.method(name, types(params));
return exports.on(method.invoke(this.get(), params));
};
Reflect.get = function () {
return arguments.length === 1 ? this.field(arguments[0]) : this.obj;
};
Reflect.create = function () {
return on(declaredConstructor(this.class, arguments).newInstance(arguments));
};
function on(obj) {
return new Reflect(obj);
}
exports.on = on;
exports.accessible = accessible;

View File

@ -2,4 +2,49 @@
/** /**
* Bukkit 命令相关类 * Bukkit 命令相关类
*/ */
/*global Java, base, module, exports, require, __FILE__*/ /*global Java, base, module, exports, require, __FILE__*/
var plugin = base.plugin;
var bukkit = require('bukkit');
var ref = require('kit/reflect');
var lookupNames = ref.on(bukkit.plugin.manager).get('lookupNames').get();
var knownCommands = ref.on(bukkit.plugin.manager).get('commandMap').get('knownCommands').get();
var PluginCommand = Java.type('org.bukkit.command.PluginCommand');
function create(jsp, name) {
var cmd = ref.on(PluginCommand).create(name, plugin).get();
register(jsp, name, cmd);
}
function register(jsp, name, cmd) {
if (name.isEmpty()) {
return;
}
knownCommands.put(name, cmd);
knownCommands.computeIfAbsent(jsp.description.name + ":" + name, function () {
return cmd;
});
knownCommands.computeIfAbsent('ms:' + jsp.description.name + ":" + name, function () {
return cmd;
});
lookupNames.put(name, plugin);
}
// var exec = {
// onCommand: function (sender, cmd, command, args) {
//
// },
// onTabComplete: function (sender, cmd, command, args) {
//
// }
// };
exports.on = function (plugin, name, exec) {
var c = create(plugin, name);
if (exec.onCommand) {
c.setExecutor(exec);
}
if (exec.onTabComplete) {
c.setTabCompleter(exec);
}
};

View File

@ -80,7 +80,7 @@ function listen(event, exec, priority, ignoreCancel) {
try { try {
eventCls = base.getClass(eventCls); eventCls = base.getClass(eventCls);
} catch (ex) { } catch (ex) {
log.w("事件 %s 未找到!"); log.w("事件 %s 未找到!", event);
return; return;
} }
} }

View File

@ -11,7 +11,10 @@ var fs = require('core/fs');
* @param path * @param path
*/ */
function loadPlugins(path) { function loadPlugins(path) {
path = fs.file(path); var plugin = fs.file(path);
if (!plugin) {
log.i("首次加载 创建文件夹 %s ...", path);
} else {
log.i("开始扫描 %s 下的插件 ...", path); log.i("开始扫描 %s 下的插件 ...", path);
updatePlugins(path); updatePlugins(path);
var files = []; var files = [];
@ -21,6 +24,7 @@ function loadPlugins(path) {
loadZipPlugin(files); loadZipPlugin(files);
loadJsPlugin(files); loadJsPlugin(files);
} }
}
/** /**
* 更新插件 * 更新插件
@ -28,10 +32,14 @@ function loadPlugins(path) {
*/ */
function updatePlugins(path) { function updatePlugins(path) {
var update = fs.file(path, "update"); var update = fs.file(path, "update");
if (!update.exists()) {
update.mkdirs();
} else {
fs.list(update).forEach(function (file) { fs.list(update).forEach(function (file) {
fs.move(fs.file(update, file.name), fs.file(path, file.name), true); fs.move(fs.file(update, file.name), fs.file(path, file.name), true);
}) })
} }
}
/** /**
* ZIP类型插件预加载 * ZIP类型插件预加载

View File

@ -4,7 +4,6 @@
*/ */
/*global Java, base, module, exports, require*/ /*global Java, base, module, exports, require*/
var papi = require("modules/ext/papi");
var event = require('modules/event'); var event = require('modules/event');
var join; var join;
@ -14,17 +13,17 @@ var description = {
}; };
function load() { function load() {
log.i('载入 Hello Wrold 测试插件!'); console.log('载入 Hello Wrold 测试插件!');
} }
function enable() { function enable() {
log.i('启用 Hello Wrold 测试插件!'); console.log('启用 Hello Wrold 测试插件!');
join = event.on('playerloginevent', function join(event) { join = event.on('playerloginevent', function join(event) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
log.d('玩家 %s 触发事件 %s', event.player.name, event.name); log.d('玩家 %s 触发事件 %s', event.player.name, event.name);
setTimeout(function () { setTimeout(function () {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
event.player.sendMessage(papi.$(event.player, "§a欢迎来到 §bMiaoScript §a的世界! 当前在线: %server_online%")); event.player.sendMessage(require("plugins/ext/papi").$(event.player, "§a欢迎来到 §bMiaoScript §a的世界! 当前在线: %server_online%"));
}, 10); }, 10);
}); });
} }