feat: 独立Bukkit插件部分 完善console输出 完善format格式化
This commit is contained in:
parent
e387863061
commit
c7293370ea
@ -29,7 +29,6 @@ public class MiaoScript extends JavaPlugin implements Executor {
|
||||
@SneakyThrows
|
||||
public void onEnable() {
|
||||
new CommandSub("ms", this);
|
||||
saveScript();
|
||||
engine = new ScriptEngine(getDataFolder().getCanonicalPath(), getClassLoader(), getLogger());
|
||||
}
|
||||
|
||||
@ -73,11 +72,6 @@ public class MiaoScript extends JavaPlugin implements Executor {
|
||||
}
|
||||
}
|
||||
|
||||
private void saveScript() {
|
||||
P.saveFile(true, "core", "modules");
|
||||
P.saveFile("plugins");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
engine.disableEngine();
|
||||
|
@ -17,14 +17,17 @@ var disable;
|
||||
try {
|
||||
init(root);
|
||||
} catch (ex) {
|
||||
throw ex;
|
||||
if(console.ex){
|
||||
console.ex(ex);
|
||||
}else{
|
||||
throw ex;
|
||||
}
|
||||
} finally {
|
||||
disable = disablePlugins
|
||||
}
|
||||
};
|
||||
|
||||
function release(root, regex, replace) {
|
||||
print(Array.prototype.join.call(arguments, ' '));
|
||||
var Files = Java.type("java.nio.file.Files");
|
||||
var Paths = Java.type("java.nio.file.Paths");
|
||||
var StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
|
||||
@ -55,7 +58,6 @@ var disable;
|
||||
}
|
||||
})
|
||||
} catch (ex) {
|
||||
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
this.log = function () {
|
||||
log.info(this.name + Array.prototype.join.call(arguments, ' '));
|
||||
};
|
||||
this.info = this.log;
|
||||
this.warn = function () {
|
||||
log.warning(this.name + Array.prototype.join.call(arguments, ' '));
|
||||
};
|
||||
@ -71,9 +72,9 @@
|
||||
}
|
||||
track.forEach(function (stack) {
|
||||
if (stack.className.startsWith('<')) {
|
||||
this.console(String.format(' §e位于 §c%s => §c%s §4行%s', stack.fileName, stack.methodName, stack.lineNumber));
|
||||
this.console(' §e位于 §c%s => §c%s §4行%s'.format(stack.fileName, stack.methodName, stack.lineNumber));
|
||||
} else {
|
||||
this.console(String.format(' §e位于 §c%s.%s(§4%s:%s§c)', stack.className, stack.methodName, stack.fileName, stack.lineNumber));
|
||||
this.console(' §e位于 §c%s.%s(§4%s:%s§c)'.format(stack.className, stack.methodName, stack.fileName, stack.lineNumber));
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ exports.concat = function () {
|
||||
*/
|
||||
exports.file = function () {
|
||||
if (!arguments[0]) {
|
||||
log.w("文件名称不得为 undefined 或者 null !");
|
||||
console.warn("文件名称不得为 undefined 或者 null !");
|
||||
}
|
||||
switch (arguments.length) {
|
||||
case 1:
|
||||
@ -77,7 +77,7 @@ exports.copy = function (inputStream, target, override) {
|
||||
exports.read = function (file) {
|
||||
file = exports.file(file);
|
||||
if (!file.exists()) {
|
||||
log.w("读取文件 %s 错误 文件不存在!", file);
|
||||
console.warn("读取文件 %s 错误 文件不存在!".format(file));
|
||||
return;
|
||||
}
|
||||
// noinspection JSPrimitiveTypeWrapperUsage
|
||||
@ -103,7 +103,7 @@ exports.list = function (path) {
|
||||
if (dir.isDirectory()) {
|
||||
return Files.list(dir.toPath());
|
||||
}
|
||||
log.w("路径 %s 不是一个目录 返回空数组!", path);
|
||||
console.warn("路径 %s 不是一个目录 返回空数组!".format(path));
|
||||
return [];
|
||||
};
|
||||
/**
|
||||
|
@ -64,7 +64,7 @@ function loadLib4Bukkit() {
|
||||
function loadPlugins() {
|
||||
// 初始化本体插件
|
||||
global.manager = require('modules/plugin');
|
||||
manager.init(base.plugin, 'plugins');
|
||||
manager.init('plugins');
|
||||
// 只有当在正式环境运行的时候才加载
|
||||
if (manager.$) {
|
||||
manager.load();
|
||||
@ -77,7 +77,7 @@ function loadPlugins() {
|
||||
* 关闭插件Hook
|
||||
*/
|
||||
function disablePlugins() {
|
||||
if (manager.$) {
|
||||
if (manager && manager.$) {
|
||||
manager.disable();
|
||||
}
|
||||
}
|
@ -3,6 +3,10 @@
|
||||
*/
|
||||
|
||||
(function(){
|
||||
// Java格式化方法
|
||||
var str = Java.type('java.lang.String');
|
||||
String.prototype.format = function(){ return str.format(this, Array.prototype.slice.call(arguments, 0))}
|
||||
|
||||
// JSON快捷方法
|
||||
Object.prototype.toJson = function(){ return JSON.stringify(this); }
|
||||
|
||||
|
@ -107,7 +107,7 @@
|
||||
* @returns {Object}
|
||||
*/
|
||||
function compileModule(id, name, file, optional) {
|
||||
console.debug('加载模块 %s 位于 %s Optional %s', name, id, optional.toJson());
|
||||
console.debug('加载模块 %s 位于 %s Optional %s'.format(name, id, optional.toJson()));
|
||||
// noinspection JSUnresolvedVariable
|
||||
var module = {
|
||||
id: id,
|
||||
@ -120,10 +120,10 @@
|
||||
compiledWrapper.apply(module.exports, [
|
||||
module, module.exports, module.require, file.parentFile, file
|
||||
]);
|
||||
console.debug('模块 %s 编译成功!', name);
|
||||
console.debug('模块 %s 编译成功!'.format(name));
|
||||
module.loaded = true;
|
||||
} catch (ex) {
|
||||
console.console("§4警告! §b模块 §a%s §4编译失败! ERR: %s", name, ex);
|
||||
console.console("§4警告! §c模块 §a%s §c编译失败! §4ERR: %s".format(name, ex));
|
||||
console.ex(ex);
|
||||
}
|
||||
return module;
|
||||
@ -155,7 +155,7 @@
|
||||
function _require(name, path, optional) {
|
||||
var file = _canonical(name) ? name : resolve(name, path);
|
||||
if (file === undefined) {
|
||||
console.console("§c模块 §a%s §c加载失败! §4未找到该模块!", name);
|
||||
console.console("§c模块 §a%s §c加载失败! §4未找到该模块!".format(name));
|
||||
return {exports: {}};
|
||||
}
|
||||
if (!optional) optional = {cache: true};
|
||||
@ -189,6 +189,6 @@
|
||||
parent = new File(parent);
|
||||
}
|
||||
var cacheModules = [];
|
||||
console.debug("初始化 require 模块组件 父目录 %s", _canonical(parent));
|
||||
console.debug("初始化 require 模块组件 父目录 ", _canonical(parent));
|
||||
return exports(parent);
|
||||
});
|
@ -12,7 +12,7 @@ var fs = require('fs');
|
||||
*/
|
||||
function unzip(zipFile, target) {
|
||||
if (!zipFile.exists()) {
|
||||
log.w("解压文件 %s 错误 文件不存在!", zipFile);
|
||||
console.warn("解压文件 %s 错误 文件不存在!".format(zipFile));
|
||||
return;
|
||||
}
|
||||
if (target === undefined) {
|
||||
@ -20,7 +20,7 @@ function unzip(zipFile, target) {
|
||||
// noinspection JSUnresolvedVariable
|
||||
target = fs.file(zipFile.parentFile.canonicalPath, fname.substring(0, fname.length() - 4));
|
||||
}
|
||||
log.d("解压文件 %s 到目录 %s", zipFile.canonicalPath, target);
|
||||
console.debug("解压文件 %s 到目录 %s".format(zipFile.canonicalPath, target));
|
||||
var zipObj = new ZipFile(zipFile);
|
||||
var e = zipObj.entries();
|
||||
while (e.hasMoreElements()) {
|
||||
|
93
src/main/resources/modules/bukkit/command.js
Normal file
93
src/main/resources/modules/bukkit/command.js
Normal file
@ -0,0 +1,93 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Bukkit 命令相关类
|
||||
*/
|
||||
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
var ref = require('core/reflect');
|
||||
var bukkit = require('./server');
|
||||
var plugin = bukkit.plugin.self;
|
||||
var commandMap = ref.on(bukkit.plugin.manager).get('commandMap').get();
|
||||
var PluginCommand = Java.type('org.bukkit.command.PluginCommand');
|
||||
|
||||
var StringUtil = Java.type('org.bukkit.util.StringUtil');
|
||||
|
||||
var ArrayList = Java.type('java.util.ArrayList');
|
||||
var Arrays = Java.type('java.util.Arrays');
|
||||
|
||||
function enable(jsp) {
|
||||
var commands = jsp.description.commands;
|
||||
if (commands) {
|
||||
var pluginCmds = [];
|
||||
for (var name in commands) {
|
||||
var command = commands[name];
|
||||
if (typeof command !== 'object') continue;
|
||||
var newCmd = create(jsp, name);
|
||||
if (command.description) newCmd.setDescription(command.description);
|
||||
if (command.usage) newCmd.setUsage(command.usage);
|
||||
if (command.aliases) newCmd.setAliases(Arrays.asList(command.aliases));
|
||||
if (command.permission) newCmd.setPermission(command.permission);
|
||||
if (command['permission-message']) newCmd.setPermissionMessage(command['permission-message']);
|
||||
pluginCmds.push(newCmd);
|
||||
console.debug('插件 %s 注册命令 %s ...'.format(jsp.description.name, name));
|
||||
}
|
||||
commandMap.registerAll(jsp.description.name, Arrays.asList(pluginCmds));
|
||||
}
|
||||
}
|
||||
|
||||
function get(name) {
|
||||
return commandMap.getCommand(name);
|
||||
}
|
||||
|
||||
function create(jsp, name) {
|
||||
return register(jsp, ref.on(PluginCommand).create(name, plugin).get());
|
||||
}
|
||||
|
||||
function register(jsp, cmd) {
|
||||
commandMap.register(jsp.description.name, cmd);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
// var exec = {
|
||||
// cmd: function (sender, command, args) {
|
||||
//
|
||||
// },
|
||||
// tab: function (sender, command, args) {
|
||||
//
|
||||
// }
|
||||
// };
|
||||
|
||||
function on(jsp, name, exec) {
|
||||
var c = get(name) || create(jsp, name);
|
||||
console.debug('插件 %s 设置命令 %s(%s) 执行器 ...'.fotmat(jsp.description.name, name, c));
|
||||
if (exec.cmd) {
|
||||
c.setExecutor(function (sender, cmd, command, args) {
|
||||
try {
|
||||
return exec.cmd(sender, command, args);
|
||||
} catch (ex) {
|
||||
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s'.fotmat(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
|
||||
console.ex(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (exec.tab) {
|
||||
c.setTabCompleter(function (sender, cmd, command, args) {
|
||||
try {
|
||||
var completions = new ArrayList();
|
||||
var token = args[args.length - 1];
|
||||
StringUtil.copyPartialMatches(token, Arrays.asList(exec.tab(sender, command, args)), completions);
|
||||
return completions;
|
||||
} catch (ex) {
|
||||
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s'.fotmat(sender.name, jsp.description.name, command, Java.from(args).join(' '), ex));
|
||||
console.ex(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.enable = enable;
|
||||
|
||||
exports.on = on;
|
||||
exports.off = function () {
|
||||
|
||||
};
|
158
src/main/resources/modules/bukkit/event.js
Normal file
158
src/main/resources/modules/bukkit/event.js
Normal file
@ -0,0 +1,158 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Bukkit 事件相关类
|
||||
*/
|
||||
/*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 HandlerList = Java.type('org.bukkit.event.HandlerList');
|
||||
var EventPriority = Java.type("org.bukkit.event.EventPriority");
|
||||
var EventExecutor = Java.type("org.bukkit.plugin.EventExecutor");
|
||||
var IllegalStateException = Java.type("java.lang.IllegalStateException");
|
||||
|
||||
var plugin = require('./server').plugin.self;
|
||||
|
||||
var ref = require('reflect');
|
||||
|
||||
var listenerMap = [];
|
||||
|
||||
/**
|
||||
* 扫描包 org.bukkit.event 下的所有事件
|
||||
* 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent
|
||||
*/
|
||||
function mapEventName() {
|
||||
var eventPackageDir = "org/bukkit/event";
|
||||
var count = 0;
|
||||
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;
|
||||
// 以 org/bukkit/event 开头 并且以 .class 结尾
|
||||
if (name.startsWith(eventPackageDir) && name.endsWith(".class")) {
|
||||
var i = name.replaceAll('/', '.');
|
||||
try {
|
||||
var clz = base.getClass(i.substring(0, i.length - 6));
|
||||
// 继承于 org.bukkit.event.Event 访问符为Public
|
||||
if (isVaildEvent(clz)) {
|
||||
// noinspection JSUnresolvedVariable
|
||||
var simpleName = clz.simpleName.toLowerCase();
|
||||
console.debug("Mapping Event [%s] => %s".format(clz.name, simpleName));
|
||||
mapEvent[simpleName] = clz;
|
||||
count++;
|
||||
}
|
||||
} catch (ex) {
|
||||
//ignore already loaded class
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为一个有效的事件类
|
||||
* @param clz
|
||||
* @returns {*|boolean}
|
||||
*/
|
||||
function isVaildEvent(clz) {
|
||||
// noinspection JSUnresolvedVariable 继承于 org.bukkit.event.Event
|
||||
return BukkitEvent.class.isAssignableFrom(clz) &&
|
||||
// 访问符为Public
|
||||
Modifier.isPublic(clz.getModifiers()) &&
|
||||
// 不是抽象类
|
||||
!Modifier.isAbstract(clz.getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加事件监听
|
||||
* @param jsp
|
||||
* @param event
|
||||
* @param exec {function}
|
||||
* @param priority
|
||||
* @param ignoreCancel
|
||||
*/
|
||||
function listen(jsp, event, exec, priority, ignoreCancel) {
|
||||
var name = jsp.description.name;
|
||||
if (ext.isNull(name)) throw new TypeError('插件名称为空 请检查传入参数!');
|
||||
var eventCls = mapEvent[event] || mapEvent[event.toLowerCase()] || mapEvent[event + 'Event'] || mapEvent[event.toLowerCase() + 'event'];
|
||||
if (!eventCls) {
|
||||
try {
|
||||
eventCls = base.getClass(eventCls);
|
||||
} catch (ex) {
|
||||
console.warn("事件 %s 未找到!".format(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (typeof priority === 'boolean') {
|
||||
ignoreCancel = priority
|
||||
}
|
||||
priority = priority || 'NORMAL';
|
||||
ignoreCancel = ignoreCancel || false;
|
||||
var listener = new 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 EventExecutor({
|
||||
execute: function (listener, event) {
|
||||
try {
|
||||
exec(event);
|
||||
} catch (ex) {
|
||||
console.console('§6插件 §b%s §6处理 §d%s §6事件时发生异常 §4%s'.format(name, event.class.simpleName, ex));
|
||||
console.ex(ex);
|
||||
}
|
||||
}
|
||||
}),
|
||||
plugin,
|
||||
ignoreCancel);
|
||||
// 添加到缓存 用于关闭插件的时候关闭事件
|
||||
if (!listenerMap[name]) listenerMap[name] = []
|
||||
var listeners = listenerMap[name];
|
||||
var off = {
|
||||
event: eventCls,
|
||||
listener: listener,
|
||||
off: function () {
|
||||
ref.on(this.event).call('getHandlerList').get().unregister(this.listener);
|
||||
console.debug('插件 %s 注销事件 %s'.format(name, this.event.simpleName));
|
||||
}
|
||||
}
|
||||
listeners.push(off);
|
||||
// noinspection JSUnresolvedVariable
|
||||
console.debug('插件 %s 注册事件 %s 方法 %s'.format(name, eventCls.simpleName, exec.name === '' ? '匿名方法' : exec.name));
|
||||
return off;
|
||||
}
|
||||
|
||||
var mapEvent = [];
|
||||
// 映射事件名称
|
||||
console.info('Bukkit 事件映射完毕 共计 %s 个事件!'.format(mapEventName().toFixed(0)));
|
||||
|
||||
module.exports = {
|
||||
on: listen,
|
||||
disable: function (jsp) {
|
||||
var jspl = listenerMap[jsp.description.name];
|
||||
if (jspl) {
|
||||
jspl.forEach(function (t) t.off());
|
||||
delete listenerMap[jsp.description.name];
|
||||
}
|
||||
}
|
||||
};
|
48
src/main/resources/modules/bukkit/permission.js
Normal file
48
src/main/resources/modules/bukkit/permission.js
Normal file
@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Bukkit 权限相关类
|
||||
*/
|
||||
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
var manager = require('./server').plugin.manager;
|
||||
|
||||
/**
|
||||
* Permission(String name, String description)
|
||||
*/
|
||||
var Permission = Java.type("org.bukkit.permissions.Permission");
|
||||
var PermissionDefault = Java.type('org.bukkit.permissions.PermissionDefault');
|
||||
|
||||
function enable(plugin) {
|
||||
var permissions = plugin.description.permissions;
|
||||
if (permissions) {
|
||||
for (var name in permissions) {
|
||||
var permission = permissions[name];
|
||||
if (typeof permission !== 'object') continue;
|
||||
var desc = permission.description;
|
||||
var def = permission.default || 'OP';
|
||||
try {
|
||||
manager.addPermission(new Permission(name, desc, PermissionDefault.getByName(def)));
|
||||
} catch (ex) {
|
||||
// ignore eg: java.lang.IllegalArgumentException: The permission xxxxxx.default is already defined!
|
||||
}
|
||||
console.debug('插件 %s 注册权限 %s Default %s ...'.format(plugin.description.name, name, def));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function disable(plugin) {
|
||||
var permissions = plugin.description.permissions;
|
||||
if (permissions) {
|
||||
for (var name in permissions) {
|
||||
try {
|
||||
manager.removePermission(name);
|
||||
} catch (ex) {
|
||||
// ignore eg: java.lang.IllegalArgumentException: The permission xxxxxx.default is already defined!
|
||||
}
|
||||
console.debug('插件 %s 注销权限 %s ...'.format(plugin.description.name, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.enable = enable;
|
||||
exports.disable = disable;
|
259
src/main/resources/modules/bukkit/plugin.js
Normal file
259
src/main/resources/modules/bukkit/plugin.js
Normal file
@ -0,0 +1,259 @@
|
||||
'use strict';
|
||||
/**
|
||||
* MiaoScript脚本插件加载类
|
||||
*/
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
// var zip = require("core/zip");
|
||||
var fs = require('core/fs');
|
||||
var yaml = require('modules/yaml');
|
||||
var event = require('modules/event');
|
||||
var bukkit = require('./server');
|
||||
var command = require('./command');
|
||||
var permission = require('./permission');
|
||||
|
||||
/**
|
||||
* 载入插件
|
||||
* @param path
|
||||
*/
|
||||
function loadPlugins(dir) {
|
||||
var plugin = fs.file(root, dir);
|
||||
if (!plugin) {
|
||||
console.info("首次加载 创建文件夹 %s ...".format(plugin));
|
||||
} else {
|
||||
console.info("开始扫描 %s 下的插件 ...".format(plugin));
|
||||
createUpdate(plugin);
|
||||
var files = [];
|
||||
fs.list(plugin).forEach(function (file) {
|
||||
files.push(file.toFile());
|
||||
});
|
||||
loadZipPlugins(files);
|
||||
loadJsPlugins(files);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新插件
|
||||
* @param path
|
||||
*/
|
||||
function createUpdate(path) {
|
||||
var update = fs.file(path, "update");
|
||||
if (!update.exists()) {
|
||||
update.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ZIP类型插件预加载
|
||||
* @param files
|
||||
*/
|
||||
function loadZipPlugins(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 loadJsPlugins(files) {
|
||||
files.filter(function (file) {
|
||||
return file.name.endsWith(".js")
|
||||
}).forEach(function (file) {
|
||||
loadPlugin(file);
|
||||
})
|
||||
}
|
||||
|
||||
function loadPlugin(file) {
|
||||
var update = fs.file(fs.file(file.parentFile, 'update'), file.name);
|
||||
if (update.exists()) {
|
||||
console.info('自动升级插件 %s'.format(file.name));
|
||||
fs.move(update, file, true);
|
||||
}
|
||||
var plugin = require(file, {
|
||||
cache: false,
|
||||
hook: function (origin) {
|
||||
return beforeLoadHook(origin);
|
||||
}
|
||||
});
|
||||
console.debug("插件编译结果: %s".format(plugin.toJson()));
|
||||
var desc = plugin.description;
|
||||
if (!desc || !desc.name) {
|
||||
console.warn("文件 %s 不存在 description 描述信息 无法加载插件!".format(file));
|
||||
} else {
|
||||
initPlugin(file, plugin);
|
||||
afterLoadHook(plugin);
|
||||
plugins.push(plugin);
|
||||
plugins[plugin.description.name] = plugin;
|
||||
console.info('载入插件 %s 版本 %s By %s'.format(desc.name, desc.version || '未知', desc.author || '未知'));
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
|
||||
function beforeLoadHook(origin) {
|
||||
var result = origin;
|
||||
// 处理 event 为了不影响 正常逻辑 event 还是手动require吧
|
||||
// result = result + 'var event = {}; module.exports.event = event;';
|
||||
// 注入 console 对象 // 给插件注入单独的 console
|
||||
result = result + 'var console = new Console(); module.exports.console = console;';
|
||||
// 插件注入 self 对象
|
||||
result = result + 'var self = {}; module.exports.self = self;';
|
||||
return result;
|
||||
}
|
||||
|
||||
function afterLoadHook(plugin) {
|
||||
// plugin.event.on = event.on.bind(plugin);
|
||||
// 给 console 添加插件名称
|
||||
plugin.console.name = plugin.description.name;
|
||||
// 赋值 self
|
||||
for (var i in plugin) {
|
||||
plugin.self[i] = plugin[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化插件内容(提供config,__DATA__等参数)
|
||||
*/
|
||||
function initPlugin(file, plugin) {
|
||||
// 初始化 __FILE__
|
||||
plugin.__FILE__ = file;
|
||||
// 初始化 __DATA__
|
||||
plugin.__DATA__ = fs.file(file.parentFile, plugin.description.name);
|
||||
// 初始化 getDataFolder()
|
||||
plugin.getDataFolder = function () {
|
||||
return plugin.__DATA__;
|
||||
};
|
||||
// 初始化 getFile()
|
||||
plugin.getFile = function (name) {
|
||||
return fs.file(plugin.getDataFolder(), name);
|
||||
};
|
||||
|
||||
// 初始化插件配置相关方法
|
||||
initPluginConfig(plugin);
|
||||
|
||||
command.enable(plugin);
|
||||
permission.enable(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化插件配置
|
||||
*/
|
||||
function initPluginConfig(plugin) {
|
||||
// 初始化 config
|
||||
plugin.configFile = plugin.getFile('config.yml');
|
||||
/**
|
||||
* 获取配置文件
|
||||
* @constructor
|
||||
* @constructor (file|string)
|
||||
*/
|
||||
plugin.getConfig = function () {
|
||||
switch (arguments.length) {
|
||||
case 0:
|
||||
return plugin.config;
|
||||
case 1:
|
||||
var file = arguments[0];
|
||||
if (!file.isFile) {
|
||||
file = plugin.getFile(file);
|
||||
}
|
||||
return yaml.safeLoad(base.read(file));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 重载配置文件
|
||||
* @constructor
|
||||
* @constructor (file|string)
|
||||
*/
|
||||
plugin.reloadConfig = function () {
|
||||
plugin.config = plugin.getConfig(plugin.configFile);
|
||||
};
|
||||
/**
|
||||
* 保存配置文件
|
||||
* @constructor
|
||||
* @constructor (file, content)
|
||||
*/
|
||||
plugin.saveConfig = function () {
|
||||
switch (arguments.length) {
|
||||
case 0:
|
||||
plugin.configFile.parentFile.mkdirs();
|
||||
base.save(plugin.configFile, plugin.config.toYaml());
|
||||
break;
|
||||
case 2:
|
||||
base.save(arguments[0], arguments[1].toYaml());
|
||||
break;
|
||||
}
|
||||
};
|
||||
if (plugin.configFile.isFile()) {
|
||||
plugin.config = plugin.getConfig('config.yml');
|
||||
} else if (plugin.description.config) {
|
||||
plugin.config = plugin.description.config;
|
||||
plugin.saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
function runAndCatch(jsp, exec, ext) {
|
||||
if (exec) {
|
||||
try {
|
||||
// 绑定方法的this到插件自身
|
||||
exec.bind(jsp)();
|
||||
if (ext) {
|
||||
ext();
|
||||
}
|
||||
} catch (ex) {
|
||||
console.console('§6插件 §b%s §6执行 §d%s §6方法时发生错误 §4%s'.format(jsp.description.name, exec.name, ex.message));
|
||||
console.ex(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkAndGet(args) {
|
||||
if (args.length === 0) {
|
||||
return plugins;
|
||||
}
|
||||
var name = args[0];
|
||||
// 如果是插件 则直接返回
|
||||
if (name.description) {
|
||||
return [name];
|
||||
}
|
||||
if (!exports.plugins[name]) {
|
||||
throw new Error("插件 " + name + " 不存在!");
|
||||
}
|
||||
return [exports.plugins[name]];
|
||||
}
|
||||
|
||||
var plugins = [];
|
||||
|
||||
exports.$ = undefined;
|
||||
exports.plugins = plugins;
|
||||
exports.init = function (path) {
|
||||
var plugin = bukkit.plugin.self;
|
||||
if (plugin !== null) {
|
||||
// 如果过plugin不等于null 则代表是正式环境
|
||||
exports.$ = plugin;
|
||||
console.info("初始化 MiaoScript 插件系统 版本: %s".format(plugin.description.version));
|
||||
}
|
||||
loadPlugins(path);
|
||||
};
|
||||
exports.load = function () {
|
||||
checkAndGet(arguments).forEach(function (p) runAndCatch(p, p.load));
|
||||
};
|
||||
exports.enable = function () {
|
||||
checkAndGet(arguments).forEach(function (p) runAndCatch(p, p.enable));
|
||||
};
|
||||
exports.disable = function () {
|
||||
checkAndGet(arguments).forEach(function (p) runAndCatch(p, p.disable, function () {
|
||||
event.disable(p);
|
||||
// task.cancel();
|
||||
}));
|
||||
};
|
||||
exports.reload = function () {
|
||||
checkAndGet(arguments).forEach(function (p) {
|
||||
exports.disable(p);
|
||||
p = loadPlugin(p.__FILE__);
|
||||
exports.load(p);
|
||||
exports.enable(p);
|
||||
});
|
||||
};
|
@ -75,7 +75,8 @@ exports.plugin = {
|
||||
PluginManager.enablePlugin(plugin);
|
||||
}
|
||||
return PluginManager.isPluginEnabled(name);
|
||||
}
|
||||
},
|
||||
self: PluginManager.getPlugin('MiaoScript')
|
||||
};
|
||||
/**
|
||||
* 公告
|
71
src/main/resources/modules/bukkit/task.js
Normal file
71
src/main/resources/modules/bukkit/task.js
Normal file
@ -0,0 +1,71 @@
|
||||
'use strict';
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
/**
|
||||
* 任务计划
|
||||
* Created by 蒋天蓓 on 2017/2/9 0009.
|
||||
*/
|
||||
var plugin = require('./server').plugin.self;
|
||||
var BukkitRunnable = Java.type("org.bukkit.scheduler.BukkitRunnable");
|
||||
/**
|
||||
* 创建任务对象
|
||||
* @param func 任务
|
||||
*/
|
||||
exports.create = function (func) {
|
||||
return new BukkitRunnable(func);
|
||||
};
|
||||
/**
|
||||
* 运行任务
|
||||
* @param func 任务
|
||||
*/
|
||||
exports.run = function (func) {
|
||||
return exports.create(func).runTask(plugin);
|
||||
};
|
||||
/**
|
||||
* 延时运行任务
|
||||
* @param func 任务
|
||||
* @param time 延时时间
|
||||
*/
|
||||
exports.later = function (func, time) {
|
||||
return exports.create(func).runTaskLater(plugin, time);
|
||||
};
|
||||
/**
|
||||
* 运行循环任务
|
||||
* @constructor (任务,执行间隔).
|
||||
* @constructor (任务,首次延时,执行间隔)
|
||||
*/
|
||||
exports.timer = function () {
|
||||
switch (arguments.length) {
|
||||
case 2:
|
||||
return exports.create(arguments[0]).runTaskTimer(plugin, 0, arguments[1]);
|
||||
case 3:
|
||||
return exports.create(arguments[0]).runTaskTimer(plugin, arguments[1], arguments[2]);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 运行异步任务
|
||||
* @param func function 任务
|
||||
*/
|
||||
exports.async = function (func) {
|
||||
return exports.create(func).runTaskAsynchronously(plugin);
|
||||
};
|
||||
/**
|
||||
* 延时运行异步任务
|
||||
* @param func 任务
|
||||
* @param time 延时时间
|
||||
*/
|
||||
exports.laterAsync = function (func, time) {
|
||||
return exports.create(func).runTaskLaterAsynchronously(plugin, time);
|
||||
};
|
||||
/**
|
||||
* 运行异步循环任务
|
||||
* @constructor (任务,执行间隔).
|
||||
* @constructor (任务,首次延时,执行间隔)
|
||||
*/
|
||||
exports.timerAsync = function () {
|
||||
switch (arguments.length) {
|
||||
case 2:
|
||||
return exports.create(arguments[0]).runTaskTimerAsynchronously(plugin, 0, arguments[1]);
|
||||
case 3:
|
||||
return exports.create(arguments[0]).runTaskTimerAsynchronously(plugin, arguments[1], arguments[2]);
|
||||
}
|
||||
};
|
@ -1,93 +1 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Bukkit 命令相关类
|
||||
*/
|
||||
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
var plugin = base.plugin;
|
||||
var ref = require('core/reflect');
|
||||
var bukkit = require('./bukkit');
|
||||
var commandMap = ref.on(bukkit.plugin.manager).get('commandMap').get();
|
||||
var PluginCommand = Java.type('org.bukkit.command.PluginCommand');
|
||||
|
||||
var StringUtil = Java.type('org.bukkit.util.StringUtil');
|
||||
|
||||
var ArrayList = Java.type('java.util.ArrayList');
|
||||
var Arrays = Java.type('java.util.Arrays');
|
||||
|
||||
function enable(jsp) {
|
||||
var commands = jsp.description.commands;
|
||||
if (commands) {
|
||||
var pluginCmds = [];
|
||||
for (var name in commands) {
|
||||
var command = commands[name];
|
||||
if (typeof command !== 'object') continue;
|
||||
var newCmd = create(jsp, name);
|
||||
if (command.description) newCmd.setDescription(command.description);
|
||||
if (command.usage) newCmd.setUsage(command.usage);
|
||||
if (command.aliases) newCmd.setAliases(Arrays.asList(command.aliases));
|
||||
if (command.permission) newCmd.setPermission(command.permission);
|
||||
if (command['permission-message']) newCmd.setPermissionMessage(command['permission-message']);
|
||||
pluginCmds.push(newCmd);
|
||||
console.debug('插件 %s 注册命令 %s ...', jsp.description.name, name);
|
||||
}
|
||||
commandMap.registerAll(jsp.description.name, Arrays.asList(pluginCmds));
|
||||
}
|
||||
}
|
||||
|
||||
function get(name) {
|
||||
return commandMap.getCommand(name);
|
||||
}
|
||||
|
||||
function create(jsp, name) {
|
||||
return register(jsp, ref.on(PluginCommand).create(name, plugin).get());
|
||||
}
|
||||
|
||||
function register(jsp, cmd) {
|
||||
commandMap.register(jsp.description.name, cmd);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
// var exec = {
|
||||
// cmd: function (sender, command, args) {
|
||||
//
|
||||
// },
|
||||
// tab: function (sender, command, args) {
|
||||
//
|
||||
// }
|
||||
// };
|
||||
|
||||
function on(jsp, name, exec) {
|
||||
var c = get(name) || create(jsp, name);
|
||||
console.debug('插件 %s 设置命令 %s(%s) 执行器 ...', jsp.description.name, name, c);
|
||||
if (exec.cmd) {
|
||||
c.setExecutor(function (sender, cmd, command, args) {
|
||||
try {
|
||||
return exec.cmd(sender, command, args);
|
||||
} catch (ex) {
|
||||
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6命令时发生异常 §4%s', sender.name, jsp.description.name, command, Java.from(args).join(' '), ex);
|
||||
console.ex(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (exec.tab) {
|
||||
c.setTabCompleter(function (sender, cmd, command, args) {
|
||||
try {
|
||||
var completions = new ArrayList();
|
||||
var token = args[args.length - 1];
|
||||
StringUtil.copyPartialMatches(token, Arrays.asList(exec.tab(sender, command, args)), completions);
|
||||
return completions;
|
||||
} catch (ex) {
|
||||
console.console('§6玩家 §a%s §6执行 §b%s §6插件 §d%s %s §6补全时发生异常 §4%s', sender.name, jsp.description.name, command, Java.from(args).join(' '), ex);
|
||||
console.ex(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.enable = enable;
|
||||
|
||||
exports.on = on;
|
||||
exports.off = function () {
|
||||
|
||||
};
|
||||
module.exports = require('./bukkit/command');
|
@ -1,158 +1 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Bukkit 事件相关类
|
||||
*/
|
||||
/*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 HandlerList = Java.type('org.bukkit.event.HandlerList');
|
||||
var EventPriority = Java.type("org.bukkit.event.EventPriority");
|
||||
var EventExecutor = Java.type("org.bukkit.plugin.EventExecutor");
|
||||
var IllegalStateException = Java.type("java.lang.IllegalStateException");
|
||||
|
||||
var plugin = base.plugin;
|
||||
|
||||
var ref = require('reflect');
|
||||
|
||||
var listenerMap = [];
|
||||
|
||||
/**
|
||||
* 扫描包 org.bukkit.event 下的所有事件
|
||||
* 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent
|
||||
*/
|
||||
function mapEventName() {
|
||||
var eventPackageDir = "org/bukkit/event";
|
||||
var count = 0;
|
||||
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;
|
||||
// 以 org/bukkit/event 开头 并且以 .class 结尾
|
||||
if (name.startsWith(eventPackageDir) && name.endsWith(".class")) {
|
||||
var i = name.replaceAll('/', '.');
|
||||
try {
|
||||
var clz = base.getClass(i.substring(0, i.length - 6));
|
||||
// 继承于 org.bukkit.event.Event 访问符为Public
|
||||
if (isVaildEvent(clz)) {
|
||||
// noinspection JSUnresolvedVariable
|
||||
var simpleName = clz.simpleName.toLowerCase();
|
||||
console.debug("Mapping Event [%s] => %s", clz.name, simpleName);
|
||||
mapEvent[simpleName] = clz;
|
||||
count++;
|
||||
}
|
||||
} catch (ex) {
|
||||
//ignore already loaded class
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为一个有效的事件类
|
||||
* @param clz
|
||||
* @returns {*|boolean}
|
||||
*/
|
||||
function isVaildEvent(clz) {
|
||||
// noinspection JSUnresolvedVariable 继承于 org.bukkit.event.Event
|
||||
return BukkitEvent.class.isAssignableFrom(clz) &&
|
||||
// 访问符为Public
|
||||
Modifier.isPublic(clz.getModifiers()) &&
|
||||
// 不是抽象类
|
||||
!Modifier.isAbstract(clz.getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加事件监听
|
||||
* @param jsp
|
||||
* @param event
|
||||
* @param exec {function}
|
||||
* @param priority
|
||||
* @param ignoreCancel
|
||||
*/
|
||||
function listen(jsp, event, exec, priority, ignoreCancel) {
|
||||
var name = jsp.description.name;
|
||||
if (ext.isNull(name)) throw new TypeError('插件名称为空 请检查传入参数!');
|
||||
var eventCls = mapEvent[event] || mapEvent[event.toLowerCase()] || mapEvent[event + 'Event'] || mapEvent[event.toLowerCase() + 'event'];
|
||||
if (!eventCls) {
|
||||
try {
|
||||
eventCls = base.getClass(eventCls);
|
||||
} catch (ex) {
|
||||
console.warn("事件 %s 未找到!", event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (typeof priority === 'boolean') {
|
||||
ignoreCancel = priority
|
||||
}
|
||||
priority = priority || 'NORMAL';
|
||||
ignoreCancel = ignoreCancel || false;
|
||||
var listener = new 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 EventExecutor({
|
||||
execute: function (listener, event) {
|
||||
try {
|
||||
exec(event);
|
||||
} catch (ex) {
|
||||
console.console('§6插件 §b%s §6处理 §d%s §6事件时发生异常 §4%s', name, event.class.simpleName, ex);
|
||||
console.ex(ex);
|
||||
}
|
||||
}
|
||||
}),
|
||||
plugin,
|
||||
ignoreCancel);
|
||||
// 添加到缓存 用于关闭插件的时候关闭事件
|
||||
if (!listenerMap[name]) listenerMap[name] = []
|
||||
var listeners = listenerMap[name];
|
||||
var off = {
|
||||
event: eventCls,
|
||||
listener: listener,
|
||||
off: function () {
|
||||
ref.on(this.event).call('getHandlerList').get().unregister(this.listener);
|
||||
console.debug('插件 %s 注销事件 %s', name, this.event.simpleName);
|
||||
}
|
||||
}
|
||||
listeners.push(off);
|
||||
// noinspection JSUnresolvedVariable
|
||||
console.debug('插件 %s 注册事件 %s 方法 %s', name, eventCls.simpleName, exec.name === '' ? '匿名方法' : exec.name);
|
||||
return off;
|
||||
}
|
||||
|
||||
var mapEvent = [];
|
||||
// 映射事件名称
|
||||
console.info('Bukkit 事件映射完毕 共计 %s 个事件!', mapEventName().toFixed(0));
|
||||
|
||||
module.exports = {
|
||||
on: listen,
|
||||
disable: function (jsp) {
|
||||
var jspl = listenerMap[jsp.description.name];
|
||||
if (jspl) {
|
||||
jspl.forEach(function (t) t.off());
|
||||
delete listenerMap[jsp.description.name];
|
||||
}
|
||||
}
|
||||
};
|
||||
module.exports = require('./bukkit/event');
|
@ -1,48 +1 @@
|
||||
'use strict';
|
||||
/**
|
||||
* Bukkit 权限相关类
|
||||
*/
|
||||
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
var manager = require('./bukkit').plugin.manager;
|
||||
|
||||
/**
|
||||
* Permission(String name, String description)
|
||||
*/
|
||||
var Permission = Java.type("org.bukkit.permissions.Permission");
|
||||
var PermissionDefault = Java.type('org.bukkit.permissions.PermissionDefault');
|
||||
|
||||
function enable(plugin) {
|
||||
var permissions = plugin.description.permissions;
|
||||
if (permissions) {
|
||||
for (var name in permissions) {
|
||||
var permission = permissions[name];
|
||||
if (typeof permission !== 'object') continue;
|
||||
var desc = permission.description;
|
||||
var def = permission.default || 'OP';
|
||||
try {
|
||||
manager.addPermission(new Permission(name, desc, PermissionDefault.getByName(def)));
|
||||
} catch (ex) {
|
||||
// ignore eg: java.lang.IllegalArgumentException: The permission xxxxxx.default is already defined!
|
||||
}
|
||||
console.debug('插件 %s 注册权限 %s Default %s ...', plugin.description.name, name, def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function disable(plugin) {
|
||||
var permissions = plugin.description.permissions;
|
||||
if (permissions) {
|
||||
for (var name in permissions) {
|
||||
try {
|
||||
manager.removePermission(name);
|
||||
} catch (ex) {
|
||||
// ignore eg: java.lang.IllegalArgumentException: The permission xxxxxx.default is already defined!
|
||||
}
|
||||
console.debug('插件 %s 注销权限 %s ...', plugin.description.name, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.enable = enable;
|
||||
exports.disable = disable;
|
||||
module.exports = require('./bukkit/permission');
|
@ -1,258 +1 @@
|
||||
'use strict';
|
||||
/**
|
||||
* MiaoScript脚本插件加载类
|
||||
*/
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
// var zip = require("core/zip");
|
||||
var fs = require('core/fs');
|
||||
var yaml = require('modules/yaml');
|
||||
var event = require('modules/event');
|
||||
var bukkit = require('./bukkit');
|
||||
var command = require('./command');
|
||||
var permission = require('./permission');
|
||||
|
||||
/**
|
||||
* 载入插件
|
||||
* @param path
|
||||
*/
|
||||
function loadPlugins(dir) {
|
||||
var plugin = fs.file(root, dir);
|
||||
if (!plugin) {
|
||||
console.info("首次加载 创建文件夹 %s ...", plugin);
|
||||
} else {
|
||||
console.info("开始扫描 %s 下的插件 ...", plugin);
|
||||
createUpdate(plugin);
|
||||
var files = [];
|
||||
fs.list(plugin).forEach(function (file) {
|
||||
files.push(file.toFile());
|
||||
});
|
||||
loadZipPlugins(files);
|
||||
loadJsPlugins(files);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新插件
|
||||
* @param path
|
||||
*/
|
||||
function createUpdate(path) {
|
||||
var update = fs.file(path, "update");
|
||||
if (!update.exists()) {
|
||||
update.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ZIP类型插件预加载
|
||||
* @param files
|
||||
*/
|
||||
function loadZipPlugins(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 loadJsPlugins(files) {
|
||||
files.filter(function (file) {
|
||||
return file.name.endsWith(".js")
|
||||
}).forEach(function (file) {
|
||||
loadPlugin(file);
|
||||
})
|
||||
}
|
||||
|
||||
function loadPlugin(file) {
|
||||
var update = fs.file(fs.file(file.parentFile, 'update'), file.name);
|
||||
if (update.exists()) {
|
||||
console.info('自动升级插件 %s', file.name);
|
||||
fs.move(update, file, true);
|
||||
}
|
||||
var plugin = require(file, {
|
||||
cache: false,
|
||||
hook: function (origin) {
|
||||
return beforeLoadHook(origin);
|
||||
}
|
||||
});
|
||||
console.debug("插件编译结果: %s", plugin.toJson());
|
||||
var desc = plugin.description;
|
||||
if (!desc || !desc.name) {
|
||||
console.warn("文件 %s 不存在 description 描述信息 无法加载插件!", file);
|
||||
} else {
|
||||
initPlugin(file, plugin);
|
||||
afterLoadHook(plugin);
|
||||
plugins.push(plugin);
|
||||
plugins[plugin.description.name] = plugin;
|
||||
console.info('载入插件 %s 版本 %s By %s', desc.name, desc.version || '未知', desc.author || '未知');
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
|
||||
function beforeLoadHook(origin) {
|
||||
var result = origin;
|
||||
// 处理 event 为了不影响 正常逻辑 event 还是手动require吧
|
||||
// result = result + 'var event = {}; module.exports.event = event;';
|
||||
// 注入 console 对象 // 给插件注入单独的 console
|
||||
result = result + 'var console = new Console(); module.exports.console = console;';
|
||||
// 插件注入 self 对象
|
||||
result = result + 'var self = {}; module.exports.self = self;';
|
||||
return result;
|
||||
}
|
||||
|
||||
function afterLoadHook(plugin) {
|
||||
// plugin.event.on = event.on.bind(plugin);
|
||||
// 给 console 添加插件名称
|
||||
plugin.console.name = plugin.description.name;
|
||||
// 赋值 self
|
||||
for (var i in plugin) {
|
||||
plugin.self[i] = plugin[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化插件内容(提供config,__DATA__等参数)
|
||||
*/
|
||||
function initPlugin(file, plugin) {
|
||||
// 初始化 __FILE__
|
||||
plugin.__FILE__ = file;
|
||||
// 初始化 __DATA__
|
||||
plugin.__DATA__ = fs.file(file.parentFile, plugin.description.name);
|
||||
// 初始化 getDataFolder()
|
||||
plugin.getDataFolder = function () {
|
||||
return plugin.__DATA__;
|
||||
};
|
||||
// 初始化 getFile()
|
||||
plugin.getFile = function (name) {
|
||||
return fs.file(plugin.getDataFolder(), name);
|
||||
};
|
||||
|
||||
// 初始化插件配置相关方法
|
||||
initPluginConfig(plugin);
|
||||
|
||||
command.enable(plugin);
|
||||
permission.enable(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化插件配置
|
||||
*/
|
||||
function initPluginConfig(plugin) {
|
||||
// 初始化 config
|
||||
plugin.configFile = plugin.getFile('config.yml');
|
||||
/**
|
||||
* 获取配置文件
|
||||
* @constructor
|
||||
* @constructor (file|string)
|
||||
*/
|
||||
plugin.getConfig = function () {
|
||||
switch (arguments.length) {
|
||||
case 0:
|
||||
return plugin.config;
|
||||
case 1:
|
||||
var file = arguments[0];
|
||||
if (!file.isFile) {
|
||||
file = plugin.getFile(file);
|
||||
}
|
||||
return yaml.safeLoad(base.read(file));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 重载配置文件
|
||||
* @constructor
|
||||
* @constructor (file|string)
|
||||
*/
|
||||
plugin.reloadConfig = function () {
|
||||
plugin.config = plugin.getConfig(plugin.configFile);
|
||||
};
|
||||
/**
|
||||
* 保存配置文件
|
||||
* @constructor
|
||||
* @constructor (file, content)
|
||||
*/
|
||||
plugin.saveConfig = function () {
|
||||
switch (arguments.length) {
|
||||
case 0:
|
||||
plugin.configFile.parentFile.mkdirs();
|
||||
base.save(plugin.configFile, plugin.config.toYaml());
|
||||
break;
|
||||
case 2:
|
||||
base.save(arguments[0], arguments[1].toYaml());
|
||||
break;
|
||||
}
|
||||
};
|
||||
if (plugin.configFile.isFile()) {
|
||||
plugin.config = plugin.getConfig('config.yml');
|
||||
} else if (plugin.description.config) {
|
||||
plugin.config = plugin.description.config;
|
||||
plugin.saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
function runAndCatch(jsp, exec, ext) {
|
||||
if (exec) {
|
||||
try {
|
||||
// 绑定方法的this到插件自身
|
||||
exec.bind(jsp)();
|
||||
if (ext) {
|
||||
ext();
|
||||
}
|
||||
} catch (ex) {
|
||||
console.console('§6插件 §b%s §6执行 §d%s §6方法时发生错误 §4%s', jsp.description.name, exec.name, ex.message);
|
||||
console.ex(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkAndGet(args) {
|
||||
if (args.length === 0) {
|
||||
return plugins;
|
||||
}
|
||||
var name = args[0];
|
||||
// 如果是插件 则直接返回
|
||||
if (name.description) {
|
||||
return [name];
|
||||
}
|
||||
if (!exports.plugins[name]) {
|
||||
throw new Error("插件 " + name + " 不存在!");
|
||||
}
|
||||
return [exports.plugins[name]];
|
||||
}
|
||||
|
||||
var plugins = [];
|
||||
|
||||
exports.$ = undefined;
|
||||
exports.plugins = plugins;
|
||||
exports.init = function (plugin, path) {
|
||||
if (plugin !== null) {
|
||||
// 如果过plugin不等于null 则代表是正式环境
|
||||
exports.$ = plugin;
|
||||
console.info("初始化 MiaoScript 插件系统 版本: %s", plugin.description.version);
|
||||
}
|
||||
loadPlugins(path);
|
||||
};
|
||||
exports.load = function () {
|
||||
checkAndGet(arguments).forEach(function (p) runAndCatch(p, p.load));
|
||||
};
|
||||
exports.enable = function () {
|
||||
checkAndGet(arguments).forEach(function (p) runAndCatch(p, p.enable));
|
||||
};
|
||||
exports.disable = function () {
|
||||
checkAndGet(arguments).forEach(function (p) runAndCatch(p, p.disable, function () {
|
||||
event.disable(p);
|
||||
// task.cancel();
|
||||
}));
|
||||
};
|
||||
exports.reload = function () {
|
||||
checkAndGet(arguments).forEach(function (p) {
|
||||
exports.disable(p);
|
||||
p = loadPlugin(p.__FILE__);
|
||||
exports.load(p);
|
||||
exports.enable(p);
|
||||
});
|
||||
};
|
||||
module.exports = require('./bukkit/plugin');
|
1
src/main/resources/modules/server.js
Normal file
1
src/main/resources/modules/server.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('./bukkit/server');
|
@ -1,71 +1 @@
|
||||
'use strict';
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
/**
|
||||
* 任务计划
|
||||
* Created by 蒋天蓓 on 2017/2/9 0009.
|
||||
*/
|
||||
var plugin = base.plugin;
|
||||
var BukkitRunnable = Java.type("org.bukkit.scheduler.BukkitRunnable");
|
||||
/**
|
||||
* 创建任务对象
|
||||
* @param func 任务
|
||||
*/
|
||||
exports.create = function (func) {
|
||||
return new BukkitRunnable(func);
|
||||
};
|
||||
/**
|
||||
* 运行任务
|
||||
* @param func 任务
|
||||
*/
|
||||
exports.run = function (func) {
|
||||
return exports.create(func).runTask(plugin);
|
||||
};
|
||||
/**
|
||||
* 延时运行任务
|
||||
* @param func 任务
|
||||
* @param time 延时时间
|
||||
*/
|
||||
exports.later = function (func, time) {
|
||||
return exports.create(func).runTaskLater(plugin, time);
|
||||
};
|
||||
/**
|
||||
* 运行循环任务
|
||||
* @constructor (任务,执行间隔).
|
||||
* @constructor (任务,首次延时,执行间隔)
|
||||
*/
|
||||
exports.timer = function () {
|
||||
switch (arguments.length) {
|
||||
case 2:
|
||||
return exports.create(arguments[0]).runTaskTimer(plugin, 0, arguments[1]);
|
||||
case 3:
|
||||
return exports.create(arguments[0]).runTaskTimer(plugin, arguments[1], arguments[2]);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 运行异步任务
|
||||
* @param func function 任务
|
||||
*/
|
||||
exports.async = function (func) {
|
||||
return exports.create(func).runTaskAsynchronously(plugin);
|
||||
};
|
||||
/**
|
||||
* 延时运行异步任务
|
||||
* @param func 任务
|
||||
* @param time 延时时间
|
||||
*/
|
||||
exports.laterAsync = function (func, time) {
|
||||
return exports.create(func).runTaskLaterAsynchronously(plugin, time);
|
||||
};
|
||||
/**
|
||||
* 运行异步循环任务
|
||||
* @constructor (任务,执行间隔).
|
||||
* @constructor (任务,首次延时,执行间隔)
|
||||
*/
|
||||
exports.timerAsync = function () {
|
||||
switch (arguments.length) {
|
||||
case 2:
|
||||
return exports.create(arguments[0]).runTaskTimerAsynchronously(plugin, 0, arguments[1]);
|
||||
case 3:
|
||||
return exports.create(arguments[0]).runTaskTimerAsynchronously(plugin, arguments[1], arguments[2]);
|
||||
}
|
||||
};
|
||||
module.exports = require('./bukkit/task');
|
@ -7,7 +7,7 @@
|
||||
|
||||
var fs = require('core/fs');
|
||||
var event = require('modules/event');
|
||||
var bukkit = require('modules/bukkit');
|
||||
var bukkit = require('modules/server');
|
||||
var command = require('modules/command');
|
||||
|
||||
var papi = require('./ext/papi');
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
/*global Java, base, module, exports, require, __FILE__*/
|
||||
var PlaceholderAPI;
|
||||
var bukkit = require('modules/bukkit');
|
||||
var bukkit = require('modules/server');
|
||||
if (bukkit.plugin.load("PlaceholderAPI")) {
|
||||
PlaceholderAPI = ext.getStatic("me.clip.placeholderapi.PlaceholderAPI");
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user